Commit 31acdf43 authored by Nick Renieris's avatar Nick Renieris Committed by Paul B Mahol

lavc/tiff: Support decoding of DNGs with single-component JPEGs

This enables decoding of DNG images generated by the 'DJI Zenmuse X7'
digital camera
Samples: https://www.dji.com/gr/zenmuse-x7/info#downloadsSigned-off-by: 's avatarNick Renieris <velocityra@gmail.com>
parent a75a9e8f
...@@ -274,7 +274,8 @@ static int add_metadata(int count, int type, ...@@ -274,7 +274,8 @@ static int add_metadata(int count, int type,
} }
static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, static void av_always_inline dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
const uint8_t *src, int src_stride, int width, int height, int is_u16); const uint8_t *src, int src_stride, int width, int height,
int is_single_comp, int is_u16);
static void av_always_inline horizontal_fill(TiffContext *s, static void av_always_inline horizontal_fill(TiffContext *s,
unsigned int bpp, uint8_t* dst, unsigned int bpp, uint8_t* dst,
...@@ -698,6 +699,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid ...@@ -698,6 +699,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid
0, // no stride, only 1 line 0, // no stride, only 1 line
width / pixel_size_bytes * pixel_size_bits / s->bpp * s->bppcount, // need to account for [1, 16] bpp width / pixel_size_bytes * pixel_size_bits / s->bpp * s->bppcount, // need to account for [1, 16] bpp
1, 1,
0, // single-component variation is only preset in JPEG-encoded DNGs
is_u16); is_u16);
} }
...@@ -795,18 +797,32 @@ static uint16_t av_always_inline dng_process_color8(uint16_t value, ...@@ -795,18 +797,32 @@ static uint16_t av_always_inline dng_process_color8(uint16_t value,
static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
const uint8_t *src, int src_stride, const uint8_t *src, int src_stride,
int width, int height, int is_u16) int width, int height, int is_single_comp, int is_u16)
{ {
int line, col; int line, col;
float scale_factor; float scale_factor;
scale_factor = 1.0f / (s->white_level - s->black_level); scale_factor = 1.0f / (s->white_level - s->black_level);
if (is_u16) { if (is_single_comp) {
for (line = 0; line < height; line++) { if (!is_u16)
return; /* <= 8bpp unsupported */
/* Image is double the width and half the height we need, each row comprises 2 rows of the output
(split vertically in the middle). */
for (line = 0; line < height / 2; line++) {
uint16_t *dst_u16 = (uint16_t *)dst; uint16_t *dst_u16 = (uint16_t *)dst;
uint16_t *src_u16 = (uint16_t *)src; uint16_t *src_u16 = (uint16_t *)src;
/* Blit first half of input row row to initial row of output */
for (col = 0; col < width; col++)
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
/* Advance the destination pointer by a row (source pointer remains in the same place) */
dst += dst_stride * sizeof(uint16_t);
dst_u16 = (uint16_t *)dst;
/* Blit second half of input row row to next row of output */
for (col = 0; col < width; col++) for (col = 0; col < width; col++)
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor); *dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
...@@ -814,12 +830,27 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride, ...@@ -814,12 +830,27 @@ static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
src += src_stride * sizeof(uint16_t); src += src_stride * sizeof(uint16_t);
} }
} else { } else {
for (line = 0; line < height; line++) { /* Input and output image are the same size and the MJpeg decoder has done per-component
for (col = 0; col < width; col++) deinterleaving, so blitting here is straightforward. */
*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor); if (is_u16) {
for (line = 0; line < height; line++) {
uint16_t *dst_u16 = (uint16_t *)dst;
uint16_t *src_u16 = (uint16_t *)src;
for (col = 0; col < width; col++)
*dst_u16++ = dng_process_color16(*src_u16++, s->dng_lut, s->black_level, scale_factor);
dst += dst_stride * sizeof(uint16_t);
src += src_stride * sizeof(uint16_t);
}
} else {
for (line = 0; line < height; line++) {
for (col = 0; col < width; col++)
*dst++ = dng_process_color8(*src++, s->dng_lut, s->black_level, scale_factor);
dst += dst_stride; dst += dst_stride;
src += src_stride; src += src_stride;
}
} }
} }
} }
...@@ -831,7 +862,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, ...@@ -831,7 +862,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame,
AVPacket jpkt; AVPacket jpkt;
uint8_t *dst_data, *src_data; uint8_t *dst_data, *src_data;
uint32_t dst_offset; /* offset from dst buffer in pixels */ uint32_t dst_offset; /* offset from dst buffer in pixels */
int is_u16, pixel_size; int is_single_comp, is_u16, pixel_size;
int ret; int ret;
/* Prepare a packet and send to the MJPEG decoder */ /* Prepare a packet and send to the MJPEG decoder */
...@@ -865,9 +896,18 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, ...@@ -865,9 +896,18 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame,
/* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */ /* Copy the outputted tile's pixels from 'jpgframe' to 'frame' (final buffer) */
/* See dng_blit for explanation */
is_single_comp = (s->avctx_mjpeg->width == w * 2 && s->avctx_mjpeg->height == h / 2);
is_u16 = (s->bpp > 8); is_u16 = (s->bpp > 8);
pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t)); pixel_size = (is_u16 ? sizeof(uint16_t) : sizeof(uint8_t));
if (is_single_comp && !is_u16) {
av_log(s->avctx, AV_LOG_ERROR, "DNGs with bpp <= 8 and 1 component are unsupported\n");
av_frame_unref(s->jpgframe);
return AVERROR_PATCHWELCOME;
}
dst_offset = x + frame->linesize[0] * y / pixel_size; dst_offset = x + frame->linesize[0] * y / pixel_size;
dst_data = frame->data[0] + dst_offset * pixel_size; dst_data = frame->data[0] + dst_offset * pixel_size;
src_data = s->jpgframe->data[0]; src_data = s->jpgframe->data[0];
...@@ -879,6 +919,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame, ...@@ -879,6 +919,7 @@ static int dng_decode_jpeg_tile(AVCodecContext *avctx, AVFrame *frame,
s->jpgframe->linesize[0] / pixel_size, s->jpgframe->linesize[0] / pixel_size,
w, w,
h, h,
is_single_comp,
is_u16); is_u16);
av_frame_unref(s->jpgframe); av_frame_unref(s->jpgframe);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment