Partial fix for Bug 687418 WTS does not work with bitcmyk driver

"Russell Lang" <[email protected]>
Newsgroups gmane.comp.printing.ghostscript.patches
Message-ID <409C0B14.19061.4B4757AF@localhost>
Dan,

Note that this patch does not change color_info.gray_index,
which is not set by check_device_separable and so could be
wrong for some devices.

This patch also includes some test code in zcolor.c which can (or 
should) be omitted.  This test code checks whether the encode_color, 
decode_color, separable_and_linear routines are consistent.  


LOG MESSAGE:
Prevent check_device_separable from accepting non-consecutive
bits as separable and linear.  Modify gx_default_encode_color
and gx_default_decode_color to work on devices for which
max_color+1 != comp_bits[i].  Partial fix for bug #687418.  

DETAILS:
One example device for which max_color+1 != comp_bits[i] is
the Windows 16-bit native formats with 5:6:5 bits for RGB.
This has max_color set to 63 (not 31) to get the best results 
for green, but this did not work with the default encode_color
function.

Russell Lang                   [email protected]
Ghostgum Software Pty Ltd      http://www.ghostgum.com.au/

diff -u l:/cvs/gs/src/gdevdflt.c src/gdevdflt.c
--- l:/cvs/gs/src/gdevdflt.c	Fri May 07 09:18:46 2004
+++ src/gdevdflt.c	Fri May 07 11:17:58 2004
@@ -447,8 +447,11 @@
 	    color_index >>= 1;
 	comp_shift[i] = j;
 	/* Determine the bit count for the colorant */
-	for (j = 0; color_index != 0; j++)
+	for (j = 0; color_index != 0; j++) {
+	    if ((color_index & 1) == 0) /* check for non-consecutive bits */
+		return;
 	    color_index >>= 1;
+	}
 	comp_bits[i] = j;
 	/*
 	 * We could verify that the bit count matches the dither_grays or
diff -u l:/cvs/gs/src/gxcmap.c src/gxcmap.c
--- l:/cvs/gs/src/gxcmap.c	Fri Jan 30 09:36:00 2004
+++ src/gxcmap.c	Fri May 07 11:24:00 2004
@@ -52,6 +52,7 @@
     int             ncomps = dev->color_info.num_components;
     int             i, i_gray = dev->color_info.gray_index;
     const byte *    comp_shift = dev->color_info.comp_shift;
+    const byte *    comp_bits = dev->color_info.comp_bits;
     gx_color_index  color = 0;
 
 #ifdef DEBUG
@@ -61,11 +62,8 @@
     }
 #endif
     for (i = 0; i < ncomps; i++) {
-        ulong   cbits = cv[i] * ((i == i_gray ?
-                                 dev->color_info.max_gray :
-                                 dev->color_info.max_color ) + 1);
-
-        color |= (cbits / (gx_max_color_value + 1)) << comp_shift[i];
+	color |= (gx_color_index)(cv[i] >> (gx_color_value_bits - comp_bits[i]))
+		<< comp_shift[i];
     }
     return color;
 }
@@ -76,7 +74,9 @@
     int                     ncomps = dev->color_info.num_components;
     int                     i;
     const byte *            comp_shift = dev->color_info.comp_shift;
+    const byte *            comp_bits = dev->color_info.comp_bits;
     const gx_color_index *  comp_mask = dev->color_info.comp_mask;
+    int bits, shift;
 
 #ifdef DEBUG
     if ( dev->color_info.separable_and_linear != GX_CINFO_SEP_LIN ) {
@@ -86,12 +86,13 @@
 #endif
 
     for (i = 0; i < ncomps; i++) {
-        gx_color_index  div = ( i == dev->color_info.gray_index ? 
-                                dev->color_info.max_gray : 
-                                dev->color_info.max_color ) + 1;
-
-        cv[i] = (gx_color_value)(((color & comp_mask[i]) >> comp_shift[i]) * 
-            (gx_max_color_value + 1) / div);
+	bits = (color & comp_mask[i]) >> comp_shift[i];
+	shift = gx_color_value_bits - comp_bits[i];
+	cv[i] = bits << shift;
+	while ((shift-=comp_bits[i]) >= 0)
+	    cv[i] |= bits << shift;
+	if (shift < 0)
+	    cv[i] |= bits >> -shift;
     }
     return 0;
 }
diff -u l:/cvs/gs/src/zcolor.c src/zcolor.c
--- l:/cvs/gs/src/zcolor.c	Thu May 06 10:58:03 2004
+++ src/zcolor.c	Fri May 07 11:11:47 2004
@@ -475,6 +475,183 @@
     return 0;
 }
 
+/* 
+ * <param1> ... <paramN> .color_test <param1> ... <paramN>
+ *
+ * encode and decode color to allow mapping to be tested.
+ */
+int zcolor_test(i_ctx_t *i_ctx_p)
+{
+    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    gx_device *dev = gs_currentdevice(igs);
+    int ncomp = dev->color_info.num_components;
+    gx_color_index color;
+    int i;
+    if (ref_stack_count(&o_stack) < ncomp)
+	return_error(e_stackunderflow);
+    for (i=0; i<ncomp; i++) {
+	if (r_has_type(&osp[-i], t_real))
+	    cv[i] = (gx_color_value)
+		(osp[-i].value.realval * gx_max_color_value);
+	else if (r_has_type(&osp[-i], t_integer))
+	    cv[i] = (gx_color_value)
+		(osp[-i].value.intval * gx_max_color_value);
+	else
+	    return_error(e_typecheck);
+    }
+    color = (*dev_proc(dev, encode_color)) (dev, cv);
+    (*dev_proc(dev, decode_color)) (dev, color, cv);
+    for (i=0; i<ncomp; i++)
+        make_real(&osp[-i], (float)cv[i] / (float)gx_max_color_value);
+    return 0;
+}
+
+/* 
+ * <levels> .color_test_all <value0> ... <valueN>
+ *
+ * Test encode/decode color procedures for a range of values.
+ * Return value with the worst error in a single component.
+ */
+int zcolor_test_all(i_ctx_t *i_ctx_p)
+{
+    os_ptr                  op = osp;
+    gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    gx_color_value cvout[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    gx_color_value cvbad[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    int counter[GX_DEVICE_COLOR_MAX_COMPONENTS];
+    gx_device *dev = gs_currentdevice(igs);
+    int ncomp = dev->color_info.num_components;
+    int steps;
+    int maxerror = 0;
+    int err;
+    int acceptable_error;
+    int linsep = dev->color_info.separable_and_linear == GX_CINFO_SEP_LIN;
+    int linsepfailed = 0;
+    int lsmaxerror = 0;
+    gx_color_index color, lscolor;
+    int i, j, k;
+    int finished = 0;
+
+    if (ncomp == 1) 
+	acceptable_error = gx_max_color_value / dev->color_info.max_gray + 1;
+    else
+	acceptable_error = gx_max_color_value / dev->color_info.max_color + 1;
+
+    if (ref_stack_count(&o_stack) < 1)
+	return_error(e_stackunderflow);
+    if (!r_has_type(&osp[0], t_integer))
+        return_error(e_typecheck);
+    steps = osp[0].value.intval;
+    for (i=0; i<ncomp; i++) {
+        counter[i] = 0; 
+	cvbad[i] = 0;
+    }
+
+    dprintf1("\nNumber of components = %d\n", ncomp);
+    dprintf1("Depth = %d\n", dev->color_info.depth);
+    dprintf2("max_gray = %d   dither_grays = %d\n", 
+	dev->color_info.max_gray, dev->color_info.dither_grays);
+    dprintf2("max_color = %d   dither_colors = %d\n", 
+ 	dev->color_info.max_color, dev->color_info.dither_colors);
+    dprintf1("polarity = %s\n", 
+      dev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE ? "Additive" :
+      dev->color_info.polarity == GX_CINFO_POLARITY_SUBTRACTIVE ?"Subtractive":
+      "Unknown");
+    dprintf1("separable_and_linear = %s\n", 
+      linsep == GX_CINFO_SEP_LIN_NONE ? "No" :
+      linsep == GX_CINFO_SEP_LIN ? "Yes" :
+      "Unknown");
+    if (linsep) {
+	if (dev->color_info.gray_index == GX_CINFO_COMP_INDEX_UNKNOWN)
+            dprintf("gray_index is unknown\n");
+	else
+            dprintf1("gray_index=%d\n", dev->color_info.gray_index);
+        dprintf(" Shift     Mask  Bits\n");
+        for (i=0; i<ncomp; i++) {
+            dprintf3(" %5d %8x  %4d\n",
+		(int)(dev->color_info.comp_shift[i]),
+		(int)(dev->color_info.comp_mask[i]),
+		(int)(dev->color_info.comp_bits[i]));
+        }
+    }
+
+    while (!finished) {
+	for (j=0; j<=steps; j++) {
+	    for (i=0; i<ncomp; i++)
+		cv[i] = counter[i] * gx_max_color_value / steps;
+	    color = (*dev_proc(dev, encode_color)) (dev, cv);
+	    if (linsep) {
+		/* Derive it the other way */
+		lscolor = gx_default_encode_color(dev, cv);
+		if ((color != lscolor) && (linsepfailed < 5)) {
+		    linsepfailed++;
+		    dprintf("Failed separable_and_linear for");
+		    for (i=0; i<ncomp; i++)
+			dprintf1(" %d", cv[i]);
+		    dprintf("\n");
+		    dprintf2("encode_color=%x  gx_default_encode_color=%x\n",
+			(int)color, (int)lscolor);
+		}
+	    }
+	    (*dev_proc(dev, decode_color)) (dev, color, cvout);
+	    for (i=0; i<ncomp; i++) {
+		err = (int)cvout[i] - (int)cv[i];
+		if (err < 0)
+		    err = -err;
+		if (err > maxerror) {
+		    maxerror = err;
+		    for (k=0; k<ncomp; k++)
+			cvbad[k] = cv[k];
+		}
+	    }
+	    if (linsep) {
+	        gx_default_decode_color(dev, color, cvout);
+		for (i=0; i<ncomp; i++) {
+		    err = (int)cvout[i] - (int)cv[i];
+		    if (err < 0)
+			err = -err;
+		    if (err > lsmaxerror) {
+			lsmaxerror = err;
+		    }
+		}
+	    }
+	    counter[0] += 1;
+	}
+	counter[0] = 0;
+	i = 1;
+	while (i < ncomp) {
+	    counter[i] += 1;
+	    if (counter[i] > steps) {
+		counter[i] = 0;
+		i++;
+	    }
+	    else
+		break;
+	}
+	if (i >= ncomp)
+	    finished = 1;
+    }
+
+    dprintf2("Maximum error %g %s\n", 
+	(float)maxerror / (float)gx_max_color_value,
+	maxerror <= acceptable_error ? "is Ok" :
+	maxerror <= 3*acceptable_error/2 ? "is POOR" : "FAILED");
+
+    if (linsep)
+      dprintf2("Maximum linear_and_separable error %g %s\n", 
+	(float)lsmaxerror / (float)gx_max_color_value,
+	lsmaxerror <= acceptable_error ? "is Ok" :
+	lsmaxerror <= 3*acceptable_error/2 ? "is POOR" : "FAILED");
+
+    /* push worst value */
+    push(ncomp-1);
+    op -= ncomp - 1;
+    for (i=0; i<ncomp; i++)
+        make_real(op+i, (float)cvbad[i] / (float)gx_max_color_value);
+
+    return 0;
+}
+
 /* ------ Initialization procedure ------ */
 
 const op_def    zcolor_op_defs[] = 
@@ -496,6 +673,8 @@
     { "1%zcolor_remap_one_signed_finish", zcolor_remap_one_signed_finish },
     { "0%zcolor_reset_transfer", zcolor_reset_transfer },
     { "0%zcolor_remap_color", zcolor_remap_color },
+    { "0.color_test", zcolor_test },
+    { "1.color_test_all", zcolor_test_all },
 
     /* high level device support */
     { "0.includecolorspace", zincludecolorspace },

_______________________________________________
gs-code-review mailing list
[email protected]
http://www.ghostscript.com/mailman/listinfo/gs-code-review
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.