Commit 8c957cf0 for libheif

commit 8c957cf014a211e0148be309273e4eb02c8706b5
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Fri Feb 13 12:06:32 2026 +0100

    support CMYK JPEG input

diff --git a/heifio/decoder_jpeg.cc b/heifio/decoder_jpeg.cc
index c2e76699..f602461c 100644
--- a/heifio/decoder_jpeg.cc
+++ b/heifio/decoder_jpeg.cc
@@ -495,6 +495,52 @@ heif_error loadJPEG(const char *filename, InputImage *input_image)
       }
     }
   }
+  else if (cinfo.jpeg_color_space == JCS_CMYK || cinfo.jpeg_color_space == JCS_YCCK) {
+    // libjpeg converts YCCK to CMYK internally when out_color_space is JCS_CMYK
+    cinfo.out_color_space = JCS_CMYK;
+
+    jpeg_start_decompress(&cinfo);
+
+    JSAMPARRAY buffer;
+    buffer = (*cinfo.mem->alloc_sarray)
+        ((j_common_ptr) &cinfo, JPOOL_IMAGE, cinfo.output_width * 4, 1);
+
+    // create interleaved RGB destination image
+
+    err = heif_image_create(cinfo.output_width, cinfo.output_height,
+                            heif_colorspace_RGB,
+                            heif_chroma_interleaved_RGB,
+                            &image);
+    if (err.code) { goto cleanup; }
+
+    err = heif_image_add_plane(image, heif_channel_interleaved, cinfo.output_width, cinfo.output_height, 8);
+    if (err.code) { goto cleanup; }
+
+    size_t rgb_stride;
+    uint8_t* pRGB = heif_image_get_plane2(image, heif_channel_interleaved, &rgb_stride);
+
+    while (cinfo.output_scanline < cinfo.output_height) {
+      (void) jpeg_read_scanlines(&cinfo, buffer, 1);
+
+      JOCTET* bufp = buffer[0];
+      size_t y = cinfo.output_scanline - 1;
+      uint8_t* row = pRGB + y * rgb_stride;
+
+      for (unsigned int x = 0; x < cinfo.output_width; x++) {
+        uint8_t C = bufp[0];
+        uint8_t M = bufp[1];
+        uint8_t Y = bufp[2];
+        uint8_t K = bufp[3];
+        bufp += 4;
+
+        // CMYK to RGB — JPEG CMYK uses inverted values (255 = no ink)
+        row[0] = (uint8_t)(C * K / 255);
+        row[1] = (uint8_t)(M * K / 255);
+        row[2] = (uint8_t)(Y * K / 255);
+        row += 3;
+      }
+    }
+  }
   else {
     jpeg_destroy_decompress(&cinfo);
     free(iccBuffer);