# HG changeset patch # User Matti Hamalainen # Date 1481226044 -7200 # Node ID e70eb0e6acd54b0cdb80d94e0a63a5d0807053d2 # Parent d04d9e3a77d0cfb316d5d52ec03a01ba55024454 Add support for indexed palette TIFFs, at least some of them. diff -r d04d9e3a77d0 -r e70eb0e6acd5 bpgenc.c --- a/bpgenc.c Thu Dec 08 21:38:15 2016 +0200 +++ b/bpgenc.c Thu Dec 08 21:40:44 2016 +0200 @@ -957,7 +957,8 @@ uint32_t img_width, img_height, tmp_len; int img_alpha, err_spp = 0; size_t img_linesize; - uint16_t img_depth, img_spp, img_pconfig, img_pmetric; + uint16_t img_depth, img_spp, img_pconfig, img_pmetric, + *buf2 = NULL, *img_colormap_r, *img_colormap_g, *img_colormap_b; ColorConvertState cvt; RGBConvertFunc *convert_func; @@ -989,6 +990,18 @@ err_spp = 1; break; + case PHOTOMETRIC_PALETTE: + img_format = BPG_FORMAT_444; + if (img_spp != 1) + err_spp = 1; + + if (!TIFFGetField(tif, TIFFTAG_COLORMAP, &img_colormap_r, &img_colormap_g, &img_colormap_b)) + { + fprintf(stderr, "TIFF with palette is missing colormap entry!\n"); + goto err; + } + break; + default: fprintf(stderr, "TIFF file has unsupported photometric interpretation %d!\n", img_pmetric); goto err; @@ -1007,8 +1020,6 @@ } img_linesize = TIFFScanlineSize(tif); - img_format = BPG_FORMAT_444; - img_bpp = sizeof(uint32_t) * img_depth / 8; if (img_spp > 3) { @@ -1025,6 +1036,19 @@ if (buf == NULL) goto err; + if (img_pmetric == PHOTOMETRIC_PALETTE) + { + // For indexed palette images we need a secondary RGB conversion buffer + buf2 = (uint16_t *) malloc(img_width * 3 * sizeof(uint16_t)); + if (buf2 == NULL) + goto err; + + // Force 16bit depth and samples per pixel 3 as the + // TIFF colormap/palette has 16bit R, G, B entries. + img_spp = 3; + img_depth = 16; + } + // Allocate target image img = image_alloc(img_width, img_height, img_format, img_alpha, color_space, out_bit_depth); if (img == NULL) @@ -1044,27 +1068,46 @@ 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); - - if (img_alpha) + // Convert the scanline data + switch (img_pmetric) { - if (idx) - { - gray16_to_gray(&cvt, - (PIXEL *)(img->data[3] + y * img->linesize[3]), - ((uint16_t *) buf) + 3, img->w, 4); - } - else - { - gray8_to_gray(&cvt, - (PIXEL *)(img->data[3] + y * img->linesize[3]), - ((uint8_t *) buf) + 3, img->w, 4); - } + case PHOTOMETRIC_PALETTE: + for (int x = 0, offs = 0; x < img->w; x++) + { + buf2[offs++] = img_colormap_r[buf[x]]; + buf2[offs++] = img_colormap_g[buf[x]]; + buf2[offs++] = img_colormap_b[buf[x]]; + } + 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]), + buf2, img->w, img_spp); + break; + + case PHOTOMETRIC_RGB: + 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); + + if (img_alpha) + { + if (idx) + { + gray16_to_gray(&cvt, + (PIXEL *)(img->data[3] + y * img->linesize[3]), + ((uint16_t *) buf) + 3, img->w, 4); + } + else + { + gray8_to_gray(&cvt, + (PIXEL *)(img->data[3] + y * img->linesize[3]), + ((uint8_t *) buf) + 3, img->w, 4); + } + } + break; } } @@ -1079,6 +1122,9 @@ if (buf != NULL) _TIFFfree(buf); + if (buf2 != NULL) + free(buf2); + TIFFClose(tif); return img; }