From: Nick Renieris
Used a technique similar to lavc/tdsc.c for invoking the MJPEG decoder.
This commit adds support for:
- DNG tiles
- DNG tile huffman lossless JPEG decoding
- DNG 8-bpp ("packed" as dcraw calls it) decoding
- DNG color scaling [1]
- LinearizationTable tag
- BlackLevel tag
[1]: As specified in the DNG Specification - Chapter 5
Signed-off-by: Nick Renieris
---
libavcodec/tiff.c | 326 +-
libavcodec/tiff.h | 2 +
2 files changed, 321 insertions(+), 7 deletions(-)
diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c
index c520d7df83..423eaf0647 100644
--- a/libavcodec/tiff.c
+++ b/libavcodec/tiff.c
@@ -46,6 +46,7 @@
#include "mathops.h"
#include "tiff.h"
#include "tiff_data.h"
+#include "mjpegdec.h"
#include "thread.h"
#include "get_bits.h"
@@ -54,6 +55,10 @@ typedef struct TiffContext {
AVCodecContext *avctx;
GetByteContext gb;
+/* JPEG decoding for DNG */
+AVCodecContext *avctx_mjpeg; // wrapper context for MJPEG
+AVFrame *jpgframe; // decoded JPEG tile
+
int get_subimage;
uint16_t get_page;
int get_thumbnail;
@@ -76,7 +81,9 @@ typedef struct TiffContext {
int is_bayer;
uint8_t pattern[4];
+unsigned black_level;
unsigned white_level;
+const uint16_t *dng_lut; // Pointer to DNG linearization table
uint32_t sub_ifd;
uint16_t cur_page;
@@ -86,6 +93,14 @@ typedef struct TiffContext {
int stripsizesoff, stripsize, stripoff, strippos;
LZWState *lzw;
+/* Tile support */
+int is_tiled;
+int tile_byte_counts_offset, tile_offsets_offset;
+int tile_width, tile_length;
+int tile_count;
+
+int is_jpeg; // 0 - Not JPEG, 1 - JPEG, 2 - New JPEG
+
uint8_t *deinvert_buf;
int deinvert_buf_size;
uint8_t *yuv_line;
@@ -257,11 +272,27 @@ static int add_metadata(int count, int type,
};
}
+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);
+
static void av_always_inline horizontal_fill(TiffContext *s,
unsigned int bpp, uint8_t* dst,
int usePtr, const uint8_t *src,
uint8_t c, int width, int offset)
{
+/* Handle DNG images with uncompressed strips (non-tiled) */
+if (s->tiff_type == TIFF_TYPE_DNG || s->tiff_type == TIFF_TYPE_CINEMADNG) {
+dng_blit(s,
+ dst + offset,
+ width,
+ src,
+ width,
+ width,
+ 1,
+ 0);
+return;
+}
+
switch (bpp) {
case 1:
while (--width >= 0) {
@@ -712,6 +743,203 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p,
uint8_t *dst, int strid
return 0;
}
+/**
+ * Map stored raw sensor values into linear reference values.
+ * See: DNG Specification - Chapter 5
+ */
+static uint16_t av_always_inline dng_raw_to_linear16(uint16_t value,
+const uint16_t *lut,
+uint16_t black_level,
+float scale_factor) {
+// Lookup table lookup
+if (lut) value = lut[value];
+
+// Black level subtraction
+value = av_clip_uint16_c((unsigned)value - black_level);
+
+// Color scaling
+value = av_clip_uint16_c((unsigned)(((float)value * scale_factor) *
0x));
+
+return value;
+}
+
+static uint16_t av_always_inline dng_raw_to_linear8(uint16_t value,
+const uint16_t *lut,
+uint16_t black_level,
+float scale_factor) {
+return dng_raw_to_linear16(value, lut, black_level, scale_factor) >> 8;
+}
+
+static void dng_blit(TiffContext *s, uint8_t *dst, int dst_stride,
+ const uint8_t *src, int src_stride,
+ int width, int height, int is_u16)
+{
+int line, col;
+float scale_factor;
+
+scale_factor = 1.0 / (s->white_level - s->black_level);
+
+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_raw_to_linear16(*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_raw_to_linear8(*src++, s->dng_lut,
s->black_level, scale_factor);
+
+