[gs-commits] rev 11020 - in branches/icc_work: Resource/Init base psi

mvrhel at ghostscript.com mvrhel at ghostscript.com
Tue Apr 6 06:10:14 UTC 2010


Author: mvrhel
Date: 2010-04-06 06:10:12 +0000 (Tue, 06 Apr 2010)
New Revision: 11020

Modified:
   branches/icc_work/Resource/Init/pdf_ops.ps
   branches/icc_work/base/gsicc.c
   branches/icc_work/base/gxcmap.c
   branches/icc_work/base/gxicolor.c
   branches/icc_work/base/gxidata.c
   branches/icc_work/base/gximage.h
   branches/icc_work/base/gxipixel.c
   branches/icc_work/base/gxiscale.c
   branches/icc_work/base/lib.mak
   branches/icc_work/psi/zcolor.c
Log:
Change so that link requests in the imaging code occur during initialization of the the image enumeration object.  This avoids having the code request a link with every line processed. Also addition of faster code for handling ICC profiles in interpolated images.  This avoids many of the conversions that were taking place within that code.  Fixes also for rendering bugs that existed when we processed CIELAB colors in graphic fills and when we did interpolation of CIELAB images.

Modified: branches/icc_work/Resource/Init/pdf_ops.ps
===================================================================
--- branches/icc_work/Resource/Init/pdf_ops.ps	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/Resource/Init/pdf_ops.ps	2010-04-06 06:10:12 UTC (rev 11020)
@@ -204,7 +204,7 @@
   /CIEBasedABC { [0 0 0] cvx } bind
   /CalGray { pop //csdevgray 0 } bind
   /CalRGB { pop //csdevrgb [0 0 0] cvx } bind
-  /Lab { pop //csdevrgb [0 0 0] cvx } bind
+  /Lab {[0 0 0] cvx } bind
   /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind
   /Separation { 1 } bind
   /DeviceN {	% What is the correct value??

Modified: branches/icc_work/base/gsicc.c
===================================================================
--- branches/icc_work/base/gsicc.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gsicc.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -333,11 +333,16 @@
        not color managed */
     memset(psrc_cm,0,sizeof(unsigned short)*GS_CLIENT_COLOR_MAX_COMPONENTS);
 
-     /* This needs to be optimized. And range corrected */
-   for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++){
-        psrc[k] = pcc->paint.values[k]*65535;
+     /* This needs to be optimized */
+    if (pcs->cmm_icc_profile_data->data_cs == gsCIELAB) {
+        psrc[0] = pcc->paint.values[0]*65535.0/100.0;
+        psrc[1] = (pcc->paint.values[1]+128)/255.0*65535.0;
+        psrc[2] = (pcc->paint.values[2]+128)/255.0*65535.0;
+    } else {
+        for (k = 0; k < pcs->cmm_icc_profile_data->num_comps; k++){
+            psrc[k] = pcc->paint.values[k]*65535.0;
+        }
     }
-
     /* Get a link from the cache, or create if it is not there. Need to get 16 bit profile */
     icc_link = gsicc_get_link(pis, pcs, NULL, &rendering_params, pis->memory, false);
     if (icc_link->is_identity) {

Modified: branches/icc_work/base/gxcmap.c
===================================================================
--- branches/icc_work/base/gxcmap.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gxcmap.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -1602,6 +1602,7 @@
     int i;
     frac cv_frac[GX_DEVICE_COLOR_MAX_COMPONENTS];
     gx_color_index color;
+    gx_color_value color_val[GX_DEVICE_COLOR_MAX_COMPONENTS];
 
     /* apply the transfer function(s) */
     if (has_transfer) {
@@ -1648,8 +1649,12 @@
 	            pis->dev_ht, &pis->screen_phase[select]) == 1)
             gx_color_load_select(pdc, pis, dev, select);
     } else {
-        /* We have a frac value from the transfer function.  Do the encode */
-        color = dev_proc(dev, encode_color)(dev, &(cv_frac[0]));
+        /* We have a frac value from the transfer function.  Do the encode.
+           which does not take a frac value...  */
+        for (i = 0; i < ncomps; i++) {
+            color_val[i] = frac2cv(cv_frac[i]);  
+        }
+        color = dev_proc(dev, encode_color)(dev, &(color_val[0]));
         /* check if the encoding was successful; we presume failure is rare */
         if (color != gx_no_color_index)
             color_set_pure(pdc, color);

Modified: branches/icc_work/base/gxicolor.c
===================================================================
--- branches/icc_work/base/gxicolor.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gxicolor.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -56,6 +56,7 @@
 
 static irender_proc(image_render_color_DeviceN);
 static irender_proc(image_render_color_icc);
+
 irender_proc_t
 gs_image_class_4_color(gx_image_enum * penum)
 {
@@ -94,6 +95,38 @@
         penum->pcs->cmm_icc_profile_data == NULL ) {
         return &image_render_color_DeviceN;
     } else {
+        /* Set up the link now */
+        const gs_color_space *pcs;
+        gsicc_rendering_param_t rendering_params;
+        int k;
+        int src_num_comp = cs_num_components(penum->pcs);
+
+         penum->icc_setup.need_decode = false;
+        /* Check if we need to do any decoding.  If yes, then that will slow us down */
+        for (k = 0; k < src_num_comp; k++) {
+            if ( penum->map[k].decoding != sd_none ) {
+                penum->icc_setup.need_decode = true;
+                break;
+            }
+        }
+        /* Define the rendering intents */
+        rendering_params.black_point_comp = BP_ON;
+        rendering_params.object_type = GS_IMAGE_TAG;
+        rendering_params.rendering_intent = penum->pis->renderingintent;
+        if (gs_color_space_is_PSCIE(penum->pcs) && penum->pcs->icc_equivalent != NULL) {
+            pcs = penum->pcs->icc_equivalent;
+        } else {
+            pcs = penum->pcs;
+        }
+        penum->icc_setup.is_lab = pcs->cmm_icc_profile_data->islab;
+        penum->icc_setup.must_halftone = gx_device_must_halftone(penum->dev);
+        penum->icc_setup.has_transfer = gx_has_transfer(penum->pis,
+                                penum->pis->icc_manager->device_profile->num_comps);
+        if (penum->icc_setup.is_lab) penum->icc_setup.need_decode = false;
+        if (penum->icc_link == NULL) {
+            penum->icc_link = gsicc_get_link(penum->pis, pcs, NULL, 
+                &rendering_params, penum->memory, false);
+        }
         return &image_render_color_icc;
     }
 }
@@ -115,25 +148,8 @@
     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);
-}
-
 static void 
-decode_row(gx_image_enum *penum, byte *psrc, int spp, byte *pdes, 
+decode_row(const gx_image_enum *penum, byte *psrc, int spp, byte *pdes, 
                 byte *bufend)
 {
     byte *curr_pos = pdes;
@@ -198,8 +214,6 @@
     color_samples next;		/* next sample value */
     byte *bufend;
     int code = 0, mcode = 0;
-    gsicc_rendering_param_t rendering_params;
-    gsicc_link_t *icc_link;
     gsicc_bufferdesc_t input_buff_desc;
     gsicc_bufferdesc_t output_buff_desc;
     unsigned char *psrc_cm, *psrc_cm_start, *psrc_decode;
@@ -207,18 +221,13 @@
     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);
     int src_num_comp = cs_num_components(penum->pcs);
-    bool need_decode = false;
-    
-   /* Check if we need to do any decoding.  If yes, then that will slow us down */
-   for (k = 0; k < src_num_comp; k++) {
-        if ( penum->map[k].decoding != sd_none ) {
-            need_decode = true;
-            break;
-        }
+    bool need_decode = penum->icc_setup.need_decode;
+    bool must_halftone = penum->icc_setup.must_halftone;
+    bool has_transfer = penum->icc_setup.has_transfer;
+
+    if (penum->icc_link == NULL) {
+        return gs_rethrow(-1, "ICC Link not created during image render color");
     }
     /* Needed for device N */
     memset(&(conc[0]), 0, sizeof(gx_color_value[GX_DEVICE_COLOR_MAX_COMPONENTS]));
@@ -227,26 +236,16 @@
     } else {
         pcs = penum->pcs;
     }
-    if (pcs->cmm_icc_profile_data->islab ) need_decode = false;
     pdevc = &devc1;
     pdevc_next = &devc2;
     /* These used to be set by init clues */
     pdevc->type = gx_dc_type_none;
     pdevc_next->type = gx_dc_type_none;
-    /* Define the rendering intents */
-    rendering_params.black_point_comp = BP_ON;
-    rendering_params.object_type = GS_IMAGE_TAG;
-    rendering_params.rendering_intent = pis->renderingintent;
     if (h == 0)
 	return 0;
-    /* Request the ICC link for the transform that we will need to use */
-    icc_link = gsicc_get_link(pis, pcs, NULL, &rendering_params, pis->memory, false);
-    if (icc_link == NULL) {
-        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 except for potentially a decode. */
-    if (icc_link->is_identity && !need_decode) {
+    if (penum->icc_link->is_identity && !need_decode) {
         /* Fastest case.  No decode or CM needed */
         psrc_cm = (unsigned char *) psrc;
         spp_cm = spp;
@@ -257,7 +256,7 @@
         psrc_cm = gs_alloc_bytes(pis->memory,  w * spp_cm/spp, "image_render_color_icc");
         psrc_cm_start = psrc_cm;
         bufend = psrc_cm +  w * spp_cm/spp;
-        if (icc_link->is_identity) {
+        if (penum->icc_link->is_identity) {
             /* decode only. no CM.  This is slow but does not happen that often */
             decode_row(penum, psrc, spp, psrc_cm, bufend);    
         } else {
@@ -278,18 +277,18 @@
                 /* Need decode and CM.  This is slow but does not happen that often */
                 psrc_decode = gs_alloc_bytes(pis->memory,  w, "image_render_color_icc");
                 decode_row(penum, psrc, spp, psrc_decode, psrc_decode+w);
-                gscms_transform_color_buffer(icc_link, &input_buff_desc, &output_buff_desc, 
-                                         (void*) psrc_decode, (void*) psrc_cm);
+                gscms_transform_color_buffer(penum->icc_link, &input_buff_desc, 
+                                        &output_buff_desc, (void*) psrc_decode, 
+                                        (void*) psrc_cm);
                 gs_free_object(pis->memory, (byte *)psrc_decode, "image_render_color_icc");
             } else {
                 /* CM only. No decode */
-                gscms_transform_color_buffer(icc_link, &input_buff_desc, &output_buff_desc, 
-                                         (void*) psrc, (void*) psrc_cm);
+                gscms_transform_color_buffer(penum->icc_link, &input_buff_desc, 
+                                            &output_buff_desc, (void*) psrc, 
+                                            (void*) psrc_cm);
             }
         }
     }
-    /* Release the link */
-    gsicc_release_link(icc_link);
     pnext = penum->dda.pixel0;
     xrun = xprev = dda_current(pnext.x);
     yrun = yprev = dda_current(pnext.y);

Modified: branches/icc_work/base/gxidata.c
===================================================================
--- branches/icc_work/base/gxidata.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gxidata.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -19,6 +19,7 @@
 #include "gxdevice.h"
 #include "gxcpath.h"
 #include "gximage.h"
+#include "gsicccache.h"
 
 /* Forward declarations */
 static void update_strip(gx_image_enum *penum);
@@ -462,6 +463,9 @@
 	(*scaler->template->release) ((stream_state *) scaler);
 	gs_free_object(mem, scaler, "image scaler state");
     }
+    if (penum->icc_link != NULL) {
+        gsicc_release_link(penum->icc_link);
+    }
     gs_free_object(mem, penum->line, "image line");
     gs_free_object(mem, penum->buffer, "image buffer");
     gx_image_free_enum(&info);

Modified: branches/icc_work/base/gximage.h
===================================================================
--- branches/icc_work/base/gximage.h	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gximage.h	2010-04-06 06:10:12 UTC (rev 11020)
@@ -26,6 +26,7 @@
 #include "gxiclass.h"
 #include "gxiparam.h"
 #include "gxsample.h"
+#include "gscms.h"
 
 /* Define the abstract type for the image enumerator state. */
 /*typedef struct gx_image_enum_s gx_image_enum;*/  /* in gxiclass.h */
@@ -165,6 +166,13 @@
 typedef struct gx_device_rop_texture_s gx_device_rop_texture;
 #endif
 
+typedef struct gx_image_icc_setup_s {
+    bool need_decode; /* used in icc processing */
+    bool is_lab; /* used in icc processing */
+    bool must_halftone; /* used in icc processing */
+    bool has_transfer; /* used in icc processing */
+} gx_image_icc_setup_t;
+
 struct gx_image_enum_s {
     gx_image_enum_common;
     /* We really want the map structure to be long-aligned, */
@@ -272,13 +280,15 @@
     gx_device_color icolor1_val;
     gx_device_color *icolor0;
     gx_device_color *icolor1;
+    gsicc_link_t *icc_link; /* ICC link to avoid recreation with every line */
+    gx_image_icc_setup_t icc_setup;
 };
 
 /* Enumerate the pointers in an image enumerator. */
 #define gx_image_enum_do_ptrs(m)\
   m(0,pis) m(1,pcs) m(2,dev) m(3,buffer) m(4,line)\
-  m(5,clip_dev) m(6,rop_dev) m(7,scaler)
-#define gx_image_enum_num_ptrs 8
+  m(5,clip_dev) m(6,rop_dev) m(7,scaler) m(8,icc_link)
+#define gx_image_enum_num_ptrs 9
 #define private_st_gx_image_enum() /* in gsimage.c */\
   gs_private_st_composite(st_gx_image_enum, gx_image_enum, "gx_image_enum",\
     image_enum_enum_ptrs, image_enum_reloc_ptrs)
@@ -295,7 +305,8 @@
  */
 void gx_image_scale_mask_colors(gx_image_enum *penum,
 				int component_index);
-
+/* Used by icc processing to detect decode cases */
+bool gx_has_transfer(const gs_imager_state *pis, int num_comps);
 /*
  * Do common initialization for processing an ImageType 1 or 4 image.
  * Allocate the enumerator and fill in the following members:

Modified: branches/icc_work/base/gxipixel.c
===================================================================
--- branches/icc_work/base/gxipixel.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gxipixel.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -467,6 +467,7 @@
     penum->buffer = buffer;
     penum->buffer_size = bsize;
     penum->line = 0;
+    penum->icc_link = NULL;
     penum->line_size = 0;
     penum->use_rop = lop != (masked ? rop3_T : rop3_S);
 #ifdef DEBUG
@@ -896,3 +897,22 @@
 	values[1] = 255 - v0;
     }
 }
+
+/* Used to indicate for ICC procesing if we have decoding to do */
+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);
+}
+

Modified: branches/icc_work/base/gxiscale.c
===================================================================
--- branches/icc_work/base/gxiscale.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/gxiscale.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -41,7 +41,12 @@
                                 and keeping data in source color space */
 #include "gxcolor2.h"           /* define of float_color_to_byte_color */
 #include "gscspace.h"           /* Needed for checking is space is CIE */
+#include "gsicccache.h"
+#include "gsiccmanage.h"
 
+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);
 
 static void 
 decode_sample_frac_to_float(gx_image_enum *penum, frac sample_value, gs_client_color *cc, int i);
@@ -61,6 +66,8 @@
    This function just gets interpolation stucture
    initialized and allocates buffer space if needed */
 static irender_proc(image_render_interpolate);
+static irender_proc(image_render_interpolate_icc);
+
 irender_proc_t
 gs_image_class_0_interpolate(gx_image_enum * penum)
 {
@@ -72,6 +79,7 @@
     const gs_color_space *pcs = penum->pcs;
     gs_point dst_xy;
     uint in_size;
+    bool use_icc = false;
 
     if (!penum->interpolate) 
 	return 0;
@@ -81,7 +89,9 @@
 	penum->interpolate = false;
 	return 0;
     }
-
+    if ( penum->pcs->cmm_icc_profile_data != NULL ) {
+        use_icc = true;
+    } 
 /*
  * USE_CONSERVATIVE_INTERPOLATION_RULES is normally NOT defined since
  * the MITCHELL digital filter seems OK as long as we are going out to
@@ -108,8 +118,13 @@
     /* Non-ANSI compilers require the following casts: */
     gs_distance_transform((float)penum->rect.w, (float)penum->rect.h,
 			  &penum->matrix, &dst_xy);
-    iss.BitsPerComponentOut = sizeof(frac) * 8;
-    iss.MaxValueOut = frac_1;
+    if (use_icc) {
+        iss.BitsPerComponentOut = 16;
+        iss.MaxValueOut = 0xffff;
+    } else {
+        iss.BitsPerComponentOut = sizeof(frac) * 8;
+        iss.MaxValueOut = frac_1;
+    }
     iss.WidthOut = (int)ceil(fabs(dst_xy.x));
     iss.HeightOut = fixed2int_pixround_perfect((fixed)((int64_t)(penum->rect.y + penum->rect.h) * 
 						penum->dst_height / penum->Height))
@@ -168,9 +183,14 @@
        }
     } else {
         /* If it has more than 8 bits per color channel then we will go to frac 
-           for the interpolation to mantain precision.  */
-	iss.BitsPerComponentIn = sizeof(frac) * 8;
-	iss.MaxValueIn = frac_1;
+           for the interpolation to mantain precision or 16 bit for icc  */
+        if (use_icc) {
+	    iss.BitsPerComponentIn = 16;
+	    iss.MaxValueIn = 0xffff;
+        } else {
+	    iss.BitsPerComponentIn = sizeof(frac) * 8;
+	    iss.MaxValueIn = frac_1;
+        }
 	in_size = round_up(iss.WidthIn * iss.Colors * sizeof(frac),
 			   align_bitmap_mod);   
         /* Size to allocate space to store the input as frac type */
@@ -244,7 +264,43 @@
     penum->xyi.y = penum->yi0 + fixed2int_pixround_perfect((fixed)((int64_t)penum->rect.y 
 				    * penum->dst_height / penum->Height));
     if_debug0('b', "[b]render=interpolate\n");
-    return &image_render_interpolate;
+    if (use_icc) {
+        /* Set up the link now */
+        const gs_color_space *pcs;
+        gsicc_rendering_param_t rendering_params;
+        int k;
+        int src_num_comp = cs_num_components(penum->pcs);
+
+        penum->icc_setup.need_decode = false;
+        /* Check if we need to do any decoding.  If yes, then that will slow us down */
+        for (k = 0; k < src_num_comp; k++) {
+            if ( penum->map[k].decoding != sd_none ) {
+                penum->icc_setup.need_decode = true;
+                break;
+            }
+        }
+        /* Define the rendering intents */
+        rendering_params.black_point_comp = BP_ON;
+        rendering_params.object_type = GS_IMAGE_TAG;
+        rendering_params.rendering_intent = penum->pis->renderingintent;
+        if (gs_color_space_is_PSCIE(penum->pcs) && penum->pcs->icc_equivalent != NULL) {
+            pcs = penum->pcs->icc_equivalent;
+        } else {
+            pcs = penum->pcs;
+        }
+        penum->icc_setup.is_lab = pcs->cmm_icc_profile_data->islab;
+        if (penum->icc_setup.is_lab) penum->icc_setup.need_decode = false;
+        penum->icc_setup.must_halftone = gx_device_must_halftone(penum->dev);
+        penum->icc_setup.has_transfer = gx_has_transfer(penum->pis,
+                                penum->pis->icc_manager->device_profile->num_comps);
+        if (penum->icc_link == NULL) {
+            penum->icc_link = gsicc_get_link(penum->pis, pcs, NULL, 
+                &rendering_params, penum->memory, false);
+        }
+        return &image_render_interpolate_icc;
+    } else {
+        return &image_render_interpolate;
+    }
 }
 
 /* ------ Rendering for interpolated images ------ */
@@ -641,7 +697,406 @@
     return (h == 0 ? 0 : 1);
 }
 
+/* Interpolation with ICC based source spaces. This is done seperately to
+   enable optimization and avoid the multiple tranformations that occur in
+   the above code */
+static int
+image_render_interpolate_icc(gx_image_enum * penum, const byte * buffer,
+			 int data_x, uint iw, int h, gx_device * dev)
+{
+    stream_image_scale_state *pss = penum->scaler;
+    const gs_imager_state *pis = penum->pis;
+    const gs_color_space *pcs = penum->pcs;
+    gs_logical_operation_t lop = penum->log_op;
+    int c = pss->params.Colors;
+    stream_cursor_read r;
+    stream_cursor_write w;
+    unsigned char index_space;
+    byte *out = penum->line;
+    bool need_decode = penum->icc_setup.need_decode;
+    bool must_halftone = penum->icc_setup.must_halftone;
+    bool has_transfer = penum->icc_setup.has_transfer;
+    bool islab = penum->icc_setup.is_lab;
 
+    if (penum->icc_link == NULL) {
+        return gs_rethrow(-1, "ICC Link not created duringgs_image_class_0_interpolate");
+    }
+    /* buffer for output scan line.  It may be large enough to hold a temporary 
+       converted input scan line also depending upon what occured in 
+       gs_image_class_0_interpolate */
+    if (h != 0) {
+	/* Convert the unpacked data to concrete values in */
+	/* the source buffer. */
+	int sizeofPixelIn = pss->params.BitsPerComponentIn / 8;
+	uint row_size = pss->params.WidthIn * c * sizeofPixelIn;
+	const unsigned char *bdata = buffer + data_x * c * sizeofPixelIn;    /* raw input data */       
+        index_space = 0;
+        /* We have the following cases to worry about 
+          1) Device 8 bit color but not indexed (e.g. ICC).  
+             Apply CMM after interpolation if needed.
+             Also if ICC CIELAB do not do a decode operation
+          2) Indexed 8 bit color.  Get to the base space. We will then be in 
+             the same state as 1.  
+          3) 16 bit not indexed.  Remap after interpolation.  
+          4) Indexed 16bit color.   Get to base space in 16bit form. We 
+             will then be in same state as 3.  
+       */
+	if (sizeofPixelIn == 1) {
+            if (pcs->type->index != gs_color_space_index_Indexed) {
+                /* An issue here is that we may not be "device color" due to 
+                   how the data is encoded.  Need to check for that case here */
+                if (penum->device_color || gs_color_space_is_CIE(pcs) || islab){
+                    /* 8-bit color values, possibly device  indep. or device 
+                       depend., not indexed. Decode range was [0 1] */
+                    if (penum->matrix.xx >= 0) {
+	                /* Use the input data directly. */
+                        /* sets up data in the stream buffere structure */
+	                r.ptr = bdata - 1;   
+                    } else {
+	                /* Mirror the data in X. */
+	                const byte *p = bdata + row_size - c;
+	                byte *q = out;
+	                int i;
+
+	                for (i = 0; i < pss->params.WidthIn; p -= c, q += c, ++i)
+	                    memcpy(q, p, c);
+	                r.ptr = out - 1;
+	                out += round_up(pss->params.WidthIn * c, align_bitmap_mod);
+                    }
+                } else {
+                    /* We need to do some decoding. Data will remain in 8 bits 
+                       This does not occur if color space was CIE encoded.  
+                       Then we do the decode during concretization which occurs 
+                       after interpolation */
+	            int bps = 1;
+	            int dc = penum->spp;
+	            const byte *pdata = bdata;
+	            byte *psrc = (byte *) penum->line;
+	            int i, j;
+                    int dpd = dc;
+	            gs_client_color cc;
+
+                    /* Go backwards through the data */
+                    if (penum->matrix.xx < 0) {
+                      pdata += (pss->params.WidthIn - 1) * dpd;
+                      dpd = - dpd;
+                    }
+	            r.ptr = (byte *) psrc - 1;
+	            for (i = 0; i < pss->params.WidthIn; i++, psrc += c) {
+                        /* Do the decode but remain in 8 bits */
+                        for (j = 0; j < dc;  ++j) {
+                            decode_sample(pdata[j], cc, j);
+                            psrc[j] = float_color_to_byte_color(cc.paint.values[j]);
+                         }
+	                pdata += dpd;
+                    }
+	            out += round_up(pss->params.WidthIn * c,align_bitmap_mod);
+                }
+            } else {
+                /* indexed 8 bit color values, possibly a device indep. or 
+                   device depend. base space. We need to get out of the indexed 
+                   space and into the base color space. Note that we need to 
+                   worry about the decode function for the index values. */
+      	        int bps = penum->bps;
+	        int dc = penum->spp;
+	        const byte *pdata = bdata; /* Input buffer */
+	        unsigned char *psrc = (unsigned char *) penum->line;  /* Output */
+	        int i;
+                int dpd = dc * (bps <= 8 ? 1 : sizeof(frac));
+                float max_range;
+
+                /* Get max of decode range */
+                max_range = (penum->map[0].decode_factor < 0 ? 
+                    penum->map[0].decode_base : 
+                penum->map[0].decode_base + 255.0 * penum->map[0].decode_factor);
+                index_space = 1;
+                /* flip the horizontal direction if indicated by the matrix value */
+                if (penum->matrix.xx < 0) {
+                  pdata += (pss->params.WidthIn - 1) * dpd;
+                  dpd = - dpd;
+                }
+	        r.ptr = (byte *) psrc - 1;
+
+	        for (i = 0; i < pss->params.WidthIn; i++, psrc += c) {
+                    /* Let's get directly to a decoded byte type loaded into 
+                       psrc, and do the interpolation in the source space. Then 
+                       we will do the appropriate remap function after 
+                       interpolation. */
+                    /* First we need to get the properly decoded value. */
+                    float decode_value;
+                    switch ( penum->map[0].decoding )
+                    {
+                        case sd_none:
+                         /* while our indexin is going to be 0 to 255.0 due to 
+                            what is getting handed to us, the range of our 
+                            original data may not have been as such and we may 
+                            need to rescale, to properly lookup at the correct 
+                            location (or do the proc correctly) during the index 
+                            look-up.  This occurs even if decoding was set to 
+                            sd_none.  */
+                            decode_value = (float) pdata[0] * (float)max_range / 255.0; 
+                        break;
+                        case sd_lookup:	
+                            decode_value = 
+                              (float) penum->map[0].decode_lookup[pdata[0] >> 4];
+                        break;
+                        case sd_compute:
+                            decode_value =   
+                              penum->map[0].decode_base + 
+                              ((float) pdata[0]) * penum->map[0].decode_factor;
+			    break;
+		        default:
+			    decode_value = 0; /* Quiet gcc warning. */
+                  }
+                  gs_cspace_indexed_lookup_bytes(pcs, decode_value,psrc);	
+	          pdata += dpd;    /* Can't have just ++ 
+                                   since we could be going backwards */
+                }
+                 /* We need to set the output to the end of the input buffer 
+                    moving it to the next desired word boundary.  This must
+                    be accounted for in the memory allocation of 
+                    gs_image_class_0_interpolate */
+ 	         out += round_up(pss->params.WidthIn*c, align_bitmap_mod);  
+              }
+	} else {
+	    /* More than 8-bits/color values */
+            /* Even in this case we need to worry about an indexed color space. 
+               We need to get to the base color space for the interpolation and
+               then if necessary do the remap to the device space */
+            if (pcs->type->index != gs_color_space_index_Indexed) {
+	        int bps = penum->bps;
+	        int dc = penum->spp;
+	        const byte *pdata = bdata;
+	        frac *psrc = (frac *) penum->line;
+	        int i, j;
+                int dpd = dc * (bps <= 8 ? 1 : sizeof(frac));
+
+                if (penum->matrix.xx < 0) {
+                  pdata += (pss->params.WidthIn - 1) * dpd;
+                  dpd = - dpd;
+                }
+	        r.ptr = (byte *) psrc - 1;
+	        if_debug0('B', "[B]Remap row:\n[B]");
+	        for (i = 0; i < pss->params.WidthIn; i++, psrc += c) {
+                    /* Lets get directly to a frac type loaded into psrc, and do 
+                       the interpolation in the source space. Then we will do 
+                       the appropriate remap function after interpolation. */
+                    for (j = 0; j < dc;  ++j) {
+	                DECODE_FRAC_FRAC(((const frac *)pdata)[j], psrc[j], j);
+                    }
+	            pdata += dpd;
+        #ifdef DEBUG
+	            if (gs_debug_c('B')) {
+	                int ci;
+
+                        for (ci = 0; ci < c; ++ci)
+		            dprintf2("%c%04x", (ci == 0 ? ' ' : ','), psrc[ci]);
+	            }
+        #endif
+                }
+	        out += round_up(pss->params.WidthIn * c * sizeof(frac),
+			        align_bitmap_mod);
+	        if_debug0('B', "\n");
+            } else {
+                /* indexed and more than 8bps.  Need to get to the base space */
+      	        int bps = penum->bps;
+	        int dc = penum->spp;
+	        const byte *pdata = bdata; /* Input buffer */
+	        frac *psrc = (frac *) penum->line;    /* Output buffer */
+	        int i;
+                int dpd = dc * (bps <= 8 ? 1 : sizeof(frac));
+                float decode_value;
+
+                index_space = 1;
+                /* flip the horizontal direction if indicated by the matrix value */
+                if (penum->matrix.xx < 0) {
+                  pdata += (pss->params.WidthIn - 1) * dpd;
+                  dpd = - dpd;
+                }
+	        r.ptr = (byte *) psrc - 1;
+	        for (i = 0; i < pss->params.WidthIn; i++, psrc += c) {
+                    /* Lets get the decoded value. Then we need to do the lookup 
+                       of this */
+                    decode_value = penum->map[i].decode_base +
+                        (((const frac *)pdata)[0]) * penum->map[i].decode_factor;
+                     /* Now we need to do the lookup of this value, and stick it 
+                        in psrc as a frac, which is what the interpolator is 
+                        expecting, since we had more than 8 bits of original 
+                        image data */
+                      gs_cspace_indexed_lookup_frac(pcs, decode_value,psrc);	
+	              pdata += dpd;  
+                }
+                 /* We need to set the output to the end of the input buffer 
+                    moving it to the next desired word boundary.  This must
+                    be accounted for in the memory allocation of 
+                    gs_image_class_0_interpolate */
+ 	         out += round_up(pss->params.WidthIn*c, align_bitmap_mod);                 
+            } /* end of else on indexed */
+	}  /* end of else on more than 8 bps */
+	r.limit = r.ptr + row_size;
+    } else {			/* h == 0 */
+	r.ptr = 0, r.limit = 0;
+	index_space = 0; 
+        /* Quiet gcc warning. We didn't figure out whether it was a real bug. */
+    }
+    /*
+     * Process input and/or collect output.  By construction, the pixels are
+     * 1-for-1 with the device, but the Y coordinate might be inverted.
+     * CM is performed on the entire row.
+     */
+    {
+	int xo = penum->xyi.x;
+	int yo = penum->xyi.y;
+	int width = pss->params.WidthOut;
+	int sizeofPixelOut = pss->params.BitsPerComponentOut / 8;
+        int dy;
+	int bpp = dev->color_info.depth;
+	uint raster = bitmap_raster(width * bpp);
+        unsigned short *psrc_cm, *psrc_cm_start;
+        int spp = pss->params.Colors;
+        int spp_cm;
+        gsicc_bufferdesc_t input_buff_desc;
+        gsicc_bufferdesc_t output_buff_desc;
+        gx_color_index color;
+
+        psrc_cm_start = NULL;
+        if (penum->matrix.yy > 0)
+	    dy = 1;
+	else
+	    dy = -1, yo--;
+	for (;;) {
+	    int ry = yo + penum->line_xy * dy;
+	    int x;
+	    const unsigned short *psrc;
+	    gx_device_color devc;
+	    int status;
+
+	    DECLARE_LINE_ACCUM_COPY(out, bpp, xo);
+	    w.limit = out + width *
+		max(c * sizeofPixelOut, arch_sizeof_color_index) - 1;
+	    w.ptr = w.limit - width * c * sizeofPixelOut;
+	    psrc = (const unsigned short *)(w.ptr + 1);
+            /* This is where the rescale takes place */
+            status = (*pss->template->process)
+		((stream_state *) pss, &r, &w, h == 0);
+	    if (status < 0 && status != EOFC)
+		return_error(gs_error_ioerror);
+	    if (w.ptr == w.limit) {
+		int xe = xo + width;
+
+		if_debug1('B', "[B]Interpolated row %d:\n[B]",
+			  penum->line_xy);
+                /* Take care of CM on the entire interpolated row */
+                spp_cm = pis->icc_manager->device_profile->num_comps;
+                if (penum->icc_link->is_identity) {
+                    /* Fastest case. No CM needed */
+                    psrc_cm = (unsigned short *) psrc;
+                } else {
+                    psrc_cm = (unsigned short *) gs_alloc_bytes(pis->memory, 
+                        sizeof(unsigned short) * width * spp_cm, 
+                        "image_render_interpolate_icc");
+                    psrc_cm_start = psrc_cm;
+                    /* Set up the buffer descriptors. */
+                    gsicc_init_buffer(&input_buff_desc, spp, 2,
+                                  false, false, false, 0, width*spp,
+                                  1, width);
+                    gsicc_init_buffer(&output_buff_desc, spp_cm, 2,
+                                  false, false, false, 0, width * spp_cm,
+                                  1, width);
+                    /* Transform */
+                    gscms_transform_color_buffer(penum->icc_link, &input_buff_desc, 
+                                                &output_buff_desc, (void*) psrc, 
+                                                (void*) psrc_cm);
+                }
+                for (x = xo; x < xe;) {
+#ifdef DEBUG
+		    if (gs_debug_c('B')) {
+			int ci;
+
+			for (ci = 0; ci < spp_cm; ++ci)
+			    dprintf2("%c%04x", (ci == 0 ? ' ' : ','),
+				     psrc_cm[ci]);
+		    }
+#endif    
+                    /* Get the device 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(psrc_cm, &devc, 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, psrc_cm);
+                        /* check if the encoding was successful; we presume failure is rare */
+                        if (color != gx_no_color_index)
+                            color_set_pure(&devc, color);
+                    }
+		    if (color_is_pure(&devc)) {
+			/* Just pack colors into a scan line. */
+			gx_color_index color = devc.colors.pure;
+			/* Skip runs quickly for the common cases. */
+			switch (spp_cm) {
+			    case 1:
+				do {
+				    LINE_ACCUM(color, bpp);
+				    vd_pixel(int2fixed(x), int2fixed(ry), color);
+				    x++, psrc_cm += 1;
+				} while (x < xe && psrc_cm[-1] == psrc_cm[0]);
+				break;
+			    case 3:
+				do {
+				    LINE_ACCUM(color, bpp);
+				    vd_pixel(int2fixed(x), int2fixed(ry), color);
+				    x++, psrc_cm += 3;
+				} while (x < xe && psrc_cm[-3] == psrc_cm[0] &&
+				     psrc_cm[-2] == psrc_cm[1] &&
+				     psrc_cm[-1] == psrc_cm[2]);
+				break;
+			    case 4:
+				do {
+				    LINE_ACCUM(color, bpp);
+				    x++, psrc_cm += 4;
+				} while (x < xe && psrc_cm[-4] == psrc_cm[0] &&
+				     psrc_cm[-3] == psrc_cm[1] && 
+                                     psrc_cm[-2] == psrc_cm[2] &&
+				     psrc_cm[-1] == psrc_cm[3]);
+				break;
+			    default:
+				LINE_ACCUM(color, bpp);
+				x++, psrc_cm += spp_cm;
+			}
+		    } else {
+			int rcode;
+
+			LINE_ACCUM_COPY(dev, out, bpp, xo, x, raster, ry);
+			rcode = gx_fill_rectangle_device_rop(x, ry,
+						     1, 1, &devc, dev, lop);
+			if (rcode < 0)
+			    return rcode;
+			LINE_ACCUM_SKIP(bpp);
+			l_xprev = x + 1;
+			x++, psrc_cm += spp_cm;
+		    }
+		}  /* End on x loop */
+		LINE_ACCUM_COPY(dev, out, bpp, xo, x, raster, ry);
+		/*if_debug1('w', "[w]Y=%d:\n", ry);*/ /* See siscale.c about 'w'. */
+		penum->line_xy++;
+		if_debug0('B', "\n");
+	    }
+	    if ((status == 0 && r.ptr == r.limit) || status == EOFC)
+		break;
+	}
+        /* Free cm buffer, if it was used */
+        if (psrc_cm_start != NULL) {
+            gs_free_object(pis->memory, (byte *)psrc_cm_start, 
+                                        "image_render_interpolate_icc");
+        }
+    }
+    return (h == 0 ? 0 : 1);
+}
+
 /* Decode a 16-bit sample into a floating point color component. 
    This is used for cases where the spatial interpolation function output is 16 bit.
    It is only used here, hence the static declaration for now. */

Modified: branches/icc_work/base/lib.mak
===================================================================
--- branches/icc_work/base/lib.mak	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/base/lib.mak	2010-04-06 06:10:12 UTC (rev 11020)
@@ -512,7 +512,7 @@
 simscale_h=$(GLSRC)simscale.h $(scommon_h) $(sisparam_h)
 gximage_h=$(GLSRC)gximage.h $(gsiparam_h)\
  $(gxcspace_h) $(gxdda_h) $(gxiclass_h) $(gxiparam_h) $(gxsample_h)\
- $(sisparam_h) $(strimpl_h)
+ $(sisparam_h) $(strimpl_h) $(gscms_h)
 gxhldevc_h=$(GLSRC)gxhldevc.h $(gsdcolor_h)
 gsptype2_h=$(GLSRC)gsptype2.h $(gspcolor_h) $(gxhldevc_h) $(gxfixed_h)
 gdevddrw_h=$(GLSRC)gdevddrw.h
@@ -652,7 +652,7 @@
 	$(GLCC) $(GLO_)gswts.$(OBJ) $(C_) $(GLSRC)gswts.c
 
 $(GLOBJ)gxidata.$(OBJ) : $(GLSRC)gxidata.c $(GXERR) $(memory__h)\
- $(gxcpath_h) $(gxdevice_h) $(gximage_h)
+ $(gxcpath_h) $(gxdevice_h) $(gximage_h) $(gsicccache_h)
 	$(GLCC) $(GLO_)gxidata.$(OBJ) $(C_) $(GLSRC)gxidata.c
 
 $(GLOBJ)gxifast.$(OBJ) : $(GLSRC)gxifast.c $(GXERR) $(memory__h) $(gpcheck_h)\
@@ -2343,7 +2343,8 @@
  $(gxarith_h) $(gxcmap_h) $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h)\
  $(gxdevmem_h) $(gxfixed_h) $(gxfrac_h) $(gximage_h) $(gxistate_h)\
  $(gxmatrix_h) $(siinterp_h) $(siscale_h) $(stream_h) $(vdtrace_h)\
- $(gxcindex_h) $(gxcolor2_h) $(gscspace_h)
+ $(gxcindex_h) $(gxcolor2_h) $(gscspace_h) $(gsicccache_h)\
+ $(gsiccmanage_h)
 	$(GLCC) $(GLO_)gxiscale.$(OBJ) $(C_) $(GLSRC)gxiscale.c
 
 # ---------------- Display Postscript / Level 2 support ---------------- #

Modified: branches/icc_work/psi/zcolor.c
===================================================================
--- branches/icc_work/psi/zcolor.c	2010-04-05 23:50:00 UTC (rev 11019)
+++ branches/icc_work/psi/zcolor.c	2010-04-06 06:10:12 UTC (rev 11020)
@@ -5051,11 +5051,11 @@
     return 0;
 }
 
-static int setlabspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, int CIESubst)
+static int setlabspace(i_ctx_t * i_ctx_p, ref *r, int *stage, int *cont, 
+                       int CIESubst)
 {
-
-    /* In this case, we will treat this as an ICC color space, with a CIELAB 16 bit profile */
-
+    /* In this case, we will treat this as an ICC color space, with a 
+       CIELAB 16 bit profile */
     ref labdict;
     int code = 0;
     float                   range_buff[4], white[3], black[3];
@@ -5068,53 +5068,28 @@
     code = array_get(imemory, r, 1, &labdict);
     if (code < 0)
 	return code;
-
-
 /* Get all the parts */
-
-    code = dict_floats_param( imemory, 
-			      &labdict,
-                              "Range",
-                              4,
-                              range_buff,
+    code = dict_floats_param( imemory, &labdict, "Range", 4, range_buff,
                               dflt_range );
     for (i = 0; i < 4 && range_buff[i + 1] >= range_buff[i]; i += 2);
     if (i != 4)
         return_error(e_rangecheck);
-
-     code = dict_floats_param( imemory, 
-			      &labdict,
-                              "BlackPoint",
-                              3,
-                              black,
+    code = dict_floats_param( imemory, &labdict, "BlackPoint", 3, black, 
                               dflt_black );
-
-
-     code = dict_floats_param( imemory, 
-			      &labdict,
-                              "WhitePoint",
-                              3,
-                              white,
+     code = dict_floats_param( imemory, &labdict, "WhitePoint", 3, white,
                               dflt_white );
-
      if (white[0] <= 0 || white[1] != 1.0 || white[2] <= 0)
         return_error(e_rangecheck);
-
     code = seticc_lab(i_ctx_p, white, black, range_buff);
-
     if ( code < 0)
         return gs_rethrow(code, "setting PDF lab color space");
-
     cc.pattern = 0x00;
     for (i=0;i<3;i++) 
         cc.paint.values[i] = 0;
     code = gs_setcolor(igs, &cc);
-
     return code;
-
 }
 
-
 static int validatelabspace(i_ctx_t * i_ctx_p, ref **r)
 {
     int code=0;
@@ -5126,36 +5101,23 @@
     /* Validate parameters, check we have enough operands */
     if (r_size(space) < 2)
 	return_error(e_rangecheck);
-
     code = array_get(imemory, space, 1, &labdict);
     if (code < 0)
 	return code;
-
-    /* Check the white point, which is required */
-
-    /* We have to have a white point */
-    /* Check white point exists, and is an array of three numbers */
+    /* Check the white point, which is required. */
     code = checkWhitePoint(i_ctx_p, &labdict);
     if (code != 0)
 	return code;
-
     /* The rest are optional.  Need to validate though */
-
     code = checkBlackPoint(i_ctx_p, &labdict);
     if (code < 0)
 	return code;
-
     /* Range on a b values */
-
     code = checkrangeab(i_ctx_p, &labdict);
     if (code < 0)
 	return code;
-
     *r = 0;  /* No nested space */
-
     return 0;
-
-
 }
 
 static int labrange(i_ctx_t * i_ctx_p, ref *space, float *ptr)



More information about the gs-commits mailing list