[gs-commits] rev 11755 - trunk/gs/base

ken at ghostscript.com ken at ghostscript.com
Tue Oct 5 12:48:16 UTC 2010


Author: ken
Date: 2010-10-05 12:48:16 +0000 (Tue, 05 Oct 2010)
New Revision: 11755

Modified:
   trunk/gs/base/gdevpdfi.c
   trunk/gs/base/gdevpsdi.c
Log:
Fix (pdfwrite) : ConvertCMYKImagesToRGB not working

Bug #691647 "-dConvertCMYKImagesToRGB no longer works"

Originally caused by the conversion to the ICC workflow, which meant that all images
appear to be in a ICC space, and only images originally natively CMYK are converted.

Probing the ICC space using the provided utility to return the original colour space 
allows the code to work, but reveals a more serious error. The code in
psdf_setup_image_filteres() alters the image colour space and decrements the reference
count of the original colour space.

This seems logically correct, and in one of the three calling paths it is correct, but
under one of the other two conditions it causes a crash. The routine 
pdf_begin_typed_image_impl() makes two copies of the original image parameters, and
when it does so it does *not* increment the reference counts of any counted objects.
This copied data is presented to the image filter setup several times, and if CMUK
to RGB conversion is going on the original colour space is decremented each time. This
leads to obvious problems.

The simplest solution would be to increment the reference counts when the copy is made, 
but that would mean checking all the error condition break outs, and decrementing the
reference count in each case.

Since the colour space is only decremented in the filter setup, this patch increments
the count before the call, and if the colour space is the same afterwards (whether
an error occurred or not) decrements it back again. If the colour space changes we do
not decrement the space of course, as the filter setup routine has done that.

In addition, extended the test for whether CMYK images should be converted to include
the original test of the native space, in case we get here after an image has been
converted to a base space and no longer has an ICC space.

No expected differences, this configuration is not tested by the regression suite.


Modified: trunk/gs/base/gdevpdfi.c
===================================================================
--- trunk/gs/base/gdevpdfi.c	2010-10-05 12:10:46 UTC (rev 11754)
+++ trunk/gs/base/gdevpdfi.c	2010-10-05 12:48:16 UTC (rev 11755)
@@ -713,6 +713,20 @@
 	image[0].pixel.ColorSpace = pcs_device;
     }
     pdev->ParamCompatibilityLevel = pdev->CompatibilityLevel;
+    
+    /* This is rather hacky. the gs_image_pixel_t union has copies of the image
+     * information, including the ColorSpace, but it does not increment the
+     * reference counts of the counted objects (teh ColorSpace) when it makes
+     * copies. However, if psdf_setup_image_filters() should change the colour
+     * space into DeviceCMYK because it converts the image, it will decrement
+     * the reference count of the original space. There is at least one place
+     * where it is called with the original space, so we can't simply remove
+     * the decrement. Handling this properly would entail incrementing the
+     * reference count when we make the copy, and correctly decrementing it
+     * in all the error conditions. Its easier to isolate the changes to
+     * this piece of code.
+     */
+    rc_increment_cs(image[0].pixel.ColorSpace);
     if ((code = pdf_begin_write_image(pdev, &pie->writer, gs_no_id, width,
 		    height, pnamed, in_line)) < 0 ||
 	/*
@@ -731,8 +745,14 @@
 		 psdf_setup_image_filters((gx_device_psdf *) pdev,
 					  &pie->writer.binary[0], &image[0].pixel,
 					  pmat, pis, true, in_line))) < 0
-	)
+	) {
+	if (image[0].pixel.ColorSpace == pim->ColorSpace)
+	    rc_decrement_only_cs(pim->ColorSpace, "psdf_setup_image_filters");
 	goto fail;
+    }
+    if (image[0].pixel.ColorSpace == pim->ColorSpace)
+        rc_decrement_only_cs(pim->ColorSpace, "psdf_setup_image_filters");
+
     if (convert_to_process_colors) {
 	image[0].pixel.ColorSpace = pcs_orig;
 	code = psdf_setup_image_colors_filter(&pie->writer.binary[0], 
@@ -741,6 +761,9 @@
   	    goto fail;
 	image[0].pixel.ColorSpace = pcs_device;
     }
+
+    /* See the comment above about reference counting of the colour space */
+    rc_increment_cs(image[1].pixel.ColorSpace);
     if (pie->writer.alt_writer_count > 1) {
         code = pdf_make_alt_stream(pdev, &pie->writer.binary[1]);
         if (code)
@@ -755,17 +778,26 @@
 	    pie->writer.alt_writer_count = 1;
 	    memset(pie->writer.binary + 1, 0, sizeof(pie->writer.binary[1]));
 	    memset(pie->writer.binary + 2, 0, sizeof(pie->writer.binary[1]));
-	} else if (code)
+	} else if (code) {
+	    if (image[1].pixel.ColorSpace == pim->ColorSpace)
+		rc_decrement_only_cs(pim->ColorSpace, "psdf_setup_image_filters");
 	    goto fail;
+	}
 	else if (convert_to_process_colors) {
 	    image[1].pixel.ColorSpace = pcs_orig;
 	    code = psdf_setup_image_colors_filter(&pie->writer.binary[1], 
 		    (gx_device_psdf *)pdev, &image[1].pixel, pis);
-	    if (code < 0)
+	    if (code < 0) {
+		if (image[1].pixel.ColorSpace == pim->ColorSpace)
+		    rc_decrement_only_cs(pim->ColorSpace, "psdf_setup_image_filters");
   		goto fail;
+	    }
 	    image[1].pixel.ColorSpace = pcs_device;
 	}
     }
+    if (image[1].pixel.ColorSpace == pim->ColorSpace)
+        rc_decrement_only_cs(pim->ColorSpace, "psdf_setup_image_filters");
+
     for (i = 0; i < pie->writer.alt_writer_count; i++) {
 	code = pdf_begin_image_data_decoded(pdev, num_components, pranges, i,
 			     &image[i].pixel, &cs_value, pie);

Modified: trunk/gs/base/gdevpsdi.c
===================================================================
--- trunk/gs/base/gdevpsdi.c	2010-10-05 12:10:46 UTC (rev 11754)
+++ trunk/gs/base/gdevpsdi.c	2010-10-05 12:48:16 UTC (rev 11755)
@@ -455,8 +455,10 @@
 {
     return pdev->params.ConvertCMYKImagesToRGB &&
 	    pis != 0 && pim->ColorSpace &&
-	    gs_color_space_get_index(pim->ColorSpace) ==
-	    gs_color_space_index_DeviceCMYK;
+	    (gs_color_space_get_index(pim->ColorSpace) == gs_color_space_index_DeviceCMYK ||
+	    (gs_color_space_get_index(pim->ColorSpace) == gs_color_space_index_ICC
+	    && gsicc_get_default_type(pim->ColorSpace->cmm_icc_profile_data) ==
+	    gs_color_space_index_DeviceCMYK));
 }
 
 static inline void 



More information about the gs-commits mailing list