libtiff: tiffcp: Setting the correct photometric interpretation for the output image when converting JPEG-YCBCR to JPEG-RGB images.

From ef4a936e3e662ac508044589e6051b1949cc7259 Mon Sep 17 00:00:00 2001
From: Even Rouault <[EMAIL REDACTED]>
Date: Wed, 4 Oct 2023 22:21:13 +0200
Subject: [PATCH] tiffcp: Setting the correct photometric interpretation for
 the output image when converting JPEG-YCBCR to JPEG-RGB images.

Closes #571
---
 tools/tiffcp.c | 22 ++++++++++------------
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/tools/tiffcp.c b/tools/tiffcp.c
index 2628bdbb..2b3aa1df 100644
--- a/tools/tiffcp.c
+++ b/tools/tiffcp.c
@@ -87,7 +87,7 @@ static uint32_t g3opts;
 static int ignore = FALSE; /* if true, ignore read errors */
 static uint32_t defg3opts = (uint32_t)-1;
 static int quality = 75; /* JPEG quality */
-static int jpegcolormode = JPEGCOLORMODE_RGB;
+static int jpeg_photometric = PHOTOMETRIC_YCBCR;
 static uint16_t defcompression = (uint16_t)-1;
 static uint16_t defpredictor = (uint16_t)-1;
 static int defpreset = -1;
@@ -490,7 +490,7 @@ static int processCompressOptions(char *opt)
             if (isdigit((int)cp[1]))
                 quality = atoi(cp + 1);
             else if (cp[1] == 'r')
-                jpegcolormode = JPEGCOLORMODE_RAW;
+                jpeg_photometric = PHOTOMETRIC_RGB;
             else
                 usage(EXIT_FAILURE);
 
@@ -871,9 +871,11 @@ static int tiffcp(TIFF *in, TIFF *out)
     }
     if (compression == COMPRESSION_JPEG)
     {
-        if (input_photometric == PHOTOMETRIC_RGB &&
-            jpegcolormode == JPEGCOLORMODE_RGB)
-            TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_YCBCR);
+        if (input_photometric == PHOTOMETRIC_RGB ||
+            input_photometric == PHOTOMETRIC_YCBCR)
+        {
+            TIFFSetField(out, TIFFTAG_PHOTOMETRIC, jpeg_photometric);
+        }
         else
             TIFFSetField(out, TIFFTAG_PHOTOMETRIC, input_photometric);
     }
@@ -882,12 +884,6 @@ static int tiffcp(TIFF *in, TIFF *out)
         TIFFSetField(out, TIFFTAG_PHOTOMETRIC,
                      samplesperpixel == 1 ? PHOTOMETRIC_LOGL
                                           : PHOTOMETRIC_LOGLUV);
-    else if (input_compression == COMPRESSION_JPEG && samplesperpixel == 3)
-    {
-        /* RGB conversion was forced above
-        hence the output will be of the same type */
-        TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
-    }
     else
         CopyTag(TIFFTAG_PHOTOMETRIC, 1, TIFF_SHORT);
     if (fillorder != 0)
@@ -954,7 +950,9 @@ static int tiffcp(TIFF *in, TIFF *out)
     {
         case COMPRESSION_JPEG:
             TIFFSetField(out, TIFFTAG_JPEGQUALITY, quality);
-            TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, jpegcolormode);
+            /* For 3 sample images, the input data provided to libtiff is
+             * always RGB, not YCbCr subsampled. */
+            TIFFSetField(out, TIFFTAG_JPEGCOLORMODE, JPEGCOLORMODE_RGB);
             break;
         case COMPRESSION_JBIG:
             CopyTag(TIFFTAG_FAXRECVPARAMS, 1, TIFF_LONG);