src/java.desktop/share/native/libawt/awt/image/awt_ImageRep.c
changeset 47216 71c04702a3d5
parent 26751 70bac69b37c9
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include <string.h>
       
    27 
       
    28 #include "jni.h"
       
    29 #include "jni_util.h"
       
    30 #include "awt_parseImage.h"
       
    31 #include "imageInitIDs.h"
       
    32 #include "sun_awt_image_ImageRepresentation.h"
       
    33 
       
    34 static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
       
    35                        unsigned int *lut2, int numLut2, unsigned char *cvtLut,
       
    36                        int *retNumLut1, int *retTransIdx, int *jniFlagP);
       
    37 
       
    38 static int findIdx(unsigned int rgb, unsigned int *lut, int numLut1);
       
    39 
       
    40 #define ALPHA_MASK    0xff000000
       
    41 #ifndef FALSE
       
    42 #  define FALSE 0
       
    43 #endif
       
    44 #ifndef TRUE
       
    45 #  define TRUE 1
       
    46 #endif
       
    47 
       
    48 #define CHECK_STRIDE(yy, hh, ss)                            \
       
    49     if ((ss) != 0) {                                        \
       
    50         int limit = 0x7fffffff / ((ss) > 0 ? (ss) : -(ss)); \
       
    51         if (limit < (yy) || limit < ((yy) + (hh) - 1)) {    \
       
    52             /* integer oveflow */                           \
       
    53             return JNI_FALSE;                               \
       
    54         }                                                   \
       
    55     }                                                       \
       
    56 
       
    57 #define CHECK_SRC()                                      \
       
    58     do {                                                 \
       
    59         int pixeloffset;                                 \
       
    60         if (off < 0 || off >= srcDataLength) {           \
       
    61             return JNI_FALSE;                            \
       
    62         }                                                \
       
    63         CHECK_STRIDE(0, h, scansize);                    \
       
    64                                                          \
       
    65         /* check scansize */                             \
       
    66         pixeloffset = scansize * (h - 1);                \
       
    67         if ((w - 1) > (0x7fffffff - pixeloffset)) {      \
       
    68             return JNI_FALSE;                            \
       
    69         }                                                \
       
    70         pixeloffset += (w - 1);                          \
       
    71                                                          \
       
    72         if (off > (0x7fffffff - pixeloffset)) {          \
       
    73             return JNI_FALSE;                            \
       
    74         }                                                \
       
    75     } while (0)                                          \
       
    76 
       
    77 #define CHECK_DST(xx, yy)                                \
       
    78     do {                                                 \
       
    79         int soffset = (yy) * sStride;                    \
       
    80         int poffset = (xx) * pixelStride;                \
       
    81         if (poffset > (0x7fffffff - soffset)) {          \
       
    82             return JNI_FALSE;                            \
       
    83         }                                                \
       
    84         poffset += soffset;                              \
       
    85         if (dstDataOff > (0x7fffffff - poffset)) {       \
       
    86             return JNI_FALSE;                            \
       
    87         }                                                \
       
    88         poffset += dstDataOff;                           \
       
    89                                                          \
       
    90         if (poffset < 0 || poffset >= dstDataLength) {   \
       
    91             return JNI_FALSE;                            \
       
    92         }                                                \
       
    93     } while (0)                                          \
       
    94 
       
    95 static jfieldID s_JnumSrcLUTID;
       
    96 static jfieldID s_JsrcLUTtransIndexID;
       
    97 
       
    98 JNIEXPORT void JNICALL
       
    99 Java_sun_awt_image_ImageRepresentation_initIDs(JNIEnv *env, jclass cls) {
       
   100     CHECK_NULL(s_JnumSrcLUTID = (*env)->GetFieldID(env, cls, "numSrcLUT", "I"));
       
   101     CHECK_NULL(s_JsrcLUTtransIndexID = (*env)->GetFieldID(env, cls,
       
   102                                                           "srcLUTtransIndex", "I"));
       
   103 }
       
   104 
       
   105 /*
       
   106  * This routine is used to draw ICM pixels into a default color model
       
   107  */
       
   108 JNIEXPORT jboolean JNICALL
       
   109 Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
       
   110                                                     jint x, jint y, jint w,
       
   111                                                     jint h, jintArray jlut,
       
   112                                                     jbyteArray jpix, jint off,
       
   113                                                     jint scansize,
       
   114                                                     jobject jict)
       
   115 {
       
   116     unsigned char *srcData = NULL;
       
   117     jint srcDataLength;
       
   118     int *dstData;
       
   119     jint dstDataLength;
       
   120     jint dstDataOff;
       
   121     int *dstP, *dstyP;
       
   122     unsigned char *srcyP, *srcP;
       
   123     int *srcLUT = NULL;
       
   124     int yIdx, xIdx;
       
   125     int sStride;
       
   126     int *cOffs;
       
   127     int pixelStride;
       
   128     jobject joffs = NULL;
       
   129     jobject jdata = NULL;
       
   130 
       
   131     if (JNU_IsNull(env, jlut)) {
       
   132         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   133         return JNI_FALSE;
       
   134     }
       
   135 
       
   136     if (JNU_IsNull(env, jpix)) {
       
   137         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   138         return JNI_FALSE;
       
   139     }
       
   140 
       
   141     if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
       
   142         return JNI_FALSE;
       
   143     }
       
   144 
       
   145     if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
       
   146         return JNI_FALSE;
       
   147     }
       
   148 
       
   149     sStride = (*env)->GetIntField(env, jict, g_ICRscanstrID);
       
   150     pixelStride = (*env)->GetIntField(env, jict, g_ICRpixstrID);
       
   151     joffs = (*env)->GetObjectField(env, jict, g_ICRdataOffsetsID);
       
   152     jdata = (*env)->GetObjectField(env, jict, g_ICRdataID);
       
   153 
       
   154     if (JNU_IsNull(env, jdata)) {
       
   155         /* no destination buffer */
       
   156         return JNI_FALSE;
       
   157     }
       
   158 
       
   159     if (JNU_IsNull(env, joffs) || (*env)->GetArrayLength(env, joffs) < 1) {
       
   160         /* invalid data offstes in raster */
       
   161         return JNI_FALSE;
       
   162     }
       
   163 
       
   164     srcDataLength = (*env)->GetArrayLength(env, jpix);
       
   165     dstDataLength = (*env)->GetArrayLength(env, jdata);
       
   166 
       
   167     cOffs = (int *) (*env)->GetPrimitiveArrayCritical(env, joffs, NULL);
       
   168     if (cOffs == NULL) {
       
   169         (*env)->ExceptionClear(env);
       
   170         JNU_ThrowNullPointerException(env, "Null channel offset array");
       
   171         return JNI_FALSE;
       
   172     }
       
   173 
       
   174     dstDataOff = cOffs[0];
       
   175 
       
   176     /* the offset array is not needed anymore and can be released */
       
   177     (*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
       
   178     joffs = NULL;
       
   179     cOffs = NULL;
       
   180 
       
   181     /* do basic validation: make sure that offsets for
       
   182     * first pixel and for last pixel are safe to calculate and use */
       
   183     CHECK_STRIDE(y, h, sStride);
       
   184     CHECK_STRIDE(x, w, pixelStride);
       
   185 
       
   186     CHECK_DST(x, y);
       
   187     CHECK_DST(x + w -1, y + h - 1);
       
   188 
       
   189     /* check source array */
       
   190     CHECK_SRC();
       
   191 
       
   192     srcLUT = (int *) (*env)->GetPrimitiveArrayCritical(env, jlut, NULL);
       
   193     if (srcLUT == NULL) {
       
   194         (*env)->ExceptionClear(env);
       
   195         JNU_ThrowNullPointerException(env, "Null IndexColorModel LUT");
       
   196         return JNI_FALSE;
       
   197     }
       
   198 
       
   199     srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
       
   200                                                                   NULL);
       
   201     if (srcData == NULL) {
       
   202         (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
       
   203         (*env)->ExceptionClear(env);
       
   204         JNU_ThrowNullPointerException(env, "Null data array");
       
   205         return JNI_FALSE;
       
   206     }
       
   207 
       
   208     dstData = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
       
   209     if (dstData == NULL) {
       
   210         (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
       
   211         (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
       
   212         (*env)->ExceptionClear(env);
       
   213         JNU_ThrowNullPointerException(env, "Null tile data array");
       
   214         return JNI_FALSE;
       
   215     }
       
   216 
       
   217     dstyP = dstData + dstDataOff + y*sStride + x*pixelStride;
       
   218     srcyP = srcData + off;
       
   219     for (yIdx = 0; yIdx < h; yIdx++, srcyP += scansize, dstyP+=sStride) {
       
   220         srcP = srcyP;
       
   221         dstP = dstyP;
       
   222         for (xIdx = 0; xIdx < w; xIdx++, dstP+=pixelStride) {
       
   223             *dstP = srcLUT[*srcP++];
       
   224         }
       
   225     }
       
   226 
       
   227     /* Release the locked arrays */
       
   228     (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,  JNI_ABORT);
       
   229     (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
       
   230     (*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
       
   231 
       
   232     return JNI_TRUE;
       
   233 }
       
   234 
       
   235 JNIEXPORT jboolean JNICALL
       
   236 Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
       
   237                                                   jint x, jint y, jint w,
       
   238                                                   jint h, jintArray jlut,
       
   239                                                   jint transIdx, jint numLut,
       
   240                                                   jobject jicm,
       
   241                                                   jbyteArray jpix, jint off,
       
   242                                                   jint scansize,
       
   243                                                   jobject jbct, jint dstDataOff)
       
   244 {
       
   245     unsigned int *srcLUT = NULL;
       
   246     unsigned int *newLUT = NULL;
       
   247     int sStride;
       
   248     int pixelStride;
       
   249     int mapSize;
       
   250     jobject jdata = NULL;
       
   251     jobject jnewlut = NULL;
       
   252     jint srcDataLength;
       
   253     jint dstDataLength;
       
   254     unsigned char *srcData;
       
   255     unsigned char *dstData;
       
   256     unsigned char *dataP;
       
   257     unsigned char *pixP;
       
   258     int i;
       
   259     int j;
       
   260     int newNumLut;
       
   261     int newTransIdx;
       
   262     int jniFlag = JNI_ABORT;
       
   263     unsigned char *ydataP;
       
   264     unsigned char *ypixP;
       
   265     unsigned char cvtLut[256];
       
   266 
       
   267     if (JNU_IsNull(env, jlut)) {
       
   268         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   269         return JNI_FALSE;
       
   270     }
       
   271 
       
   272     if (JNU_IsNull(env, jpix)) {
       
   273         JNU_ThrowNullPointerException(env, "NullPointerException");
       
   274         return JNI_FALSE;
       
   275     }
       
   276 
       
   277     if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
       
   278         return JNI_FALSE;
       
   279     }
       
   280 
       
   281     if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
       
   282         return JNI_FALSE;
       
   283     }
       
   284 
       
   285 
       
   286     sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID);
       
   287     pixelStride =(*env)->GetIntField(env, jbct, g_BCRpixstrID);
       
   288     jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
       
   289     jnewlut = (*env)->GetObjectField(env, jicm, g_ICMrgbID);
       
   290     mapSize = (*env)->GetIntField(env, jicm, g_ICMmapSizeID);
       
   291 
       
   292     if (numLut < 0 || numLut > 256 || mapSize < 0 || mapSize > 256) {
       
   293         /* Ether old or new ICM has a palette that exceeds capacity
       
   294            of byte data type, so we have to convert the image data
       
   295            to default representation.
       
   296         */
       
   297         return JNI_FALSE;
       
   298     }
       
   299 
       
   300     if (JNU_IsNull(env, jdata)) {
       
   301         /* no destination buffer */
       
   302         return JNI_FALSE;
       
   303     }
       
   304 
       
   305     srcDataLength = (*env)->GetArrayLength(env, jpix);
       
   306     dstDataLength = (*env)->GetArrayLength(env, jdata);
       
   307 
       
   308     CHECK_STRIDE(y, h, sStride);
       
   309     CHECK_STRIDE(x, w, pixelStride);
       
   310 
       
   311     CHECK_DST(x, y);
       
   312     CHECK_DST(x + w -1, y + h - 1);
       
   313 
       
   314     /* check source array */
       
   315     CHECK_SRC();
       
   316 
       
   317     srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut,
       
   318                                                                 NULL);
       
   319     if (srcLUT == NULL) {
       
   320         /* out of memory error already thrown */
       
   321         return JNI_FALSE;
       
   322     }
       
   323 
       
   324     newLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jnewlut,
       
   325                                                                 NULL);
       
   326     if (newLUT == NULL) {
       
   327         (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
       
   328                                               JNI_ABORT);
       
   329         /* out of memory error already thrown */
       
   330         return JNI_FALSE;
       
   331     }
       
   332 
       
   333     newNumLut = numLut;
       
   334     newTransIdx = transIdx;
       
   335     if (compareLUTs(srcLUT, numLut, transIdx, newLUT, mapSize,
       
   336                     cvtLut, &newNumLut, &newTransIdx, &jniFlag) == FALSE) {
       
   337         /* Need to convert to ICR */
       
   338         (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
       
   339                                               JNI_ABORT);
       
   340         (*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
       
   341         return JNI_FALSE;
       
   342     }
       
   343 
       
   344     /* Don't need these any more */
       
   345     (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, jniFlag);
       
   346     (*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
       
   347 
       
   348     if (newNumLut != numLut) {
       
   349         /* Need to write back new number of entries in lut */
       
   350         (*env)->SetIntField(env, cls, s_JnumSrcLUTID, newNumLut);
       
   351     }
       
   352 
       
   353     if (newTransIdx != transIdx) {
       
   354         (*env)->SetIntField(env, cls, s_JsrcLUTtransIndexID, newTransIdx);
       
   355     }
       
   356 
       
   357     srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
       
   358                                                                   NULL);
       
   359     if (srcData == NULL) {
       
   360         /* out of memory error already thrown */
       
   361         return JNI_FALSE;
       
   362     }
       
   363 
       
   364     dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
       
   365                                                                   NULL);
       
   366     if (dstData == NULL) {
       
   367         (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
       
   368         /* out of memory error already thrown */
       
   369         return JNI_FALSE;
       
   370     }
       
   371 
       
   372     ydataP = dstData + dstDataOff + y*sStride + x*pixelStride;
       
   373     ypixP  = srcData + off;
       
   374 
       
   375     for (i=0; i < h; i++) {
       
   376         dataP = ydataP;
       
   377         pixP = ypixP;
       
   378         for (j=0; j < w; j++) {
       
   379             *dataP = cvtLut[*pixP];
       
   380             dataP += pixelStride;
       
   381             pixP++;
       
   382         }
       
   383         ydataP += sStride;
       
   384         ypixP  += scansize;
       
   385     }
       
   386 
       
   387     (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
       
   388     (*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
       
   389 
       
   390     return JNI_TRUE;
       
   391 }
       
   392 
       
   393 static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
       
   394                        unsigned int *lut2, int numLut2, unsigned char *cvtLut,
       
   395                        int *retNumLut1, int *retTransIdx, int *jniFlagP)
       
   396 {
       
   397     int i;
       
   398     int idx;
       
   399     int newTransIdx = -1;
       
   400     unsigned int rgb;
       
   401     int changed = FALSE;
       
   402     int maxSize = (numLut1 > numLut2 ? numLut1 : numLut2);
       
   403 
       
   404     *jniFlagP = JNI_ABORT;
       
   405 
       
   406     for (i=0; i < maxSize; i++) {
       
   407         cvtLut[i] = i;
       
   408     }
       
   409 
       
   410     for (i=0; i < numLut2; i++) {
       
   411         /* If this slot in new palette is different from the
       
   412          * same slot in current palette, then we try to find
       
   413          * this color in other slots. On failure, add this color
       
   414          * to current palette.
       
   415          */
       
   416         if ((i >= numLut1) ||
       
   417             (lut1[i] != lut2[i]))
       
   418         {
       
   419             rgb = lut2[i];
       
   420             /* Transparent */
       
   421             if ((rgb & ALPHA_MASK) == 0) {
       
   422                 if (transIdx == -1) {
       
   423                     if (numLut1 < 256) {
       
   424                         cvtLut[i] = numLut1;
       
   425                         newTransIdx = i;
       
   426                         transIdx = i;
       
   427                         numLut1++;
       
   428                         changed = TRUE;
       
   429                     }
       
   430                     else {
       
   431                         return FALSE;
       
   432                     }
       
   433                 }
       
   434                 cvtLut[i] = transIdx;
       
   435             }
       
   436             else {
       
   437                 if ((idx = findIdx(rgb, lut1, numLut1)) == -1) {
       
   438                     if (numLut1 < 256) {
       
   439                         lut1[numLut1] = rgb;
       
   440                         cvtLut[i] = numLut1;
       
   441                         numLut1++;
       
   442                         changed = TRUE;
       
   443                     }
       
   444                     else {
       
   445                         /* Bad news...  need to convert image */
       
   446                         return FALSE;
       
   447                     }
       
   448                 } else {
       
   449                     cvtLut[i] = idx;
       
   450                 }
       
   451             }
       
   452         }
       
   453     }
       
   454 
       
   455     if (changed) {
       
   456         *jniFlagP = 0;
       
   457         *retNumLut1 = numLut1;
       
   458         if (newTransIdx != -1) {
       
   459             *retTransIdx = newTransIdx;
       
   460         }
       
   461     }
       
   462     return TRUE;
       
   463 }
       
   464 
       
   465 static int findIdx(unsigned int rgb, unsigned int *lut, int numLut) {
       
   466     int i;
       
   467 
       
   468     if ((rgb&0xff000000)==0) {
       
   469         for (i=0; i < numLut; i++) {
       
   470             if ((lut[i]&0xff000000)==0) return i;
       
   471         }
       
   472     }
       
   473     else {
       
   474         for (i=0; i < numLut; i++) {
       
   475             if (lut[i] == rgb) return i;
       
   476         }
       
   477     }
       
   478     return -1;
       
   479 }