changeset 11:e70eb0e6acd5

Add support for indexed palette TIFFs, at least some of them.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 08 Dec 2016 21:40:44 +0200
parents d04d9e3a77d0
children 9b00d4206f99
files bpgenc.c
diffstat 1 files changed, 69 insertions(+), 23 deletions(-) [+]
line wrap: on
line diff
--- 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;
 }