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

mvrhel at ghostscript.com mvrhel at ghostscript.com
Tue Mar 23 20:46:15 UTC 2010


Author: mvrhel
Date: 2010-03-23 20:46:14 +0000 (Tue, 23 Mar 2010)
New Revision: 10958

Modified:
   branches/icc_work/base/gscspace.c
   branches/icc_work/base/gsicc.c
   branches/icc_work/base/gxcspace.h
   branches/icc_work/base/gxshade.c
   branches/icc_work/base/gxshade.h
   branches/icc_work/base/gxshade1.c
   branches/icc_work/base/gxshade6.c
Log:
Change in how the shading code performs is-linear check with icc colors.  This is a optimized in that the link request is made at the time that the shading object is set up.  In addition, ICC color spaces now have their own optimized check for linearity as opposed to using the default operation.

Modified: branches/icc_work/base/gscspace.c
===================================================================
--- branches/icc_work/base/gscspace.c	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gscspace.c	2010-03-23 20:46:14 UTC (rev 10958)
@@ -513,7 +513,7 @@
 		gx_device * dev, 
 		const gs_client_color *c0, const gs_client_color *c1,
 		const gs_client_color *c2, const gs_client_color *c3,
-		float smoothness)
+		float smoothness, gsicc_link_t *icclink)
 {
     return_error(gs_error_rangecheck);
 }
@@ -662,13 +662,14 @@
     return 1;
 }
 
+
 /* Default color mapping linearity check. */
 int
 gx_cspace_is_linear_default(const gs_color_space *cs, const gs_imager_state * pis,
 		gx_device *dev, 
 		const gs_client_color *c0, const gs_client_color *c1,
 		const gs_client_color *c2, const gs_client_color *c3,
-		float smoothness)
+		float smoothness, gsicc_link_t *icclink)
 {
     /* Assuming 2 <= nc <= 4. We don't need other cases. */
     /* With nc == 4 assuming a convex plain quadrangle in the client color space. */

Modified: branches/icc_work/base/gsicc.c
===================================================================
--- branches/icc_work/base/gsicc.c	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gsicc.c	2010-03-23 20:46:14 UTC (rev 10958)
@@ -27,6 +27,7 @@
 #include "gsicc.h"
 #include "gsicccache.h"
 #include "gsicc_littlecms.h"
+#include "gxdevice.h"
 
 #define SAVEICCPROFILE 0
 
@@ -61,6 +62,7 @@
 static cs_proc_remap_concrete_color(gx_remap_concrete_ICC);
 static cs_proc_final(gx_final_ICC);
 static cs_proc_serialize(gx_serialize_ICC);
+static cs_proc_is_linear(gx_cspace_is_linear_ICC);
 
 const gs_color_space_type gs_color_space_type_ICC = {
     gs_color_space_index_ICC,       /* index */
@@ -79,9 +81,152 @@
     gx_final_ICC,                   /* final */
     gx_no_adjust_color_count,       /* adjust_color_count */
     gx_serialize_ICC,               /* serialize */
-    gx_cspace_is_linear_default
+    gx_cspace_is_linear_ICC
 };
 
+
+
+static inline void
+gsicc_remap_fast(unsigned short *psrc, unsigned short *psrc_cm,
+		       gsicc_link_t *icc_link)
+{
+    gscms_transform_color(icc_link, psrc, psrc_cm, 2, NULL);
+}
+
+/* ICC color mapping linearity check, a 2-points case. Check only the 1/2 point */
+static int
+gx_icc_is_linear_in_line(const gs_color_space *cs, const gs_imager_state * pis,
+		gx_device *dev, 
+		const gs_client_color *c0, const gs_client_color *c1,
+		float smoothness, gsicc_link_t *icclink)
+{
+    int nsrc = cs->type->num_components(cs);
+    int ndes = dev->color_info.num_components;
+    unsigned short src0[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src1[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src01[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des0[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des1[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des01[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short interp_des;
+    unsigned short max_diff = max(1, 65535 * smoothness);
+    int k;
+
+    /* Get us to ushort and get mid point */
+    for (k = 0; k < nsrc; k++) {
+        src0[k] = c0->paint.values[k]*65535;
+        src1[k] = c1->paint.values[k]*65535;
+        src01[k] = ((unsigned int) src0[k] + (unsigned int) src1[k]) >> 1;
+    }
+    /* Transform the end points and the interpolated point */
+    gsicc_remap_fast(&(src0[0]), &(des0[0]), icclink);
+    gsicc_remap_fast(&(src1[0]), &(des1[0]), icclink);
+    gsicc_remap_fast(&(src01[0]), &(des01[0]), icclink);
+    /* Interpolate 1/2 value in des space and compare */
+    for (k = 0; k < ndes; k++) {
+        interp_des = (des0[k] + des1[k]) >> 1;
+        if (any_abs(interp_des - des01[k]) > max_diff)
+            return false;
+    }
+    return 1;
+}
+
+/* Default icc color mapping linearity check, a triangle case. */
+static int
+gx_icc_is_linear_in_triangle(const gs_color_space *cs, const gs_imager_state * pis,
+		gx_device *dev, 
+		const gs_client_color *c0, const gs_client_color *c1,
+		const gs_client_color *c2, float smoothness, gsicc_link_t *icclink)
+{
+    /* Check 4 points middle points of 3 sides and middle of one side with
+       other point.  We avoid divisions this way. */
+    unsigned short src0[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src1[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src2[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des0[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des1[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des2[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src01[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src12[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src02[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short src012[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des01[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des12[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des02[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    unsigned short des012[GS_CLIENT_COLOR_MAX_COMPONENTS];
+    int nsrc = cs->type->num_components(cs);
+    int ndes = dev->color_info.num_components;
+    unsigned short max_diff = max(1, 65535 * smoothness);
+    unsigned int interp_des;
+    int k;
+
+    /* This needs to be optimized. And range corrected */
+    for (k = 0; k < nsrc; k++){
+        src0[k] = c0->paint.values[k]*65535;
+        src1[k] = c1->paint.values[k]*65535;
+        src2[k] = c2->paint.values[k]*65535;
+        src01[k] = (src0[k] + src1[k]) >> 1;
+        src02[k] = (src0[k] + src2[k]) >> 1;   
+        src12[k] = (src1[k] + src2[k]) >> 1;
+        src012[k] = (src12[k] + src0[k]) >> 1;  
+    }
+    /* Map the points */
+    gsicc_remap_fast(&(src0[0]), &(des0[0]), icclink);
+    gsicc_remap_fast(&(src1[0]), &(des1[0]), icclink);
+    gsicc_remap_fast(&(src2[0]), &(des2[0]), icclink);
+    gsicc_remap_fast(&(src01[0]), &(des01[0]), icclink);
+    gsicc_remap_fast(&(src12[0]), &(des12[0]), icclink);
+    gsicc_remap_fast(&(src02[0]), &(des02[0]), icclink);
+    gsicc_remap_fast(&(src012[0]), &(des012[0]), icclink);
+    /* Interpolate in des space and check it */
+    for (k = 0; k < ndes; k++){
+        interp_des = (des0[k] + des1[k]) >> 1;
+        if (any_abs(interp_des - des01[k]) > max_diff)
+            return false;
+        interp_des = (des0[k] + des2[k]) >> 1;
+        if (any_abs(interp_des - des02[k]) > max_diff)
+            return false;
+        interp_des = (des1[k] + des2[k]) >> 1;
+        if (any_abs(interp_des - des12[k]) > max_diff)
+            return false;
+        /* 12 with 0 */
+        interp_des = (des0[k] + interp_des) >> 1;
+        if (any_abs(interp_des - des012[k]) > max_diff)
+            return false;
+    }
+    return 1;
+}
+
+/* ICC color mapping linearity check. */
+int
+gx_cspace_is_linear_ICC(const gs_color_space *cs, const gs_imager_state * pis,
+		gx_device *dev, 
+		const gs_client_color *c0, const gs_client_color *c1,
+		const gs_client_color *c2, const gs_client_color *c3,
+		float smoothness, gsicc_link_t *icclink)
+{
+    /* Assuming 2 <= nc <= 4. We don't need other cases. */
+    /* With nc == 4 assuming a convex plain quadrangle in the client color space. */
+    int code;
+    
+    /* Do a quick check if we are in a halftone situation. If yes,
+       then we should not be doing this linear check */
+    if (gx_device_must_halftone(dev)) return 0;
+    if (icclink->is_identity) return 1; /* Transform is identity, linear! */
+
+    if (dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN)
+	return_error(gs_error_rangecheck);
+    if (c2 == NULL)
+	return gx_icc_is_linear_in_line(cs, pis, dev, c0, c1, smoothness, icclink);
+    code = gx_icc_is_linear_in_triangle(cs, pis, dev, c0, c1, c2, 
+                                            smoothness, icclink);
+    if (code <= 0)
+	return code;
+    if (c3 == NULL)
+	return 1;
+    return gx_icc_is_linear_in_triangle(cs, pis, dev, c1, c2, c3, 
+                                                smoothness, icclink);
+}
 /*
  * Return the number of components used by a ICCBased color space - 1, 3, or 4
  */

Modified: branches/icc_work/base/gxcspace.h
===================================================================
--- branches/icc_work/base/gxcspace.h	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gxcspace.h	2010-03-23 20:46:14 UTC (rev 10958)
@@ -205,9 +205,9 @@
 		gx_device *dev,\
 		const gs_client_color *c0, const gs_client_color *c1,\
 		const gs_client_color *c2, const gs_client_color *c3,\
-		float smoothness)
-#define cs_is_linear(pcs, pis, dev, c0, c1, c2, c3, smoothness)\
-  (*(pcs)->type->is_linear)(pcs, pis, dev, c0, c1, c2, c3, smoothness)
+		float smoothness, gsicc_link_t *icclink)
+#define cs_is_linear(pcs, pis, dev, c0, c1, c2, c3, smoothness, icclink)\
+  (*(pcs)->type->is_linear)(pcs, pis, dev, c0, c1, c2, c3, smoothness, icclink)
 	cs_proc_is_linear((*is_linear));
 };
 

Modified: branches/icc_work/base/gxshade.c
===================================================================
--- branches/icc_work/base/gxshade.c	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gxshade.c	2010-03-23 20:46:14 UTC (rev 10958)
@@ -322,6 +322,7 @@
 	max(dev->color_info.max_gray, dev->color_info.max_color) + 1;
     const gs_range *ranges = 0;
     int ci;
+    gsicc_rendering_param_t rendering_params;
 
     pfs->dev = dev;
     pfs->pis = pis;
@@ -372,10 +373,19 @@
         pfs->trans_device = pis->trans_device;
     } else {
         pfs->trans_device = dev;
+    }
+    /* Grab the icc link transform that we need now */
+    if (pcs->cmm_icc_profile_data != NULL) {
+        rendering_params.black_point_comp = BP_ON;
+        rendering_params.object_type = GS_PATH_TAG;
+        rendering_params.rendering_intent = pis->renderingintent;
+        pfs->icclink = gsicc_get_link(pis, pcs, NULL, &rendering_params, 
+                                        pis->memory, false);
+    } else {
+        pfs->icclink = NULL;
+    }
 }
 
-}
-
 /* Fill one piece of a shading. */
 int
 shade_fill_path(const shading_fill_state_t * pfs, gx_path * ppath,

Modified: branches/icc_work/base/gxshade.h
===================================================================
--- branches/icc_work/base/gxshade.h	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gxshade.h	2010-03-23 20:46:14 UTC (rev 10958)
@@ -196,7 +196,8 @@
   const gs_color_space *direct_space;\
   int num_components;		/* # of color components in direct_space */\
   float cc_max_error[GS_CLIENT_COLOR_MAX_COMPONENTS];\
-  gx_device *trans_device
+  gx_device *trans_device;\
+  gsicc_link_t *icclink 
 
 typedef struct shading_fill_state_s {
     shading_fill_state_common;

Modified: branches/icc_work/base/gxshade1.c
===================================================================
--- branches/icc_work/base/gxshade1.c	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gxshade1.c	2010-03-23 20:46:14 UTC (rev 10958)
@@ -266,6 +266,7 @@
     }
     if (term_patch_fill_state(&pfs1))
 	return_error(gs_error_unregistered); /* Must not happen. */
+    if (pfs1.icclink != NULL) gsicc_release_link(pfs1.icclink);
     return code;
 }
 

Modified: branches/icc_work/base/gxshade6.c
===================================================================
--- branches/icc_work/base/gxshade6.c	2010-03-23 20:43:36 UTC (rev 10957)
+++ branches/icc_work/base/gxshade6.c	2010-03-23 20:46:14 UTC (rev 10958)
@@ -1116,7 +1116,7 @@
 	if (s > pfs->smoothness)
 	    return 0;
 	code = cs_is_linear(cs, pfs->pis, pfs->dev, 
-		&c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s);
+		&c0->cc, &c1->cc, NULL, NULL, pfs->smoothness - s, pfs->icclink);
 	if (code <= 0)
 	    return code;
 	return 1;
@@ -1706,7 +1706,8 @@
 	    s01 = max(s0, s1);
 	    s012 = max(s01, s2);
 	    code = cs_is_linear(cs, pfs->pis, pfs->dev, 
-				&p0->c->cc, &p1->c->cc, &p2->c->cc, NULL, pfs->smoothness - s012);
+				&p0->c->cc, &p1->c->cc, &p2->c->cc, NULL, 
+                                pfs->smoothness - s012, pfs->icclink);
 	    if (code < 0)
 		return code;
 	    if (code == 0)
@@ -2680,6 +2681,7 @@
     pfs->color_stack_limit = NULL; /* fixme */
     pfs->pcic = NULL; /* Will do someday. */
     pfs->trans_device = NULL;
+    pfs->icclink = NULL;
     return alloc_patch_fill_memory(pfs, memory, NULL);
 }
 



More information about the gs-commits mailing list