# HG changeset patch # User Matti Hamalainen # Date 1481099858 -7200 # Node ID bbd61622856aa2643f7a5b001e57e7582e5abe63 # Parent ffcd1967fb5cee1aa85aee4a7df805ea801a3567 Initial implementation of TIFF format read support via libtiff. diff -r ffcd1967fb5c -r bbd61622856a Makefile --- a/Makefile Wed Dec 07 10:35:38 2016 +0200 +++ b/Makefile Wed Dec 07 10:37:38 2016 +0200 @@ -48,9 +48,12 @@ LIBJPEG_CFLAGS:=$(shell pkg-config --cflags libjpeg) LIBJPEG_LDFLAGS:=$(shell pkg-config --libs libjpeg) +LIBTIFF_CFLAGS:=$(shell pkg-config --cflags libtiff-4) +LIBTIFF_LDFLAGS:=$(shell pkg-config --libs libtiff-4) + CFLAGS:=-Os -Wall -MMD -fno-asynchronous-unwind-tables -fdata-sections -ffunction-sections -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -fomit-frame-pointer CFLAGS+=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_REENTRANT -CFLAGS+=-I. $(LIBSDL_CFLAGS) $(LIBPNG_CFLAGS) $(LIBJPEG_CFLAGS) +CFLAGS+=-I. $(LIBSDL_CFLAGS) $(LIBPNG_CFLAGS) $(LIBJPEG_CFLAGS) $(LIBTIFF_CFLAGS) CFLAGS+=-DCONFIG_BPG_VERSION=\"$(shell cat VERSION)\" ifdef USE_JCTVC_HIGH_BIT_DEPTH CFLAGS+=-DRExt__HIGH_BIT_DEPTH_SUPPORT @@ -190,7 +193,7 @@ LIBS+=-lm -lpthread BPGDEC_LIBS:=$(LIBPNG_LDFLAGS) $(LIBS) -BPGENC_LIBS+=$(LIBPNG_LDFLAGS) $(LIBJPEG_LDFLAGS) $(LIBS) +BPGENC_LIBS+=$(LIBPNG_LDFLAGS) $(LIBJPEG_LDFLAGS) $(LIBTIFF_LDFLAGS) $(LIBS) BPGVIEW_LIBS:=$(LIBSDL_LDFLAGS) $(LIBS) endif #!CONFIG_WIN32 diff -r ffcd1967fb5c -r bbd61622856a bpgenc.c --- a/bpgenc.c Wed Dec 07 10:35:38 2016 +0200 +++ b/bpgenc.c Wed Dec 07 10:37:38 2016 +0200 @@ -31,6 +31,7 @@ #include #include +#include #include "bpgenc.h" @@ -908,6 +909,93 @@ } } +Image *read_tiff(BPGMetaData **pmd, const char *filename, + BPGColorSpaceEnum color_space, int out_bit_depth, + int limited_range, int premultiplied_alpha) +{ + TIFF *tif; + Image *img = NULL; + BPGImageFormatEnum img_format; + uint8_t *buf = NULL; + uint32_t img_width, img_height; + int img_alpha, img_bpp; + size_t img_linesize; + uint16_t img_depth, img_spp, img_sfmt, img_pconfig; + ColorConvertState cvt; + RGBConvertFunc *convert_func; + + *pmd = NULL; + + // Open and read TIFF header etc. + if ((tif = TIFFOpen(filename, "rb")) == NULL) + return NULL; + + TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &img_width); + TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &img_height); + TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &img_spp); + TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &img_depth); + TIFFGetField(tif, TIFFTAG_SAMPLEFORMAT, &img_sfmt); + TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &img_pconfig); + + // Check basics + if ((img_depth != 8 && img_depth != 16) || img_spp > 4) + goto err; + + img_linesize = TIFFScanlineSize(tif); + img_format = BPG_FORMAT_444; + img_bpp = sizeof(uint32_t) * img_depth / 8; + + if (img_spp > 3) + { + uint16_t img_esmp, *img_esmp_types; + + TIFFGetField(tif, TIFFTAG_EXTRASAMPLES, &img_esmp, &img_esmp_types); + img_alpha = img_esmp == 1 && img_esmp_types[0] == EXTRASAMPLE_UNASSALPHA; + } + else + img_alpha = 0; + + // Allocate temporary image space + buf = (uint8_t *) _TIFFmalloc(img_linesize * img_spp); + if (buf == NULL) + goto err; + + // Allocate target image + img = image_alloc(img_width, img_height, img_format, img_alpha, color_space, out_bit_depth); + if (img == NULL) + goto err; + + img->limited_range = limited_range; + img->premultiplied_alpha = premultiplied_alpha; + + convert_init(&cvt, img_depth, out_bit_depth, color_space, limited_range); + + int idx = img_depth == 16; + convert_func = rgb_to_cs[idx][color_space]; + + for (int y = 0; y < img->h; y++) + { + // Read TIFF image to raster + if (!TIFFReadScanline(tif, buf, y, 0)) + goto err; + + // Convert + convert_func(&cvt, + (PIXEL *)(img->data[0] + y * img->linesize[0]), + (PIXEL *)(img->data[1] + y * img->linesize[1]), + (PIXEL *)(img->data[2] + y * img->linesize[2]), + buf, img->w, img_spp); + } + + +err: + if (buf != NULL) + _TIFFfree(buf); + + TIFFClose(tif); + return img; +} + Image *read_png(BPGMetaData **pmd, FILE *f, BPGColorSpaceEnum color_space, int out_bit_depth, int limited_range, int premultiplied_alpha) @@ -1420,6 +1508,10 @@ return img; } +static const char PROBE_TIFF_MAGIC_LE[] = { 'I', 'I', 42, 0 }; +static const char PROBE_TIFF_MAGIC_BE[] = { 'M', 'M', 0, 42 }; +#define PROBE_BUF_SIZE 8 + Image *load_image(BPGMetaData **pmd, const char *infilename, BPGColorSpaceEnum color_space, int bit_depth, int limited_range, int premultiplied_alpha) @@ -1442,6 +1534,10 @@ if (png_sig_cmp(buf, 0, PROBE_BUF_SIZE) == 0) img = read_png(&md, f, color_space, bit_depth, limited_range, premultiplied_alpha); else + if (memcmp(buf, PROBE_TIFF_MAGIC_LE, sizeof(PROBE_TIFF_MAGIC_LE)) == 0 || + memcmp(buf, PROBE_TIFF_MAGIC_BE, sizeof(PROBE_TIFF_MAGIC_BE)) == 0) + img = read_tiff(&md, infilename, color_space, bit_depth, limited_range, premultiplied_alpha); + else img = read_jpeg(&md, f, bit_depth); err: