[gs-commits] rev 10855 - branches/icc_work/base

mvrhel at ghostscript.com mvrhel at ghostscript.com
Thu Mar 4 20:57:27 UTC 2010


Author: mvrhel
Date: 2010-03-04 20:57:26 +0000 (Thu, 04 Mar 2010)
New Revision: 10855

Modified:
   branches/icc_work/base/gxcmap.c
   branches/icc_work/base/gxicolor.c
Log:
Fix so that image color render with ICC profiles properly applies the transfer curve and/or the halftoning for the device.

Modified: branches/icc_work/base/gxcmap.c
===================================================================
--- branches/icc_work/base/gxcmap.c	2010-03-04 20:41:47 UTC (rev 10854)
+++ branches/icc_work/base/gxcmap.c	2010-03-04 20:57:26 UTC (rev 10855)
@@ -1587,3 +1587,64 @@
         f = float2frac(fvalue);
     return f;
 }
+
+/* This is used by image color render to handle the cases where we need to
+   perform either a transfer function or halftoning on the color values
+   during an ICC color flow.  In this case, the color is already in the
+   device color space but in 16bpp color values. */
+void
+cmap_transfer_halftone(gx_color_value *pconc, gx_device_color * pdc,
+     const gs_imager_state * pis, gx_device * dev, bool has_transfer,
+     bool has_halftone, gs_color_select_t select)
+{
+    int ncomps = dev->color_info.num_components;
+    frac frac_value;
+    int i;
+    frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS];
+
+    /* apply the transfer function(s) */
+    if (has_transfer) {
+        if (dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE) {
+            for (i = 0; i < ncomps; i++) {
+                frac_value = cv2frac(pconc[i]);
+                cv_frac[i] = gx_map_color_frac(pis,
+	    			    frac_value, effective_transfer[i]);
+            }
+        } else {
+            if (dev->color_info.opmode == GX_CINFO_OPMODE_UNKNOWN) {
+                check_cmyk_color_model_comps(dev);
+            }
+            if (dev->color_info.opmode == GX_CINFO_OPMODE) {  /* CMYK-like color space */
+                int k = dev->color_info.black_component;
+                for (i = 0; i < ncomps; i++) {
+                    frac_value = cv2frac(pconc[i]);
+                    if (i == k) {
+                        cv_frac[i] = frac_1 - gx_map_color_frac(pis,
+	    		    (frac)(frac_1 - frac_value), effective_transfer[i]);
+                    } else {
+                        cv_frac[i] = cv2frac(pconc[i]);  /* Ignore transfer, see PLRM3 p. 494 */
+                    }
+                }
+            } else {
+                for (i = 0; i < ncomps; i++) {
+                    frac_value = cv2frac(pconc[i]);
+                    cv_frac[i] = frac_1 - gx_map_color_frac(pis,
+	    		        (frac)(frac_1 - frac_value), effective_transfer[i]);
+                }
+            }
+        }
+    } else {
+        if (has_halftone) {
+            /* We need this to be in frac form */
+            for (i = 0; i < ncomps; i++) {
+                cv_frac[i] = cv2frac(pconc[i]);  
+            }
+        }   
+    }
+    /* Halftoning */
+    if (has_halftone) {
+        if (gx_render_device_DeviceN(&(cv_frac[0]), pdc, dev,
+	            pis->dev_ht, &pis->screen_phase[select]) == 1)
+            gx_color_load_select(pdc, pis, dev, select);
+    }
+}

Modified: branches/icc_work/base/gxicolor.c
===================================================================
--- branches/icc_work/base/gxicolor.c	2010-03-04 20:41:47 UTC (rev 10854)
+++ branches/icc_work/base/gxicolor.c	2010-03-04 20:57:26 UTC (rev 10855)
@@ -45,6 +45,10 @@
     bits32 all[BITS32_PER_COLOR_SAMPLES];	/* for fast comparison */
 } color_samples;
 
+extern void cmap_transfer_halftone(gx_color_value *pconc, gx_device_color * pdc,
+     const gs_imager_state * pis, gx_device * dev, bool has_transfer,
+     bool has_halftone, gs_color_select_t select);
+
 /* ------ Strategy procedure ------ */
 
 /* Check the prototype. */
@@ -111,6 +115,23 @@
     return true;
 }
 
+static bool 
+gx_has_transfer(const gs_imager_state *pis, int num_comps)
+{
+    int k;
+    gs_state *pgs;
+
+    if (pis->is_gstate) {
+        pgs = (gs_state *)pis;
+        for (k = 0; k < num_comps; k++) {
+            if (pgs->effective_transfer[k]->proc != gs_identity_transfer) {
+                return(true);
+            }
+        }
+    } 
+    return(false);
+}
+
 /* Render a color image with 8 or fewer bits per sample using ICC profile. */
 static int
 image_render_color_icc(gx_image_enum *penum_orig, const byte *buffer, int data_x,
@@ -148,9 +169,12 @@
     gsicc_bufferdesc_t output_buff_desc;
     unsigned char *psrc_cm, *psrc_cm_start;
     int k;
-    gx_color_index color;
     gx_color_value conc[GX_DEVICE_COLOR_MAX_COMPONENTS];
     int spp_cm, num_pixels;
+    gx_color_index color;
+    bool must_halftone = gx_device_must_halftone(dev);
+    bool has_transfer = gx_has_transfer(pis,
+                                pis->icc_manager->device_profile->num_comps);
 
     /* Needed for device N */
     memset(&(conc[0]), 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
@@ -176,7 +200,7 @@
         return gs_rethrow(-1, "ICC Link not created during image render color");
     }
     /* If the link is the identity, then we don't need to do any color conversions */
-    if (icc_link->is_identity ) {
+    if (icc_link->is_identity) {
         psrc_cm = (unsigned char *) psrc;
         spp_cm = spp;
         bufend = psrc_cm +  w;
@@ -245,11 +269,20 @@
          for ( k = 0; k < spp_cm; k++ ) {
             conc[k] = gx_color_value_from_byte(next.v[k]);
         }
-        /* encode as a color index */
-        color = dev_proc(dev, encode_color)(dev, &(conc[0]));
-    /* check if the encoding was successful; we presume failure is rare */
-    if (color != gx_no_color_index)
-        color_set_pure(pdevc_next, color);
+        /* Now we can do an encoding directly or we have to apply transfer
+           and or halftoning */
+        if (must_halftone || has_transfer) {
+            /* We need to do the tranfer function and/or the halftoning */
+            cmap_transfer_halftone(&(conc[0]), pdevc_next, pis, dev, 
+                has_transfer, must_halftone, gs_color_select_source);
+        } else {
+            /* encode as a color index. avoid all the cv to frac to cv
+               conversions */
+            color = dev_proc(dev, encode_color)(dev, &(conc[0]));
+            /* check if the encoding was successful; we presume failure is rare */
+            if (color != gx_no_color_index)
+                color_set_pure(pdevc_next, color);
+        }
         /* Fill the region between */
 	/* xrun/irun and xprev */
         /*



More information about the gs-commits mailing list