[gs-commits] rev 11847 - in trunk/gs: base psi

alexcher at ghostscript.com alexcher at ghostscript.com
Mon Oct 25 04:39:51 UTC 2010


Author: alexcher
Date: 2010-10-25 04:39:51 +0000 (Mon, 25 Oct 2010)
New Revision: 11847

Modified:
   trunk/gs/base/sjpx_luratech.c
   trunk/gs/base/sjpx_luratech.h
   trunk/gs/psi/msvc32.mak
Log:
Merge rev. 11790, 11795, 11802, 11805, 11809, 11810, 11812, 11813, 11818
into the trunk. JPX files without SMaskInData are now rendered correctly.
Other JPX files are rendered incorrectly. Trunk PostScript code and Jasper
use separate access to opacity and data. Luratech is still using pixel-
interleaved format.


Modified: trunk/gs/base/sjpx_luratech.c
===================================================================
--- trunk/gs/base/sjpx_luratech.c	2010-10-25 04:16:46 UTC (rev 11846)
+++ trunk/gs/base/sjpx_luratech.c	2010-10-25 04:39:51 UTC (rev 11847)
@@ -81,6 +81,20 @@
     return copy_bytes;
 }
 
+static unsigned long
+jp2_get_value(JP2_Decomp_Handle *handle,
+              JP2_Property_Tag tag,
+              short comp,
+              unsigned long def)
+{
+    JP2_Property_Value v;
+
+    if (JP2_Decompress_GetProp(handle, tag, &v, -1, comp) != cJP2_Error_OK)
+        return def;
+
+    return (unsigned long)v;
+}
+
 /* write decompressed data into our image buffer */
 static JP2_Error JP2_Callback_Conv
 s_jpxd_write_data(unsigned char * pucData,
@@ -91,8 +105,7 @@
                                JP2_Callback_Param param)
 {
     stream_jpxd_state *const state = (stream_jpxd_state *) param;
-    unsigned char *p;
-    unsigned long i;
+    int comp = state->clut[sComponent];
 
     /* check input */
     if (ulRow >= state->height) return cJP2_Error_Invalid_Height;
@@ -104,20 +117,142 @@
        from each call in planar buffers and interleave a tile at
        a time into a stipe buffer for output */
 
-    /* todo: handle non-8-bit samples, subsampled components,
-        and Y'CrCb colorspace rotation */
+    if (state->colorspace == gs_jpx_cs_indexed && sComponent == 0) {
+        JP2_Palette_Params *pal;
+        JP2_Error err;
+        int i, c;
+        unsigned char *dst = &state->image[state->stride * ulRow +
+                                           state->ncomp * ulStart + comp];
 
-    p = state->image + state->stride*ulRow + state->ncomp*ulStart;
-    if (state->ncomp == 1)
-        memcpy(p, pucData, ulNum);
-    else for (i = 0; i < ulNum; i++) {
-        p[sComponent] = pucData[i];
+        err = JP2_Decompress_GetPalette(state->handle, &pal);
+        if (err != cJP2_Error_OK)
+            return err;
+
+        if (pal->ulEntries != 256)
+            return cJP2_Error_Invalid_Colorspace;
+
+        for (i = 0; i < ulNum; i++) {
+            unsigned char v = pucData[i];
+            for (c = 0; c < state->ncomp; c++)
+                *dst++ = (unsigned char)pal->ppulPalette[c][v];
+        }
+    }
+    else if (state->ncomp == 1 && comp == 0) {
+        if (state->bpc <= 8) {
+            memcpy(&state->image[state->stride*ulRow + state->ncomp*ulStart],
+                   pucData, ulNum);
+        }
+        else {
+            unsigned long i;
+            unsigned short *src = (unsigned short *)pucData;
+            unsigned char *dst = &state->image[state->stride * ulRow + 2 * ulStart];
+            unsigned int shift = 16 - state->bpc;
+            for (i = 0; i < ulNum; i++) {
+                unsigned short v = *src++ << shift;
+                *dst++ = (v >> 8) & 0xff;
+                *dst++ = v & 0xff;
+            }
+        }
+    }
+    else if (comp >= 0) {
+        unsigned long cw, ch, i, hstep, vstep, x, y;
+        unsigned char *row;
+
+        /* repeat subsampled pixels */
+        cw = jp2_get_value(state->handle, cJP2_Prop_Width, comp, state->width);
+        ch = jp2_get_value(state->handle, cJP2_Prop_Height, comp, state->height);
+        hstep = state->width / cw;
+        vstep = state->height / ch;
+
+        if (state->bpc <= 8) {
+            row = &state->image[state->stride * ulRow * vstep +
+                                state->ncomp * ulStart * hstep + comp];
+            for (y = 0; y < vstep; y++) {
+                unsigned char *p = row;
+                for (i = 0; i < ulNum; i++)
+                    for (x = 0; x < hstep; x++) {
+                        *p = pucData[i];
         p += state->ncomp;
     }
+                row += state->stride;
+            }
+        }
+        else {
+            int shift = 16 - state->bpc;
+            unsigned short *src = (unsigned short *)pucData;
+            row = &state->image[state->stride * ulRow * vstep +
+                                2 * state->ncomp * ulStart * hstep + 2 * comp];
+            for (y = 0; y < vstep; y++) {
+                unsigned char *p = row;
+                for (i = 0; i < ulNum; i++)
+                    for (x = 0; x < hstep; x++) {
+                        unsigned short v = *src++ << shift;
+                        p[0] = (v >> 8) & 0xff;
+                        p[1] = v & 0xff;
+                        p += 2 * state->ncomp;
+                    }
+                row += state->stride;
+            }
+        }
+    }
     return cJP2_Error_OK;
 }
 
+/* convert state->image from YCrCb to RGBa */
 static int
+s_jpxd_ycc_to_rgb(stream_jpxd_state *state)
+{
+    int i, y, x;
+    int is_signed[2];  /* Cr, Cb */
+
+    if (state->ncomp - state->alpha != 3)
+        return -1;
+
+    for (i = 0; i < 2; i++) {
+        int comp = state->clut[i + state->alpha + 1];  /* skip alpha and Y */
+        is_signed[i] = !jp2_get_value(state->handle,
+                                   cJP2_Prop_Signed_Samples, comp, 0);
+    }
+
+    for (y = 0; y < state->height; y++) {
+        unsigned char *row = &state->image[y * state->stride];
+
+        for (x = 0; x < state->stride; x += 3) {
+            int p[3], q[3];
+
+            for (i = 0; i < 3; i++)
+                p[i] = (int)row[x + i];
+
+            if (is_signed[0])
+                p[1] -= 0x80;
+            if (is_signed[1])
+                p[2] -= 0x80;
+
+            /* rotate to RGB */
+#ifdef JPX_USE_IRT
+            q[1] = p[0] - ((p[1] + p[2])>>2);
+            q[0] = p[1] + q[1];
+            q[2] = p[2] + q[1];
+#else
+            q[0] = (int)((double)p[0] + 1.402 * p[2]);
+            q[1] = (int)((double)p[0] - 0.34413 * p[1] - 0.71414 * p[2]);
+            q[2] = (int)((double)p[0] + 1.772 * p[1]);
+#endif
+            /* clamp */
+            for (i = 0; i < 3; i++){
+                if (q[i] < 0) q[i] = 0;
+                else if (q[i] > 0xFF) q[i] = 0xFF;
+            }
+            /* write out the pixel */
+            for (i = 0; i < 3; i++)
+                row[x + i] = (unsigned char)q[i];
+        }
+    }
+
+    return 0;
+}
+
+static int
 s_jpxd_inbuf(stream_jpxd_state *state, stream_cursor_read * pr)
 {
     long in_size = pr->limit - pr->ptr;
@@ -176,8 +311,10 @@
     state->inbuf_size = 0;
     state->inbuf_fill = 0;
 
+    state->alpha = false;
     state->ncomp = 0;
     state->bpc = 0;
+    state->clut = NULL;
     state->width = 0;
     state->height = 0;
     state->stride = 0;
@@ -187,6 +324,41 @@
     return 0;
 }
 
+/* write component mapping into 'clut' and return number of used components
+ */
+static int
+map_components(JP2_Channel_Def_Params *chans, int nchans, int alpha, int clut[])
+{
+    int i, cnt = 0;
+
+    alpha = alpha ? 1 : 0;
+
+    for (i = 0; i < nchans; i++)
+        clut[i] = -1;
+
+    /* always write the alpha channel as first component */
+    if (alpha) {
+        for (i = 0; i < nchans; i++) {
+            if (chans[i].ulType == cJP2_Channel_Type_Opacity) {
+                clut[i] = 0;
+                break;
+            }
+        }
+    }
+
+    for (i = 0; i < nchans; i++) {
+        if (chans[i].ulType == cJP2_Channel_Type_Color) {
+            int assoc = chans[i].ulAssociated -1;
+            if (assoc >= nchans)
+                return -1;
+            clut[i] = assoc + alpha;
+            cnt++;
+        }
+    }
+
+    return cnt + alpha;
+}
+
 /* process a secton of the input and return any decoded data.
    see strimpl.h for return codes.
  */
@@ -199,6 +371,7 @@
     JP2_Property_Value result;
     long in_size = pr->limit - pr->ptr;
     long out_size = pw->limit - pw->ptr;
+    JP2_Colorspace image_cs = cJP2_Colorspace_RGBa;
 
     if (in_size > 0) {
         /* buffer available data */
@@ -209,6 +382,7 @@
         /* we have all the data, decode and return */
 
         if (state->handle == (JP2_Decomp_Handle)NULL) {
+            int ncomp;
             /* initialize decompressor */
             err = JP2_Decompress_Start(&state->handle,
                 /* memory allocator callbacks */
@@ -237,8 +411,24 @@
                 dlprintf1("Luratech JP2 error %d decoding number of image components\n", (int)err);
                 return ERRC;
             }
-            state->ncomp = result;
+            ncomp = result;
 
+            {
+                JP2_Channel_Def_Params *chans = NULL;
+                unsigned long nchans = 0;
+                err = JP2_Decompress_GetChannelDefs(state->handle, &chans, &nchans);
+                if (err != cJP2_Error_OK) {
+                    dlprintf1("Luratech JP2 error %d reading channel definitions\n", (int)err);
+                    return ERRC;
+                }
+                state->clut = malloc((nchans + 1) * sizeof(int)); /* +1 for requested but missing alpha */
+                state->ncomp = map_components(chans, nchans, state->alpha, state->clut);
+                if (state->ncomp < 0) {
+                    dlprintf("Luratech JP2 error decoding channel definitions\n");
+                    return ERRC;
+                }
+            }
+
             if_debug1('w', "[w]jpxd image has %d components\n", state->ncomp);
 
             {
@@ -249,25 +439,48 @@
                     dlprintf1("Luratech JP2 error %d decoding colorspace\n", (int)err);
                     return ERRC;
                 }
+                image_cs = (JP2_Colorspace)result;
                 switch (result) {
-                    case cJP2_Colorspace_Gray: cspace = "gray"; break;
-                    case cJP2_Colorspace_RGBa: cspace = "sRGB"; break;
+                    case cJP2_Colorspace_Gray:
+                        cspace = "gray";
+                        state->colorspace = gs_jpx_cs_gray;
+                        break;
+                    case cJP2_Colorspace_RGBa:
+                        cspace = "sRGB";
+                        state->colorspace = gs_jpx_cs_rgb;
+                        break;
                     case cJP2_Colorspace_RGB_YCCa:
                         cspace = "sRGB YCrCb"; break;
+                        state->colorspace = gs_jpx_cs_rgb;
+                        break;
                     case cJP2_Colorspace_CIE_LABa:
-                        cspace = "CIE Lab"; break;
+                        cspace = "CIE Lab";
+                        state->colorspace = gs_jpx_cs_rgb;
+                        break;
                     case cJP2_Colorspace_ICCa:
-                        cspace = "ICC profile"; break;
+                        cspace = "ICC profile";
+                        state->colorspace = gs_jpx_cs_rgb;
+                        break;
                     case cJP2_Colorspace_Palette_Gray:
-                        cspace = "indexed gray"; break;
+                        cspace = "indexed gray";
+                        state->colorspace = gs_jpx_cs_indexed;
+                        break;
                     case cJP2_Colorspace_Palette_RGBa:
-                        cspace = "indexed sRGB"; break;
+                        cspace = "indexed sRGB";
+                        state->colorspace = gs_jpx_cs_indexed;
+                        break;
                     case cJP2_Colorspace_Palette_RGB_YCCa:
-                        cspace = "indexed sRGB YCrCb"; break;
+                        cspace = "indexed sRGB YCrCb";
+                        state->colorspace = gs_jpx_cs_indexed;
+                        break;
                     case cJP2_Colorspace_Palette_CIE_LABa:
-                        cspace = "indexed CIE Lab"; break;
+                        cspace = "indexed CIE Lab";
+                        state->colorspace = gs_jpx_cs_indexed;
+                        break;
                     case cJP2_Colorspace_Palette_ICCa:
-                        cspace = "indexed with ICC profile"; break;
+                        cspace = "indexed with ICC profile";
+                        state->colorspace = gs_jpx_cs_indexed;
+                        break;
                 }
                 if_debug1('w', "[w]jpxd image colorspace is %s\n", cspace);
             }
@@ -281,7 +494,7 @@
                 int comp;
                 int width, height;
                 int bits, is_signed;
-                for (comp = 0; comp < state->ncomp; comp++) {
+                for (comp = 0; comp < ncomp; comp++) {
                     err= JP2_Decompress_GetProp(state->handle,
                         cJP2_Prop_Width, &result, -1, (short)comp);
                     if (err != cJP2_Error_OK) {
@@ -328,14 +541,14 @@
             if_debug3('w', "[w]jpxd decoding image at %ldx%ld"
                 " with %d bits per component\n",
                 state->width, state->height, state->bpc);
-
         }
 
         if (state->handle != (JP2_Decomp_Handle)NULL &&
                 state->image == NULL) {
 
             /* allocate our output buffer */
-            state->stride = state->width*state->ncomp;
+            int real_bpc = state->bpc > 8 ? 16 : state->bpc;
+            state->stride = (state->width * state->ncomp * real_bpc + 7) / 8;
             state->image = malloc(state->stride*state->height);
             if (state->image == NULL) return ERRC;
 
@@ -360,7 +573,11 @@
                 dlprintf1("Luratech JP2 error %d decoding image data\n", (int)err);
                 return ERRC; /* parsing error */
             }
+
+            if (image_cs == cJP2_Colorspace_RGB_YCCa) {
+                s_jpxd_ycc_to_rgb(state);
         }
+        }
 
         /* copy out available data */
         if (state->image != NULL && out_size > 0) {
@@ -395,6 +612,7 @@
         err = JP2_Decompress_End(state->handle);
         if (state->inbuf) free(state->inbuf);
         if (state->image) free(state->image);
+        if (state->clut) free(state->clut);
     }
 }
 

Modified: trunk/gs/base/sjpx_luratech.h
===================================================================
--- trunk/gs/base/sjpx_luratech.h	2010-10-25 04:16:46 UTC (rev 11846)
+++ trunk/gs/base/sjpx_luratech.h	2010-10-25 04:39:51 UTC (rev 11847)
@@ -45,8 +45,10 @@
     unsigned long inbuf_size;
     unsigned long inbuf_fill;
     gs_jpx_cs colorspace;	/* requested output colorspace */
+    bool alpha; /* return opacity channel */
     int ncomp;			/* number of image components */
     int bpc;			/* sample bits per component */
+    int *clut;			/* channel indices */
     unsigned long width, height;
     unsigned long stride;
     unsigned char *image;	/* decoded image buffer */

Modified: trunk/gs/psi/msvc32.mak
===================================================================
--- trunk/gs/psi/msvc32.mak	2010-10-25 04:16:46 UTC (rev 11846)
+++ trunk/gs/psi/msvc32.mak	2010-10-25 04:39:51 UTC (rev 11847)
@@ -261,23 +261,6 @@
 JPX_LIB=jasper
 !endif
 
-!if "$(JPX_LIB)" == "luratech" || "$(JPX_LIB)" == "lwf_jp2"
-# Set defaults for using the Luratech JP2 implementation
-!ifndef JPXSRCDIR
-# CSDK source code location
-JPXSRCDIR=lwf_jp2
-!endif
-!ifndef JPX_CFLAGS
-# required compiler flags
-JPX_CFLAGS=-DUSE_LWF_JP2 -DWIN32
-!endif
-!else
-# Use jasper by default. See jasper.mak for more information.
-!ifndef JPXSRCDIR
-JPXSRCDIR=jasper
-!endif
-!endif
-
 # Alternatively, you can build a separate DLL
 # and define SHARE_JPX=1 in src/winlib.mak
 
@@ -658,6 +641,29 @@
 SYNC=winsync
 !endif
 
+# Luratech jp2 flags depend on the compiler version
+#
+!if "$(JPX_LIB)" == "luratech" || "$(JPX_LIB)" == "lwf_jp2"
+# Set defaults for using the Luratech JP2 implementation
+!ifndef JPXSRCDIR
+# CSDK source code location
+JPXSRCDIR=lwf_jp2
+!endif
+!ifndef JPX_CFLAGS
+# required compiler flags
+!if $(MSVC_VERSION) <= 7
+JPX_CFLAGS=-DUSE_LWF_JP2 -DWIN32 -DNO_ASSEMBLY
+!else
+JPX_CFLAGS=-DUSE_LWF_JP2 -DWIN32
+!endif
+!endif
+!else
+# Use jasper by default. See jasper.mak for more information.
+!ifndef JPXSRCDIR
+JPXSRCDIR=jasper
+!endif
+!endif
+
 # ------ Devices and features ------ #
 
 # Choose the language feature(s) to include.  See gs.mak for details.



More information about the gs-commits mailing list