1 /*
2  * Copyright (c) 1997, 2016, 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 <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include "sun_awt_image_ImagingLib.h"
30 #include "java_awt_Transparency.h"
31 #include "java_awt_image_AffineTransformOp.h"
32 #include "java_awt_image_BufferedImage.h"
33 #include "java_awt_color_ColorSpace.h"
34 #include "java_awt_image_ConvolveOp.h"
35 #include "sun_awt_image_IntegerComponentRaster.h"
36 #include "awt_ImagingLib.h"
37 #include "awt_parseImage.h"
38 #include "imageInitIDs.h"
39 #include <jni.h>
40 #include <jni_util.h>
41 #include <assert.h>
42 #include "awt_Mlib.h"
43 #include "gdefs.h"
44 #include "safe_alloc.h"
45 #include "safe_math.h"
46 
47 /***************************************************************************
48  *                               Definitions                               *
49  ***************************************************************************/
50 #define jio_fprintf fprintf
51 
52 #ifndef TRUE
53 #define TRUE 1
54 #endif /* TRUE */
55 
56 #ifndef FALSE
57 #define FALSE 0
58 #endif /* FALSE */
59 
60 #define TYPE_CUSTOM         java_awt_image_BufferedImage_TYPE_CUSTOM
61 #define TYPE_INT_RGB        java_awt_image_BufferedImage_TYPE_INT_RGB
62 #define TYPE_INT_ARGB       java_awt_image_BufferedImage_TYPE_INT_ARGB
63 #define TYPE_INT_ARGB_PRE   java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE
64 #define TYPE_INT_BGR        java_awt_image_BufferedImage_TYPE_INT_BGR
65 #define TYPE_4BYTE_ABGR     java_awt_image_BufferedImage_TYPE_4BYTE_ABGR
66 #define TYPE_4BYTE_ABGR_PRE java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE
67 
68 /* (alpha*color)>>nbits + alpha>>(nbits-1) */
69 #define BLEND(color, alpha, alphaNbits) \
70     ((((alpha)*(color))>>(alphaNbits)) + ((alpha) >> ((alphaNbits)-1)))
71 
72     /* ((color - (alpha>>(nBits-1)))<<nBits)/alpha */
73 #define UNBLEND(color, alpha, alphaNbits) \
74     ((((color)-((alpha)>>((alphaNbits)-1)))<<(alphaNbits))/(alpha))
75 
76 /* Enumeration of all of the mlib functions used */
77 typedef enum {
78     MLIB_CONVMxN,
79     MLIB_AFFINE,
80     MLIB_LOOKUP,
81     MLIB_CONVKERNCVT
82 } mlibTypeE_t;
83 
84 typedef struct {
85     int dataType;           /* One of BYTE_DATA_TYPE, SHORT_DATA_TYPE, */
86     int needToCopy;
87     int cvtSrcToDefault;    /* If TRUE, convert the src to def CM (pre?) */
88     int allocDefaultDst;    /* If TRUE, alloc def CM dst buffer */
89     int cvtToDst;           /* If TRUE, convert dst buffer to Dst CM */
90     int addAlpha;
91 } mlibHintS_t;
92 
93 /***************************************************************************
94  *                     Static Variables/Structures                         *
95  ***************************************************************************/
96 
97 static mlibSysFnS_t sMlibSysFns = {
98     NULL, // placeholder for j2d_mlib_ImageCreate
99     NULL, // placeholder for j2d_mlib_ImageCreateStruct
100     NULL, // placeholder for j2d_mlib_ImageDelete
101 };
102 
103 static mlibFnS_t sMlibFns[] = {
104     {NULL, "j2d_mlib_ImageConvMxN"},
105     {NULL, "j2d_mlib_ImageAffine"},
106     {NULL, "j2d_mlib_ImageLookUp"},
107     {NULL, "j2d_mlib_ImageConvKernelConvert"},
108     {NULL, NULL},
109 };
110 
111 static int s_timeIt = 0;
112 static int s_printIt = 0;
113 static int s_startOff = 0;
114 static int s_nomlib = 0;
115 
116 /***************************************************************************
117  *                          Static Function Prototypes                     *
118  ***************************************************************************/
119 
120 static int
121 allocateArray(JNIEnv *env, BufImageS_t *imageP,
122               mlib_image **mlibImagePP, void **dataPP, int isSrc,
123               int cvtToDefault, int addAlpha);
124 static int
125 allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
126                     mlib_image **mlibImagePP, void **dataPP, int isSrc);
127 
128 static void
129 freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,
130           void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,
131           void *dstdataP);
132 static void
133 freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,
134           void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,
135           void *dstdataP);
136 
137 static int
138 storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
139                 mlib_image *mlibImP);
140 
141 static int
142 storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,
143                 mlib_image *mlibImP);
144 
145 static int
146 storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
147               mlib_image *mlibImP);
148 
149 static int
150 colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors);
151 
152 static int
153 setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
154               int expandICM, int useAlpha,
155               int premultiply, mlibHintS_t *hintP);
156 
157 
158 static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP);
159 static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
160                            unsigned char *outDataP);
161 static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
162                            unsigned char *outDataP);
163 static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
164                            unsigned char *outDataP);
165 static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
166                                   int component, unsigned char *outDataP,
167                                   int forceAlpha);
168 static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
169                                   int component, unsigned char *outDataP,
170                                   int forceAlpha);
171 static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
172                                   int component, unsigned char *outDataP,
173                                   int forceAlpha);
174 static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
175                         unsigned char *outDataP);
176 static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
177                         unsigned char *outDataP);
178 static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
179                         unsigned char *outDataP);
180 static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
181                                int component, unsigned char *outDataP,
182                                int supportsAlpha);
183 static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
184                                int component, unsigned char *outDataP,
185                                int supportsAlpha);
186 static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
187                                int component, unsigned char *outDataP,
188                                int supportsAlpha);
189 
190 mlib_start_timer start_timer = NULL;
191 mlib_stop_timer stop_timer = NULL;
192 
193 /***************************************************************************
194  *                          Debugging Definitions                          *
195  ***************************************************************************/
196 #ifdef DEBUG
197 
198 static void
printMedialibError(int status)199 printMedialibError(int status) {
200     switch(status) {
201     case MLIB_FAILURE:
202         jio_fprintf(stderr, "failure\n");
203         break;
204     case MLIB_NULLPOINTER:
205         jio_fprintf(stderr, "null pointer\n");
206         break;
207     case MLIB_OUTOFRANGE:
208         jio_fprintf (stderr, "out of range\n");
209         break;
210     default:
211         jio_fprintf (stderr, "medialib error\n");
212         break;
213     }
214 }
215 #else /* ! DEBUG */
216 #  define printMedialibError(x)
217 
218 #endif /* ! DEBUG */
219 
220 static int
getMlibEdgeHint(jint edgeHint)221 getMlibEdgeHint(jint edgeHint) {
222     switch (edgeHint) {
223     case java_awt_image_ConvolveOp_EDGE_NO_OP:
224         return MLIB_EDGE_DST_COPY_SRC;
225     case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:
226     default:
227         return MLIB_EDGE_DST_FILL_ZERO;
228     }
229 }
230 
231 /*
232  * We have to make sure that awt_setPixels can be safely applied to the given pair of
233  * raster and mlib image.
234  *
235  * In particular, make sure that
236  *  - dimension is the same
237  *  - number of channels in mlib image corresponds to the number of bands in the raster
238  *  - sample size in image and raster are the same.
239  *
240  * Returns:
241  *  -1 to indicate failure,
242  *   1 to indicate success
243  */
setPixelsFormMlibImage(JNIEnv * env,RasterS_t * rasterP,mlib_image * img)244 static int setPixelsFormMlibImage(JNIEnv *env, RasterS_t *rasterP, mlib_image* img) {
245     if (rasterP->width != img->width || rasterP->height != img->height) {
246         /* dimension does not match */
247         return -1;
248     }
249 
250     if (rasterP->numBands != img->channels) {
251         /* number of bands does not match */
252         return -1;
253     }
254 
255     switch (rasterP->dataType) {
256     case BYTE_DATA_TYPE:
257         if (img->type != MLIB_BYTE) {
258             return -1;
259         }
260         break;
261     case SHORT_DATA_TYPE:
262         if (img->type != MLIB_SHORT && img->type != MLIB_USHORT) {
263             return -1;
264         }
265         break;
266     default:
267         /* awt_setPixels does not support such rasters */
268         return -1;
269     }
270 
271     return awt_setPixels(env, rasterP, mlib_ImageGetData(img));
272 }
273 
274 /***************************************************************************
275  *                          External Functions                             *
276  ***************************************************************************/
277 JNIEXPORT jint JNICALL
Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv * env,jobject this,jobject jsrc,jobject jdst,jobject jkernel,jint edgeHint)278 Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this,
279                                          jobject jsrc, jobject jdst,
280                                          jobject jkernel, jint edgeHint)
281 {
282     void *sdata, *ddata;
283     mlib_image *src;
284     mlib_image *dst;
285     int i, scale;
286     mlib_d64 *dkern;
287     mlib_s32 *kdata;
288     int klen;
289     float kmax;
290     mlib_s32 cmask;
291     mlib_status status;
292     int retStatus = 1;
293     float *kern;
294     BufImageS_t *srcImageP, *dstImageP;
295     jobject jdata;
296     int kwidth;
297     int kheight;
298     int w, h;
299     int x, y;
300     mlibHintS_t hint;
301     int nbands;
302 
303     /* This function requires a lot of local refs ??? Is 64 enough ??? */
304     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
305         return 0;
306 
307     if (s_nomlib) return 0;
308     if (s_timeIt)     (*start_timer)(3600);
309 
310     kwidth  = (*env)->GetIntField(env, jkernel, g_KernelWidthID);
311     kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID);
312     jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID);
313     klen  = (*env)->GetArrayLength(env, jdata);
314     kern  = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
315     if (kern == NULL) {
316         /* out of memory exception already thrown */
317         return 0;
318     }
319 
320     if ((kwidth&0x1) == 0) {
321         /* Kernel has even width */
322         w = kwidth+1;
323     }
324     else {
325         w = kwidth;
326     }
327     if ((kheight&0x1) == 0) {
328         /* Kernel has even height */
329         h = kheight+1;
330     }
331     else {
332         h = kheight;
333     }
334 
335     dkern = NULL;
336     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) {
337         dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64));
338     }
339     if (dkern == NULL) {
340         (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
341         return 0;
342     }
343 
344     /* Need to flip and find max value of the kernel.
345      * Also, save the kernel values as mlib_d64 values.
346      * The flip is to operate correctly with medialib,
347      * which doesn't do the mathemetically correct thing,
348      * i.e. it doesn't rotate the kernel by 180 degrees.
349      * REMIND: This should perhaps be done at the Java
350      * level by ConvolveOp.
351      * REMIND: Should the max test be looking at absolute
352      * values?
353      * REMIND: What if klen != kheight * kwidth?
354      */
355     kmax = kern[klen-1];
356     i = klen-1;
357     for (y=0; y < kheight; y++) {
358         for (x=0; x < kwidth; x++, i--) {
359             dkern[y*w+x] = (mlib_d64) kern[i];
360             if (kern[i] > kmax) {
361                 kmax = kern[i];
362             }
363         }
364     }
365 
366     (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
367 
368     if (kmax > 1<<16) {
369         /* We can only handle 16 bit max */
370         free(dkern);
371         return 0;
372     }
373 
374 
375     /* Parse the source image */
376     if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {
377         /* Can't handle any custom images */
378         free(dkern);
379         return 0;
380     }
381 
382     /* Parse the destination image */
383     if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {
384         /* Can't handle any custom images */
385         awt_freeParsedImage(srcImageP, TRUE);
386         free(dkern);
387         return 0;
388     }
389 
390     nbands = setImageHints(env, srcImageP, dstImageP, TRUE, TRUE,
391                         FALSE, &hint);
392     if (nbands < 1) {
393         /* Can't handle any custom images */
394         awt_freeParsedImage(srcImageP, TRUE);
395         awt_freeParsedImage(dstImageP, TRUE);
396         free(dkern);
397         return 0;
398     }
399     /* Allocate the arrays */
400     if (allocateArray(env, srcImageP, &src, &sdata, TRUE,
401                       hint.cvtSrcToDefault, hint.addAlpha) < 0) {
402         /* Must be some problem */
403         awt_freeParsedImage(srcImageP, TRUE);
404         awt_freeParsedImage(dstImageP, TRUE);
405         free(dkern);
406         return 0;
407     }
408     if (allocateArray(env, dstImageP, &dst, &ddata, FALSE,
409                       hint.cvtToDst, FALSE) < 0) {
410         /* Must be some problem */
411         freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
412         awt_freeParsedImage(srcImageP, TRUE);
413         awt_freeParsedImage(dstImageP, TRUE);
414         free(dkern);
415         return 0;
416     }
417 
418     kdata = NULL;
419     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) {
420         kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32));
421     }
422     if (kdata == NULL) {
423         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
424         awt_freeParsedImage(srcImageP, TRUE);
425         awt_freeParsedImage(dstImageP, TRUE);
426         free(dkern);
427         return 0;
428     }
429 
430     if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h,
431                                     mlib_ImageGetType(src)) != MLIB_SUCCESS) {
432         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
433         awt_freeParsedImage(srcImageP, TRUE);
434         awt_freeParsedImage(dstImageP, TRUE);
435         free(dkern);
436         free(kdata);
437         return 0;
438     }
439 
440     if (s_printIt) {
441         fprintf(stderr, "Orig Kernel(len=%d):\n",klen);
442         for (y=kheight-1; y >= 0; y--) {
443             for (x=kwidth-1; x >= 0; x--) {
444                 fprintf(stderr, "%g ", dkern[y*w+x]);
445             }
446             fprintf(stderr, "\n");
447         }
448         fprintf(stderr, "New Kernel(scale=%d):\n", scale);
449         for (y=kheight-1; y >= 0; y--) {
450             for (x=kwidth-1; x >= 0; x--) {
451                 fprintf(stderr, "%d ", kdata[y*w+x]);
452             }
453             fprintf(stderr, "\n");
454         }
455     }
456 
457     cmask = (1<<src->channels)-1;
458     status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
459                                (w-1)/2, (h-1)/2, scale, cmask,
460                                getMlibEdgeHint(edgeHint));
461 
462     if (status != MLIB_SUCCESS) {
463         printMedialibError(status);
464         retStatus = 0;
465     }
466 
467     if (s_printIt) {
468         unsigned int *dP;
469         if (s_startOff != 0) {
470             printf("Starting at %d\n", s_startOff);
471         }
472         if (sdata == NULL) {
473             dP = (unsigned int *) mlib_ImageGetData(src);
474         }
475         else {
476             dP = (unsigned int *) sdata;
477         }
478         printf("src is\n");
479         for (i=0; i < 20; i++) {
480             printf("%x ",dP[s_startOff+i]);
481         }
482         printf("\n");
483         if (ddata == NULL) {
484             dP = (unsigned int *)mlib_ImageGetData(dst);
485         }
486         else {
487             dP = (unsigned int *) ddata;
488         }
489         printf("dst is \n");
490         for (i=0; i < 20; i++) {
491             printf("%x ",dP[s_startOff+i]);
492         }
493         printf("\n");
494     }
495 
496     /* Means that we couldn't write directly into the destination buffer */
497     if (ddata == NULL) {
498 
499         /* Need to store it back into the array */
500         if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
501             /* Error */
502             retStatus = 0;
503         }
504     }
505 
506     /* Release the pinned memory */
507     freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
508     awt_freeParsedImage(srcImageP, TRUE);
509     awt_freeParsedImage(dstImageP, TRUE);
510     free(dkern);
511     free(kdata);
512 
513     if (s_timeIt) (*stop_timer)(3600, 1);
514 
515     return retStatus;
516 }
517 
518 JNIEXPORT jint JNICALL
Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv * env,jobject this,jobject jsrc,jobject jdst,jobject jkernel,jint edgeHint)519 Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this,
520                                              jobject jsrc, jobject jdst,
521                                              jobject jkernel, jint edgeHint)
522 {
523     mlib_image *src;
524     mlib_image *dst;
525     int i, scale;
526     mlib_d64 *dkern;
527     mlib_s32 *kdata;
528     int klen;
529     float kmax;
530     int retStatus = 1;
531     mlib_status status;
532     mlib_s32 cmask;
533     void *sdata;
534     void *ddata;
535     RasterS_t *srcRasterP;
536     RasterS_t *dstRasterP;
537     int kwidth;
538     int kheight;
539     int w, h;
540     int x, y;
541     jobject jdata;
542     float *kern;
543 
544     /* This function requires a lot of local refs ??? Is 64 enough ??? */
545     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
546         return 0;
547 
548     if (s_nomlib) return 0;
549     if (s_timeIt)     (*start_timer)(3600);
550 
551     kwidth  = (*env)->GetIntField(env, jkernel, g_KernelWidthID);
552     kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID);
553     jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID);
554     klen  = (*env)->GetArrayLength(env, jdata);
555     kern  = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
556     if (kern == NULL) {
557         /* out of memory exception already thrown */
558         return 0;
559     }
560 
561     if ((kwidth&0x1) == 0) {
562         /* Kernel has even width */
563         w = kwidth+1;
564     }
565     else {
566         w = kwidth;
567     }
568     if ((kheight&0x1) == 0) {
569         /* Kernel has even height */
570         h = kheight+1;
571     }
572     else {
573         h = kheight;
574     }
575 
576     dkern = NULL;
577     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) {
578         dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64));
579     }
580     if (dkern == NULL) {
581         (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
582         return 0;
583     }
584 
585     /* Need to flip and find max value of the kernel.
586      * Also, save the kernel values as mlib_d64 values.
587      * The flip is to operate correctly with medialib,
588      * which doesn't do the mathemetically correct thing,
589      * i.e. it doesn't rotate the kernel by 180 degrees.
590      * REMIND: This should perhaps be done at the Java
591      * level by ConvolveOp.
592      * REMIND: Should the max test be looking at absolute
593      * values?
594      * REMIND: What if klen != kheight * kwidth?
595      */
596     kmax = kern[klen-1];
597     i = klen-1;
598     for (y=0; y < kheight; y++) {
599         for (x=0; x < kwidth; x++, i--) {
600             dkern[y*w+x] = (mlib_d64) kern[i];
601             if (kern[i] > kmax) {
602                 kmax = kern[i];
603             }
604         }
605     }
606 
607     (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
608 
609     if (kmax > 1<<16) {
610         /* We can only handle 16 bit max */
611         free(dkern);
612         return 0;
613     }
614 
615     /* Parse the source image */
616     if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
617         JNU_ThrowOutOfMemoryError(env, "Out of memory");
618         free(dkern);
619         return -1;
620     }
621 
622     if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
623         JNU_ThrowOutOfMemoryError(env, "Out of memory");
624         free(srcRasterP);
625         free(dkern);
626         return -1;
627     }
628 
629     /* Parse the source raster */
630     if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {
631         /* Can't handle any custom rasters */
632         free(srcRasterP);
633         free(dstRasterP);
634         free(dkern);
635         return 0;
636     }
637 
638     /* Parse the destination raster */
639     if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {
640         /* Can't handle any custom images */
641         awt_freeParsedRaster(srcRasterP, TRUE);
642         free(dstRasterP);
643         free(dkern);
644         return 0;
645     }
646 
647     /* Allocate the arrays */
648     if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
649         /* Must be some problem */
650         awt_freeParsedRaster(srcRasterP, TRUE);
651         awt_freeParsedRaster(dstRasterP, TRUE);
652         free(dkern);
653         return 0;
654     }
655     if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
656         /* Must be some problem */
657         freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
658         awt_freeParsedRaster(srcRasterP, TRUE);
659         awt_freeParsedRaster(dstRasterP, TRUE);
660         free(dkern);
661         return 0;
662     }
663 
664     kdata = NULL;
665     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) {
666         kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32));
667     }
668     if (kdata == NULL) {
669         freeDataArray(env, srcRasterP->jdata, src, sdata,
670                       dstRasterP->jdata, dst, ddata);
671         awt_freeParsedRaster(srcRasterP, TRUE);
672         awt_freeParsedRaster(dstRasterP, TRUE);
673         free(dkern);
674         return 0;
675     }
676 
677     if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h,
678                                     mlib_ImageGetType(src)) != MLIB_SUCCESS) {
679         freeDataArray(env, srcRasterP->jdata, src, sdata,
680                       dstRasterP->jdata, dst, ddata);
681         awt_freeParsedRaster(srcRasterP, TRUE);
682         awt_freeParsedRaster(dstRasterP, TRUE);
683         free(dkern);
684         free(kdata);
685         return 0;
686     }
687 
688     if (s_printIt) {
689         fprintf(stderr, "Orig Kernel(len=%d):\n",klen);
690         for (y=kheight-1; y >= 0; y--) {
691             for (x=kwidth-1; x >= 0; x--) {
692                 fprintf(stderr, "%g ", dkern[y*w+x]);
693             }
694             fprintf(stderr, "\n");
695         }
696         fprintf(stderr, "New Kernel(scale=%d):\n", scale);
697         for (y=kheight-1; y >= 0; y--) {
698             for (x=kwidth-1; x >= 0; x--) {
699                 fprintf(stderr, "%d ", kdata[y*w+x]);
700             }
701             fprintf(stderr, "\n");
702         }
703     }
704 
705     cmask = (1<<src->channels)-1;
706     status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
707                                (w-1)/2, (h-1)/2, scale, cmask,
708                                getMlibEdgeHint(edgeHint));
709 
710     if (status != MLIB_SUCCESS) {
711         printMedialibError(status);
712         retStatus = 0;
713     }
714 
715     if (s_printIt) {
716         unsigned int *dP;
717         if (s_startOff != 0) {
718             printf("Starting at %d\n", s_startOff);
719         }
720         if (sdata == NULL) {
721             dP = (unsigned int *) mlib_ImageGetData(src);
722         }
723         else {
724             dP = (unsigned int *) sdata;
725         }
726         printf("src is\n");
727         for (i=0; i < 20; i++) {
728             printf("%x ",dP[s_startOff+i]);
729         }
730         printf("\n");
731         if (ddata == NULL) {
732             dP = (unsigned int *)mlib_ImageGetData(dst);
733         }
734         else {
735             dP = (unsigned int *) ddata;
736         }
737         printf("dst is\n");
738         for (i=0; i < 20; i++) {
739             printf("%x ",dP[s_startOff+i]);
740         }
741         printf("\n");
742     }
743 
744     /* Means that we couldn't write directly into the destination buffer */
745     if (ddata == NULL) {
746         if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
747             retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
748         }
749     }
750 
751     /* Release the pinned memory */
752     freeDataArray(env, srcRasterP->jdata, src, sdata,
753                   dstRasterP->jdata, dst, ddata);
754     awt_freeParsedRaster(srcRasterP, TRUE);
755     awt_freeParsedRaster(dstRasterP, TRUE);
756     free(dkern);
757     free(kdata);
758 
759     if (s_timeIt) (*stop_timer)(3600,1);
760 
761     return retStatus;
762 }
763 
764 
765 JNIEXPORT jint JNICALL
Java_sun_awt_image_ImagingLib_transformBI(JNIEnv * env,jobject this,jobject jsrc,jobject jdst,jdoubleArray jmatrix,jint interpType)766 Java_sun_awt_image_ImagingLib_transformBI(JNIEnv *env, jobject this,
767                                           jobject jsrc,
768                                           jobject jdst,
769                                           jdoubleArray jmatrix,
770                                           jint interpType)
771 {
772     mlib_image *src;
773     mlib_image *dst;
774     int i;
775     int j = 0;
776     int retStatus = 1;
777     mlib_status status;
778     double *matrix;
779     mlib_d64 mtx[6];
780     void *sdata;
781     void *ddata;
782     BufImageS_t *srcImageP;
783     BufImageS_t *dstImageP;
784     mlib_filter filter;
785     mlibHintS_t hint;
786     unsigned int *dP;
787     int useIndexed;
788     int nbands;
789 
790     /* This function requires a lot of local refs ??? Is 64 enough ??? */
791     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
792         return 0;
793 
794     if (s_nomlib) return 0;
795     if (s_timeIt) {
796         (*start_timer)(3600);
797     }
798 
799     switch(interpType) {
800     case java_awt_image_AffineTransformOp_TYPE_BILINEAR:
801         filter = MLIB_BILINEAR;
802         break;
803     case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR:
804         filter = MLIB_NEAREST;
805         break;
806     case java_awt_image_AffineTransformOp_TYPE_BICUBIC:
807         filter = MLIB_BICUBIC;
808         break;
809     default:
810         JNU_ThrowInternalError(env, "Unknown interpolation type");
811         return -1;
812     }
813 
814     if ((*env)->GetArrayLength(env, jmatrix) < 6) {
815         /*
816          * Very unlikely, however we should check for this:
817          * if given matrix array is too short, we can't handle it
818          */
819         return 0;
820     }
821 
822     matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL);
823     if (matrix == NULL) {
824         /* out of memory error already thrown */
825         return 0;
826     }
827 
828     /* Check for invalid double value in transformation matrix */
829     for (j = 0; j < 6; j++) {
830 
831         if (!(IS_FINITE(matrix[j]))) {
832             (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
833             return 0;
834         }
835     }
836 
837     if (s_printIt) {
838         printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
839                matrix[2], matrix[3], matrix[4], matrix[5]);
840     }
841 
842     mtx[0] = matrix[0];
843     mtx[1] = matrix[2];
844     mtx[2] = matrix[4];
845     mtx[3] = matrix[1];
846     mtx[4] = matrix[3];
847     mtx[5] = matrix[5];
848 
849     (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
850 
851     /* Parse the source image */
852     if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {
853         /* Can't handle any custom images */
854         return 0;
855     }
856 
857     /* Parse the destination image */
858     if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {
859         /* Can't handle any custom images */
860         awt_freeParsedImage(srcImageP, TRUE);
861         return 0;
862     }
863 
864     /* REMIND!!  Can't assume that it is the same LUT!! */
865     /* Fix 4213160, 4184283 */
866     useIndexed = (srcImageP->cmodel.cmType == INDEX_CM_TYPE &&
867                   dstImageP->cmodel.cmType == INDEX_CM_TYPE &&
868                   srcImageP->raster.rasterType == dstImageP->raster.rasterType &&
869                   srcImageP->raster.rasterType == COMPONENT_RASTER_TYPE);
870 
871     nbands = setImageHints(env, srcImageP, dstImageP, !useIndexed, TRUE,
872                         FALSE, &hint);
873     if (nbands < 1) {
874         /* Can't handle any custom images */
875         awt_freeParsedImage(srcImageP, TRUE);
876         awt_freeParsedImage(dstImageP, TRUE);
877         return 0;
878     }
879 
880     /* Allocate the arrays */
881     if (allocateArray(env, srcImageP, &src, &sdata, TRUE,
882                       hint.cvtSrcToDefault, hint.addAlpha) < 0) {
883         /* Must be some problem */
884         awt_freeParsedImage(srcImageP, TRUE);
885         awt_freeParsedImage(dstImageP, TRUE);
886         return 0;
887     }
888     if (allocateArray(env, dstImageP, &dst, &ddata, FALSE,
889                       hint.cvtToDst, FALSE) < 0) {
890         /* Must be some problem */
891         freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
892         awt_freeParsedImage(srcImageP, TRUE);
893         awt_freeParsedImage(dstImageP, TRUE);
894         return 0;
895     }
896 #if 0
897 fprintf(stderr,"Src----------------\n");
898 fprintf(stderr,"Type : %d\n",src->type);
899 fprintf(stderr,"Channels: %d\n",src->channels);
900 fprintf(stderr,"Width   : %d\n",src->width);
901 fprintf(stderr,"Height  : %d\n",src->height);
902 fprintf(stderr,"Stride  : %d\n",src->stride);
903 fprintf(stderr,"Flags   : %d\n",src->flags);
904 
905 fprintf(stderr,"Dst----------------\n");
906 fprintf(stderr,"Type : %d\n",dst->type);
907 fprintf(stderr,"Channels: %d\n",dst->channels);
908 fprintf(stderr,"Width   : %d\n",dst->width);
909 fprintf(stderr,"Height  : %d\n",dst->height);
910 fprintf(stderr,"Stride  : %d\n",dst->stride);
911 fprintf(stderr,"Flags   : %d\n",dst->flags);
912 #endif
913 
914     if (dstImageP->cmodel.cmType == INDEX_CM_TYPE) {
915         /* Need to clear the destination to the transparent pixel */
916         unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);
917 
918         memset(cP, dstImageP->cmodel.transIdx,
919                mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));
920     }
921     /* Perform the transformation */
922     if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,
923                                   MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))
924     {
925         printMedialibError(status);
926         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
927         awt_freeParsedImage(srcImageP, TRUE);
928         awt_freeParsedImage(dstImageP, TRUE);
929 
930         return 0;
931     }
932 
933     if (s_printIt) {
934         if (sdata == NULL) {
935             dP = (unsigned int *) mlib_ImageGetData(src);
936         }
937         else {
938             dP = (unsigned int *) sdata;
939         }
940         printf("src is\n");
941         for (i=0; i < 20; i++) {
942             printf("%x ",dP[i]);
943         }
944         printf("\n");
945         if (ddata == NULL) {
946             dP = (unsigned int *)mlib_ImageGetData(dst);
947         }
948         else {
949             dP = (unsigned int *) ddata;
950         }
951         printf("dst is\n");
952         for (i=0; i < 20; i++) {
953             printf("%x ",dP[i]);
954         }
955         printf("\n");
956     }
957 
958     /* Means that we couldn't write directly into the destination buffer */
959     if (ddata == NULL) {
960         freeDataArray(env, srcImageP->raster.jdata, src, sdata,
961                       NULL, NULL, NULL);
962         /* Need to store it back into the array */
963         if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
964             /* Error */
965             retStatus = 0;
966         }
967         freeDataArray(env, NULL, NULL, NULL, dstImageP->raster.jdata,
968                       dst, ddata);
969     }
970     else {
971         /* Release the pinned memory */
972         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
973     }
974 
975     awt_freeParsedImage(srcImageP, TRUE);
976     awt_freeParsedImage(dstImageP, TRUE);
977 
978     if (s_timeIt) (*stop_timer)(3600,1);
979 
980     return retStatus;
981 }
982 
983 JNIEXPORT jint JNICALL
Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv * env,jobject this,jobject jsrc,jobject jdst,jdoubleArray jmatrix,jint interpType)984 Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv *env, jobject this,
985                                               jobject jsrc,
986                                               jobject jdst,
987                                               jdoubleArray jmatrix,
988                                               jint interpType)
989 {
990     mlib_image *src;
991     mlib_image *dst;
992     int i;
993     int j = 0;
994     int retStatus = 1;
995     mlib_status status;
996     double *matrix;
997     mlib_d64 mtx[6];
998     void *sdata;
999     void *ddata;
1000     RasterS_t *srcRasterP;
1001     RasterS_t *dstRasterP;
1002     mlib_filter filter;
1003     unsigned int *dP;
1004 
1005     /* This function requires a lot of local refs ??? Is 64 enough ??? */
1006     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1007         return 0;
1008 
1009     if (s_nomlib) return 0;
1010     if (s_timeIt) {
1011         (*start_timer)(3600);
1012     }
1013 
1014     switch(interpType) {
1015     case java_awt_image_AffineTransformOp_TYPE_BILINEAR:
1016         filter = MLIB_BILINEAR;
1017         break;
1018     case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR:
1019         filter = MLIB_NEAREST;
1020         break;
1021     case java_awt_image_AffineTransformOp_TYPE_BICUBIC:
1022         filter = MLIB_BICUBIC;
1023         break;
1024     default:
1025         JNU_ThrowInternalError(env, "Unknown interpolation type");
1026         return -1;
1027     }
1028 
1029     if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
1030         JNU_ThrowOutOfMemoryError(env, "Out of memory");
1031         return -1;
1032     }
1033 
1034     if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
1035         JNU_ThrowOutOfMemoryError(env, "Out of memory");
1036         free(srcRasterP);
1037         return -1;
1038     }
1039 
1040     if ((*env)->GetArrayLength(env, jmatrix) < 6) {
1041         /*
1042          * Very unlikely, however we should check for this:
1043          * if given matrix array is too short, we can't handle it.
1044          */
1045         free(srcRasterP);
1046         free(dstRasterP);
1047         return 0;
1048     }
1049 
1050     matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL);
1051     if (matrix == NULL) {
1052         /* out of memory error already thrown */
1053         free(srcRasterP);
1054         free(dstRasterP);
1055         return 0;
1056     }
1057 
1058     /* Check for invalid double value in transformation matrix */
1059     for (j = 0; j < 6; j++) {
1060 
1061         if (!(IS_FINITE(matrix[j]))) {
1062             (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
1063             free(srcRasterP);
1064             free(dstRasterP);
1065             return 0;
1066         }
1067     }
1068 
1069     if (s_printIt) {
1070         printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
1071                matrix[2], matrix[3], matrix[4], matrix[5]);
1072     }
1073 
1074     mtx[0] = matrix[0];
1075     mtx[1] = matrix[2];
1076     mtx[2] = matrix[4];
1077     mtx[3] = matrix[1];
1078     mtx[4] = matrix[3];
1079     mtx[5] = matrix[5];
1080 
1081     (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
1082 
1083     /* Parse the source raster */
1084     if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {
1085         /* Can't handle any custom rasters */
1086         free(srcRasterP);
1087         free(dstRasterP);
1088         return 0;
1089     }
1090 
1091     /* Parse the destination raster */
1092     if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {
1093         /* Can't handle any custom images */
1094         awt_freeParsedRaster(srcRasterP, TRUE);
1095         free(dstRasterP);
1096         return 0;
1097     }
1098 
1099     /* Allocate the arrays */
1100     if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
1101         /* Must be some problem */
1102         awt_freeParsedRaster(srcRasterP, TRUE);
1103         awt_freeParsedRaster(dstRasterP, TRUE);
1104         return 0;
1105     }
1106     if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
1107         /* Must be some problem */
1108         freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
1109         awt_freeParsedRaster(srcRasterP, TRUE);
1110         awt_freeParsedRaster(dstRasterP, TRUE);
1111         return 0;
1112     }
1113 
1114 #if 0
1115 fprintf(stderr,"Src----------------\n");
1116 fprintf(stderr,"Type : %d\n",src->type);
1117 fprintf(stderr,"Channels: %d\n",src->channels);
1118 fprintf(stderr,"Width   : %d\n",src->width);
1119 fprintf(stderr,"Height  : %d\n",src->height);
1120 fprintf(stderr,"Stride  : %d\n",src->stride);
1121 fprintf(stderr,"Flags   : %d\n",src->flags);
1122 
1123 fprintf(stderr,"Dst----------------\n");
1124 fprintf(stderr,"Type : %d\n",dst->type);
1125 fprintf(stderr,"Channels: %d\n",dst->channels);
1126 fprintf(stderr,"Width   : %d\n",dst->width);
1127 fprintf(stderr,"Height  : %d\n",dst->height);
1128 fprintf(stderr,"Stride  : %d\n",dst->stride);
1129 fprintf(stderr,"Flags   : %d\n",dst->flags);
1130 #endif
1131 
1132     {
1133         unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);
1134 
1135         memset(cP, 0, mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));
1136     }
1137 
1138     /* Perform the transformation */
1139     if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,
1140                                   MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))
1141     {
1142         printMedialibError(status);
1143         /* REMIND: Free the regions */
1144         return 0;
1145     }
1146 
1147     if (s_printIt) {
1148         if (sdata == NULL) {
1149             dP = (unsigned int *) mlib_ImageGetData(src);
1150         }
1151         else {
1152             dP = (unsigned int *) sdata;
1153         }
1154         printf("src is\n");
1155         for (i=0; i < 20; i++) {
1156             printf("%x ",dP[i]);
1157         }
1158         printf("\n");
1159         if (ddata == NULL) {
1160             dP = (unsigned int *)mlib_ImageGetData(dst);
1161         }
1162         else {
1163             dP = (unsigned int *) ddata;
1164         }
1165         printf("dst is\n");
1166         for (i=0; i < 20; i++) {
1167             printf("%x ",dP[i]);
1168         }
1169         printf("\n");
1170     }
1171 
1172     /* Means that we couldn't write directly into the destination buffer */
1173     if (ddata == NULL) {
1174         /* Need to store it back into the array */
1175         if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
1176             (*env)->ExceptionClear(env); // Could not store the array, try another way
1177             retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
1178         }
1179     }
1180 
1181     /* Release the pinned memory */
1182     freeDataArray(env, srcRasterP->jdata, src, sdata,
1183                   dstRasterP->jdata, dst, ddata);
1184 
1185     awt_freeParsedRaster(srcRasterP, TRUE);
1186     awt_freeParsedRaster(dstRasterP, TRUE);
1187 
1188     if (s_timeIt) (*stop_timer)(3600,1);
1189 
1190     return retStatus;
1191 }
1192 
1193 typedef struct {
1194     jobject jArray;
1195     jsize length;
1196     unsigned char *table;
1197 } LookupArrayInfo;
1198 
1199 #define NLUT 8
1200 
1201 #ifdef VM_LITTLE_ENDIAN
1202 #define INDEXES    { 3, 2, 1, 0, 7, 6, 5, 4 }
1203 #else
1204 #define INDEXES    { 0, 1, 2, 3, 4, 5, 6, 7 }
1205 #endif
1206 
lookupShortData(mlib_image * src,mlib_image * dst,LookupArrayInfo * lookup)1207 static int lookupShortData(mlib_image* src, mlib_image* dst,
1208     LookupArrayInfo* lookup)
1209 {
1210     int x, y;
1211     unsigned int mask = NLUT-1;
1212 
1213     unsigned short* srcLine = (unsigned short*)src->data;
1214     unsigned char* dstLine = (unsigned char*)dst->data;
1215 
1216     static int indexes[NLUT] = INDEXES;
1217 
1218     if (src->width != dst->width || src->height != dst->height) {
1219         return 0;
1220     }
1221 
1222     for (y=0; y < src->height; y++) {
1223         int nloop, nx;
1224         int npix = src->width;
1225 
1226         unsigned short* srcPixel = srcLine;
1227         unsigned char* dstPixel = dstLine;
1228 
1229 #ifdef SIMPLE_LOOKUP_LOOP
1230         for (x=0; status && x < width; x++) {
1231             unsigned short s = *srcPixel++;
1232             if (s >= lookup->length) {
1233                 /* we can not handle source image using
1234                 * byte lookup table. Fall back to processing
1235                 * images in java
1236                 */
1237                 return 0;
1238             }
1239             *dstPixel++ = lookup->table[s];
1240         }
1241 #else
1242         /* Get to 32 bit-aligned point */
1243         while(((uintptr_t)dstPixel & 0x3) != 0 && npix>0) {
1244             unsigned short s = *srcPixel++;
1245             if (s >= lookup->length) {
1246                 return 0;
1247             }
1248             *dstPixel++ = lookup->table[s];
1249             npix--;
1250         }
1251 
1252         /*
1253          * Do NLUT pixels per loop iteration.
1254          * Pack into ints and write out 2 at a time.
1255          */
1256         nloop = npix/NLUT;
1257         nx = npix%NLUT;
1258 
1259         for(x=nloop; x!=0; x--) {
1260             int i = 0;
1261             int* dstP = (int*)dstPixel;
1262 
1263             for (i = 0; i < NLUT; i++) {
1264                 if (srcPixel[i] >= lookup->length) {
1265                     return 0;
1266                 }
1267             }
1268 
1269             dstP[0] = (int)
1270                 ((lookup->table[srcPixel[indexes[0]]] << 24) |
1271                  (lookup->table[srcPixel[indexes[1]]] << 16) |
1272                  (lookup->table[srcPixel[indexes[2]]] << 8)  |
1273                   lookup->table[srcPixel[indexes[3]]]);
1274             dstP[1] = (int)
1275                 ((lookup->table[srcPixel[indexes[4]]] << 24) |
1276                  (lookup->table[srcPixel[indexes[5]]] << 16) |
1277                  (lookup->table[srcPixel[indexes[6]]] << 8)  |
1278                   lookup->table[srcPixel[indexes[7]]]);
1279 
1280 
1281             dstPixel += NLUT;
1282             srcPixel += NLUT;
1283         }
1284 
1285         /*
1286          * Complete any remaining pixels
1287          */
1288         for(x=nx; x!=0; x--) {
1289             unsigned short s = *srcPixel++;
1290             if (s >= lookup->length) {
1291                 return 0;
1292             }
1293             *dstPixel++ = lookup->table[s];
1294         }
1295 #endif
1296 
1297         dstLine += dst->stride;     // array of bytes, scan stride in bytes
1298         srcLine += src->stride / 2; // array of shorts, scan stride in bytes
1299     }
1300     return 1;
1301 }
1302 
1303 JNIEXPORT jint JNICALL
Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv * env,jobject thisLib,jobject jsrc,jobject jdst,jobjectArray jtableArrays)1304 Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject thisLib,
1305                                            jobject jsrc, jobject jdst,
1306                                            jobjectArray jtableArrays)
1307 {
1308     mlib_image *src;
1309     mlib_image *dst;
1310     void *sdata, *ddata;
1311     unsigned char **tbl;
1312     unsigned char lut[256];
1313     int retStatus = 1;
1314     int i;
1315     mlib_status status;
1316     int lut_nbands;
1317     LookupArrayInfo *jtable;
1318     BufImageS_t *srcImageP, *dstImageP;
1319     int nbands;
1320     int ncomponents;
1321     mlibHintS_t hint;
1322 
1323     /* This function requires a lot of local refs ??? Is 64 enough ??? */
1324     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1325         return 0;
1326 
1327     if (s_nomlib) return 0;
1328     if (s_timeIt) (*start_timer)(3600);
1329 
1330     /* Parse the source image */
1331     if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {
1332         /* Can't handle any custom images */
1333         return 0;
1334     }
1335 
1336     /* Parse the destination image */
1337     if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {
1338         /* Can't handle any custom images */
1339         awt_freeParsedImage(srcImageP, TRUE);
1340         return 0;
1341     }
1342 
1343     nbands = setImageHints(env, srcImageP, dstImageP, FALSE, TRUE,
1344                         FALSE, &hint);
1345 
1346     if (nbands < 1 || nbands > srcImageP->cmodel.numComponents) {
1347         /* Can't handle any custom images */
1348         awt_freeParsedImage(srcImageP, TRUE);
1349         awt_freeParsedImage(dstImageP, TRUE);
1350         return 0;
1351     }
1352 
1353     ncomponents = srcImageP->cmodel.isDefaultCompatCM
1354         ? 4
1355         : srcImageP->cmodel.numComponents;
1356 
1357     /* Make sure that color order can be used for
1358      * re-ordering of lookup arrays.
1359      */
1360     for (i = 0; i < nbands; i++) {
1361         int idx = srcImageP->hints.colorOrder[i];
1362 
1363         if (idx < 0 || idx >= ncomponents) {
1364             awt_freeParsedImage(srcImageP, TRUE);
1365             awt_freeParsedImage(dstImageP, TRUE);
1366             return 0;
1367         }
1368     }
1369 
1370     lut_nbands = (*env)->GetArrayLength(env, jtableArrays);
1371 
1372     if (lut_nbands > ncomponents) {
1373         lut_nbands = ncomponents;
1374     }
1375 
1376     tbl = NULL;
1377     if (SAFE_TO_ALLOC_2(ncomponents, sizeof(unsigned char *))) {
1378         tbl = (unsigned char **)
1379             calloc(1, ncomponents * sizeof(unsigned char *));
1380     }
1381 
1382     jtable = NULL;
1383     if (SAFE_TO_ALLOC_2(lut_nbands, sizeof(LookupArrayInfo))) {
1384         jtable = (LookupArrayInfo *)malloc(lut_nbands * sizeof (LookupArrayInfo));
1385     }
1386 
1387     if (tbl == NULL || jtable == NULL) {
1388         if (tbl != NULL) free(tbl);
1389         if (jtable != NULL) free(jtable);
1390         awt_freeParsedImage(srcImageP, TRUE);
1391         awt_freeParsedImage(dstImageP, TRUE);
1392         JNU_ThrowNullPointerException(env, "NULL LUT");
1393         return 0;
1394     }
1395     /* Need to grab these pointers before we lock down arrays */
1396     for (i=0; i < lut_nbands; i++) {
1397         jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);
1398 
1399         if (jtable[i].jArray != NULL) {
1400             jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);
1401             jtable[i].table = NULL;
1402 
1403             if (jtable[i].length < 256) {
1404                 /* we may read outside the table during lookup */
1405                 jtable[i].jArray = NULL;
1406                 jtable[i].length = 0;
1407             }
1408         }
1409         if (jtable[i].jArray == NULL) {
1410             free(tbl);
1411             free(jtable);
1412             awt_freeParsedImage(srcImageP, TRUE);
1413             awt_freeParsedImage(dstImageP, TRUE);
1414             return 0;
1415         }
1416     }
1417 
1418     /* Allocate the arrays */
1419     if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) {
1420         /* Must be some problem */
1421         free(tbl);
1422         free(jtable);
1423         awt_freeParsedImage(srcImageP, TRUE);
1424         awt_freeParsedImage(dstImageP, TRUE);
1425         return 0;
1426     }
1427     if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) {
1428         /* Must be some problem */
1429         free(tbl);
1430         free(jtable);
1431         freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
1432         awt_freeParsedImage(srcImageP, TRUE);
1433         awt_freeParsedImage(dstImageP, TRUE);
1434         return 0;
1435     }
1436 
1437     /* Set up a straight lut so we don't mess around with alpha */
1438     /*
1439      * NB: medialib lookup routine expects lookup array for each
1440      * component of source image including alpha.
1441      * If lookup table we got form the java layer does not contain
1442      * sufficient number of lookup arrays we add references to identity
1443      * lookup array to make medialib happier.
1444      */
1445     if (lut_nbands < ncomponents) {
1446         int j;
1447         /* REMIND: This should be the size of the input lut!! */
1448         for (j=0; j < 256; j++) {
1449             lut[j] = j;
1450         }
1451         for (j=0; j < ncomponents; j++) {
1452             tbl[j] = lut;
1453         }
1454     }
1455 
1456     for (i=0; i < lut_nbands; i++) {
1457         jtable[i].table = (unsigned char *)
1458             (*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);
1459         if (jtable[i].table == NULL) {
1460             /* Free what we've got so far. */
1461             int j;
1462             for (j = 0; j < i; j++) {
1463                 (*env)->ReleasePrimitiveArrayCritical(env,
1464                                                       jtable[j].jArray,
1465                                                       (jbyte *) jtable[j].table,
1466                                                       JNI_ABORT);
1467             }
1468             free(tbl);
1469             free(jtable);
1470             freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
1471             awt_freeParsedImage(srcImageP, TRUE);
1472             awt_freeParsedImage(dstImageP, TRUE);
1473             return 0;
1474         }
1475         tbl[srcImageP->hints.colorOrder[i]] = jtable[i].table;
1476     }
1477 
1478     if (lut_nbands == 1) {
1479         for (i=1; i < nbands -
1480                  srcImageP->cmodel.supportsAlpha; i++) {
1481                      tbl[srcImageP->hints.colorOrder[i]] = jtable[0].table;
1482         }
1483     }
1484 
1485     /* Mlib needs 16bit lookuptable and must be signed! */
1486     if (src->type == MLIB_SHORT) {
1487         if (dst->type == MLIB_BYTE) {
1488             if (nbands > 1) {
1489                 retStatus = 0;
1490             }
1491             else {
1492                 retStatus = lookupShortData(src, dst, &jtable[0]);
1493             }
1494         }
1495         /* How about ddata == null? */
1496     }
1497     else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,
1498                                       (void **)tbl) != MLIB_SUCCESS)) {
1499         printMedialibError(status);
1500         retStatus = 0;
1501     }
1502 
1503    /* Release the LUT */
1504     for (i=0; i < lut_nbands; i++) {
1505         (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
1506             (jbyte *) jtable[i].table, JNI_ABORT);
1507     }
1508     free ((void *) jtable);
1509     free ((void *) tbl);
1510 
1511     /*
1512      * Means that we couldn't write directly into
1513      * the destination buffer
1514      */
1515     if (ddata == NULL) {
1516 
1517         /* Need to store it back into the array */
1518         if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
1519             /* Error */
1520             retStatus = 0;
1521         }
1522     }
1523 
1524 
1525     /* Release the pinned memory */
1526     freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
1527 
1528     awt_freeParsedImage(srcImageP, TRUE);
1529     awt_freeParsedImage(dstImageP, TRUE);
1530 
1531     if (s_timeIt) (*stop_timer)(3600, 1);
1532 
1533     return retStatus;
1534 }
1535 
1536 JNIEXPORT jint JNICALL
Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv * env,jobject this,jobject jsrc,jobject jdst,jobjectArray jtableArrays)1537 Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env,
1538                                                jobject this,
1539                                                jobject jsrc,
1540                                                jobject jdst,
1541                                                jobjectArray jtableArrays)
1542 {
1543     RasterS_t*     srcRasterP;
1544     RasterS_t*     dstRasterP;
1545     mlib_image*    src;
1546     mlib_image*    dst;
1547     void*          sdata;
1548     void*          ddata;
1549     LookupArrayInfo jtable[4];
1550     unsigned char* mlib_lookupTable[4];
1551     int            i;
1552     int            retStatus = 1;
1553     mlib_status    status;
1554     int            jlen;
1555     int            lut_nbands;
1556     int            src_nbands;
1557     int            dst_nbands;
1558     unsigned char  ilut[256];
1559 
1560     /* This function requires a lot of local refs ??? Is 64 enough ??? */
1561     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1562         return 0;
1563 
1564     if (s_nomlib) return 0;
1565     if (s_timeIt) (*start_timer)(3600);
1566 
1567     if ((srcRasterP = (RasterS_t*) calloc(1, sizeof(RasterS_t))) == NULL) {
1568         JNU_ThrowOutOfMemoryError(env, "Out of memory");
1569         return -1;
1570     }
1571 
1572     if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
1573         JNU_ThrowOutOfMemoryError(env, "Out of memory");
1574         free(srcRasterP);
1575         return -1;
1576     }
1577 
1578     /* Parse the source raster - reject custom images */
1579     if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {
1580         free(srcRasterP);
1581         free(dstRasterP);
1582         return 0;
1583     }
1584 
1585     /* Parse the destination image - reject custom images */
1586     if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {
1587         awt_freeParsedRaster(srcRasterP, TRUE);
1588         free(dstRasterP);
1589         return 0;
1590     }
1591 
1592     jlen = (*env)->GetArrayLength(env, jtableArrays);
1593 
1594     lut_nbands = jlen;
1595     src_nbands = srcRasterP->numBands;
1596     dst_nbands = dstRasterP->numBands;
1597 
1598     /* adjust number of lookup bands */
1599     if (lut_nbands > src_nbands) {
1600         lut_nbands = src_nbands;
1601     }
1602 
1603     /* MediaLib can't do more than 4 bands */
1604     if (src_nbands <= 0 || src_nbands > 4 ||
1605         dst_nbands <= 0 || dst_nbands > 4 ||
1606         lut_nbands <= 0 || lut_nbands > 4 ||
1607         src_nbands != dst_nbands ||
1608         ((lut_nbands != 1) && (lut_nbands != src_nbands)))
1609     {
1610         // we should free parsed rasters here
1611         awt_freeParsedRaster(srcRasterP, TRUE);
1612         awt_freeParsedRaster(dstRasterP, TRUE);
1613         return 0;
1614     }
1615 
1616     /* Allocate the raster arrays */
1617     if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
1618         /* Must be some problem */
1619         awt_freeParsedRaster(srcRasterP, TRUE);
1620         awt_freeParsedRaster(dstRasterP, TRUE);
1621         return 0;
1622     }
1623     if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
1624         /* Must be some problem */
1625         freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
1626         awt_freeParsedRaster(srcRasterP, TRUE);
1627         awt_freeParsedRaster(dstRasterP, TRUE);
1628         return 0;
1629     }
1630 
1631     /*
1632      * Well, until now we have analyzed number of bands in
1633      * src and dst rasters.
1634      * However, it is not enough because medialib lookup routine uses
1635      * number of channels of medialib image. Note that in certain
1636      * case number of channels may differs form the number of bands.
1637      * Good example is raster that is used in TYPE_INT_RGB buffered
1638      * image: it has 3 bands, but their medialib representation has
1639      * 4 channels.
1640      *
1641      * In order to avoid the lookup routine failure, we need:
1642      *
1643      * 1. verify that src and dst have same number of channels.
1644      * 2. provide lookup array for every channel. If we have "extra"
1645      *    channel (like the raster described above) then we need to
1646      *    provide identical lookup array.
1647      */
1648     if (src->channels != dst->channels) {
1649         freeDataArray(env, srcRasterP->jdata, src, sdata,
1650                       dstRasterP->jdata, dst, ddata);
1651 
1652         awt_freeParsedRaster(srcRasterP, TRUE);
1653         awt_freeParsedRaster(dstRasterP, TRUE);
1654         return 0;
1655     }
1656 
1657     if (src_nbands < src->channels) {
1658         for (i = 0; i < 256; i++) {
1659             ilut[i] = i;
1660         }
1661     }
1662 
1663 
1664     /* Get references to the lookup table arrays */
1665     /* Need to grab these pointers before we lock down arrays */
1666     for (i=0; i < lut_nbands; i++) {
1667         jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);
1668         jtable[i].table = NULL;
1669         if (jtable[i].jArray != NULL) {
1670             jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);
1671             if (jtable[i].length < 256) {
1672                  /* we may read outside the table during lookup */
1673                 jtable[i].jArray = NULL;
1674             }
1675         }
1676 
1677         if (jtable[i].jArray == NULL)
1678         {
1679             freeDataArray(env, srcRasterP->jdata, src, sdata,
1680                           dstRasterP->jdata, dst, ddata);
1681 
1682             awt_freeParsedRaster(srcRasterP, TRUE);
1683             awt_freeParsedRaster(dstRasterP, TRUE);
1684             return 0;
1685         }
1686     }
1687 
1688     for (i=0; i < lut_nbands; i++) {
1689         jtable[i].table = (unsigned char *)
1690             (*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);
1691         if (jtable[i].table == NULL) {
1692             /* Free what we've got so far. */
1693             int j;
1694             for (j = 0; j < i; j++) {
1695                 (*env)->ReleasePrimitiveArrayCritical(env,
1696                                                       jtable[j].jArray,
1697                                                       (jbyte *) jtable[j].table,
1698                                                       JNI_ABORT);
1699             }
1700             freeDataArray(env, srcRasterP->jdata, src, sdata,
1701                           dstRasterP->jdata, dst, ddata);
1702             awt_freeParsedRaster(srcRasterP, TRUE);
1703             awt_freeParsedRaster(dstRasterP, TRUE);
1704             return 0;
1705         }
1706         mlib_lookupTable[i] = jtable[i].table;
1707     }
1708 
1709     /*
1710      * Medialib routine expects lookup array for each band of raster.
1711      * Setup the  rest of lookup arrays if supplied lookup table
1712      * contains single lookup array.
1713      */
1714     for (i = lut_nbands; i < src_nbands; i++) {
1715         mlib_lookupTable[i] = jtable[0].table;
1716     }
1717 
1718     /*
1719      * Setup lookup array for "extra" channels
1720      */
1721     for ( ; i < src->channels; i++) {
1722         mlib_lookupTable[i] = ilut;
1723     }
1724 
1725     /* Mlib needs 16bit lookuptable and must be signed! */
1726     if (src->type == MLIB_SHORT) {
1727         if (dst->type == MLIB_BYTE) {
1728             if (lut_nbands > 1) {
1729                 retStatus = 0;
1730             } else {
1731                 retStatus = lookupShortData(src, dst, &jtable[0]);
1732             }
1733         }
1734         /* How about ddata == null? */
1735     } else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,
1736                                       (void **)mlib_lookupTable) != MLIB_SUCCESS)) {
1737         printMedialibError(status);
1738         retStatus = 0;
1739     }
1740 
1741     /* Release the LUT */
1742     for (i=0; i < lut_nbands; i++) {
1743         (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
1744                                               (jbyte *) jtable[i].table, JNI_ABORT);
1745     }
1746 
1747     /*
1748      * Means that we couldn't write directly into
1749      * the destination buffer
1750      */
1751     if (ddata == NULL) {
1752         if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
1753             retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
1754         }
1755     }
1756 
1757     /* Release the pinned memory */
1758     freeDataArray(env, srcRasterP->jdata, src, sdata,
1759                   dstRasterP->jdata, dst, ddata);
1760 
1761     awt_freeParsedRaster(srcRasterP, TRUE);
1762     awt_freeParsedRaster(dstRasterP, TRUE);
1763 
1764     if (s_timeIt) (*stop_timer)(3600, 1);
1765 
1766     return retStatus;
1767 }
1768 
1769 
1770 JNIEXPORT jboolean JNICALL
Java_sun_awt_image_ImagingLib_init(JNIEnv * env,jclass thisClass)1771 Java_sun_awt_image_ImagingLib_init(JNIEnv *env, jclass thisClass) {
1772     char *start;
1773     if (getenv("IMLIB_DEBUG")) {
1774         start_timer = awt_setMlibStartTimer();
1775         stop_timer = awt_setMlibStopTimer();
1776         if (start_timer && stop_timer) {
1777             s_timeIt = 1;
1778         }
1779     }
1780 
1781     if (getenv("IMLIB_PRINT")) {
1782         s_printIt = 1;
1783     }
1784     if ((start = getenv("IMLIB_START")) != NULL) {
1785         sscanf(start, "%d", &s_startOff);
1786     }
1787 
1788     if (getenv ("IMLIB_NOMLIB")) {
1789         s_nomlib = 1;
1790         return JNI_FALSE;
1791     }
1792 
1793     /* This function is platform-dependent and is in awt_mlib.c */
1794     if (awt_getImagingLib(env, (mlibFnS_t *)&sMlibFns, &sMlibSysFns) !=
1795         MLIB_SUCCESS)
1796     {
1797         s_nomlib = 1;
1798         return JNI_FALSE;
1799     }
1800     return JNI_TRUE;
1801 }
1802 
1803 /* REMIND: How to specify border? */
extendEdge(JNIEnv * env,BufImageS_t * imageP,int * widthP,int * heightP)1804 static void extendEdge(JNIEnv *env, BufImageS_t *imageP,
1805                        int *widthP, int *heightP) {
1806     RasterS_t *rasterP = &imageP->raster;
1807     int width;
1808     int height;
1809     /* Useful for convolution? */
1810 
1811     jobject jbaseraster = (*env)->GetObjectField(env, rasterP->jraster,
1812                                                  g_RasterBaseRasterID);
1813     width = rasterP->width;
1814     height = rasterP->height;
1815 #ifdef WORKING
1816     if (! JNU_IsNull(env, jbaseraster) &&
1817         !(*env)->IsSameObject(env, rasterP->jraster, jbaseraster)) {
1818         int xOff;
1819         int yOff;
1820         int baseWidth;
1821         int baseHeight;
1822         int baseXoff;
1823         int baseYoff;
1824         /* Not the same object so get the width and height */
1825         xOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterXOffsetID);
1826         yOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterYOffsetID);
1827         baseWidth  = (*env)->GetIntField(env, jbaseraster, g_RasterWidthID);
1828         baseHeight = (*env)->GetIntField(env, jbaseraster, g_RasterHeightID);
1829         baseXoff   = (*env)->GetIntField(env, jbaseraster, g_RasterXOffsetID);
1830         baseYoff   = (*env)->GetIntField(env, jbaseraster, g_RasterYOffsetID);
1831 
1832         if (xOff + rasterP->width < baseXoff + baseWidth) {
1833             /* Can use edge */
1834             width++;
1835         }
1836         if (yOff + rasterP->height < baseYoff + baseHeight) {
1837             /* Can use edge */
1838             height++;
1839         }
1840 
1841     }
1842 #endif
1843 
1844 }
1845 
1846 static int
setImageHints(JNIEnv * env,BufImageS_t * srcP,BufImageS_t * dstP,int expandICM,int useAlpha,int premultiply,mlibHintS_t * hintP)1847 setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
1848               int expandICM, int useAlpha,
1849               int premultiply, mlibHintS_t *hintP)
1850 {
1851     ColorModelS_t *srcCMP = &srcP->cmodel;
1852     ColorModelS_t *dstCMP = &dstP->cmodel;
1853     int nbands = 0;
1854     int ncomponents;
1855 
1856     hintP->dataType = srcP->raster.dataType;
1857     hintP->addAlpha = FALSE;
1858 
1859     /* Are the color spaces the same? */
1860     if (srcCMP->csType != dstCMP->csType) {
1861         /* If the src is GRAY and dst RGB, we can handle it */
1862         if (!(srcCMP->csType == java_awt_color_ColorSpace_TYPE_GRAY &&
1863               dstCMP->csType == java_awt_color_ColorSpace_TYPE_RGB)) {
1864             /* Nope, need to handle that in java for now */
1865             return -1;
1866         }
1867         else {
1868             hintP->cvtSrcToDefault = TRUE;
1869         }
1870     }
1871     else {
1872         if (srcP->hints.needToExpand) {
1873             hintP->cvtSrcToDefault = TRUE;
1874         }
1875         else {
1876             /* Need to initialize this */
1877             hintP->cvtSrcToDefault = FALSE;
1878         }
1879     }
1880 
1881     ncomponents = srcCMP->numComponents;
1882     if ((useAlpha == 0) && srcCMP->supportsAlpha) {
1883         ncomponents--;  /* ?? */
1884         /* Not really, more like shrink src to get rid of alpha */
1885         hintP->cvtSrcToDefault = TRUE;
1886     }
1887 
1888     hintP->dataType = srcP->raster.dataType;
1889     if (hintP->cvtSrcToDefault == FALSE) {
1890         if (srcCMP->cmType == INDEX_CM_TYPE) {
1891             if (expandICM) {
1892                 nbands = srcCMP->numComponents;
1893                 hintP->cvtSrcToDefault = TRUE;
1894 
1895                 if (dstCMP->isDefaultCompatCM) {
1896                     hintP->allocDefaultDst = FALSE;
1897                     hintP->cvtToDst = FALSE;
1898                 }
1899                 else if (dstCMP->isDefaultCompatCM) {
1900                     hintP->allocDefaultDst = FALSE;
1901                     hintP->cvtToDst = FALSE;
1902                 }
1903             }
1904             else {
1905                 nbands = 1;
1906                 hintP->cvtSrcToDefault = FALSE;
1907             }
1908 
1909         }
1910         else {
1911             if (srcP->hints.packing & INTERLEAVED) {
1912                 nbands = srcCMP->numComponents;
1913             }
1914             else {
1915                 nbands = 1;
1916             }
1917 
1918             /* Look at the packing */
1919             if ((srcP->hints.packing&BYTE_INTERLEAVED)==BYTE_INTERLEAVED ||
1920                 (srcP->hints.packing&SHORT_INTERLEAVED)==SHORT_INTERLEAVED||
1921                 (srcP->hints.packing&BYTE_SINGLE_BAND) == BYTE_SINGLE_BAND||
1922                 (srcP->hints.packing&SHORT_SINGLE_BAND)==SHORT_SINGLE_BAND||
1923                 (srcP->hints.packing&BYTE_BANDED)  == BYTE_BANDED       ||
1924                 (srcP->hints.packing&SHORT_BANDED) == SHORT_BANDED) {
1925                 /* Can use src directly */
1926                 hintP->cvtSrcToDefault = FALSE;
1927             }
1928             else {
1929                 /* Must be packed or custom */
1930                 hintP->cvtSrcToDefault = TRUE;
1931             }
1932         }
1933     }
1934     if (hintP->cvtSrcToDefault) {
1935         /* By definition */
1936         nbands = 4;  /* What about alpha? */
1937         hintP->dataType = BYTE_DATA_TYPE;
1938         hintP->needToCopy = TRUE;
1939 
1940         if (srcP->imageType == dstP->imageType) {
1941             hintP->cvtToDst = TRUE;
1942         }
1943         else if (dstP->cmodel.isDefaultCM) {
1944             /* Not necessarily */
1945             hintP->cvtToDst = FALSE;
1946         }
1947         else {
1948             hintP->cvtToDst = TRUE;
1949         }
1950     }
1951     else {
1952         int srcImageType = srcP->imageType;
1953         int dstImageType = dstP->imageType;
1954         /* Special case where we need to fill in alpha values */
1955         if (srcCMP->isDefaultCompatCM && dstCMP->isDefaultCompatCM) {
1956             int i;
1957             if (!srcCMP->supportsAlpha &&dstCMP->supportsAlpha) {
1958                 hintP->addAlpha = TRUE;
1959             }
1960             for (i=0; i < srcCMP->numComponents; i++) {
1961                 if (srcP->hints.colorOrder[i] != dstP->hints.colorOrder[i]){
1962                     if (!srcCMP->isDefaultCM) {
1963                         hintP->cvtSrcToDefault = TRUE;
1964                         srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1965                     }
1966                     if (!dstCMP->isDefaultCM) {
1967                         hintP->cvtToDst = TRUE;
1968                         dstImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1969                     }
1970 
1971                     break;
1972                 }
1973             }
1974         }
1975         else if (srcCMP->cmType != INDEX_CM_TYPE &&
1976                  !srcCMP->supportsAlpha && dstCMP->supportsAlpha)
1977         {
1978             /* We've already handled the index case.  This is for the rest of the cases */
1979             srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1980             hintP->cvtSrcToDefault = TRUE;
1981         }
1982 
1983         hintP->allocDefaultDst = FALSE;
1984         if (srcImageType == dstImageType) {
1985             /* Same image type so use it */
1986             hintP->cvtToDst = FALSE;
1987         }
1988         else if (srcImageType == TYPE_INT_RGB &&
1989                  (dstImageType == TYPE_INT_ARGB ||
1990                   dstImageType == TYPE_INT_ARGB_PRE)) {
1991             hintP->cvtToDst = FALSE;
1992         }
1993         else if (srcImageType == TYPE_INT_BGR &&
1994                  (dstImageType == TYPE_4BYTE_ABGR ||
1995                   dstImageType == TYPE_4BYTE_ABGR_PRE)) {
1996             hintP->cvtToDst = FALSE;
1997         }
1998         else if (srcP->hints.packing == dstP->hints.packing) {
1999             /* Now what? */
2000 
2001             /* Check color order */
2002 
2003             /* Check if just need to scale the data */
2004 
2005             hintP->cvtToDst = TRUE;
2006         }
2007         else {
2008             /* Don't know what it is so convert it */
2009             hintP->allocDefaultDst = TRUE;
2010             hintP->cvtToDst = TRUE;
2011         }
2012         hintP->needToCopy = (ncomponents > nbands);
2013     }
2014 
2015     return nbands;
2016 }
2017 
2018 
2019 static int
expandPacked(JNIEnv * env,BufImageS_t * img,ColorModelS_t * cmP,RasterS_t * rasterP,int component,unsigned char * bdataP)2020 expandPacked(JNIEnv *env, BufImageS_t *img, ColorModelS_t *cmP,
2021              RasterS_t *rasterP, int component, unsigned char *bdataP) {
2022 
2023     if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {
2024         switch (rasterP->dataType) {
2025         case BYTE_DATA_TYPE:
2026             if (expandPackedBCR(env, rasterP, component, bdataP) < 0) {
2027                 /* Must have been an error */
2028                 return -1;
2029             }
2030             break;
2031 
2032         case SHORT_DATA_TYPE:
2033             if (expandPackedICR(env, rasterP, component, bdataP) < 0) {
2034                 /* Must have been an error */
2035                 return -1;
2036             }
2037             break;
2038 
2039         case INT_DATA_TYPE:
2040             if (expandPackedICR(env, rasterP, component, bdataP) < 0) {
2041                 /* Must have been an error */
2042                 return -1;
2043             }
2044             break;
2045 
2046         default:
2047             /* REMIND: Return some sort of error */
2048             return -1;
2049         }
2050     }
2051     else {
2052         /* REMIND: Return some sort of error */
2053         return -1;
2054     }
2055 
2056     return 0;
2057 }
2058 
2059 #define NUM_LINES    10
2060 
2061 static int
cvtCustomToDefault(JNIEnv * env,BufImageS_t * imageP,int component,unsigned char * dataP)2062 cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,
2063                    unsigned char *dataP) {
2064     const RasterS_t *rasterP = &imageP->raster;
2065     const int w = rasterP->width;
2066     const int h = rasterP->height;
2067 
2068     int y;
2069     jintArray jpixels = NULL;
2070     jint *pixels;
2071     unsigned char *dP = dataP;
2072     int numLines = h > NUM_LINES ? NUM_LINES : h;
2073 
2074     /* it is safe to calculate the scan length, because width has been verified
2075      * on creation of the mlib image
2076      */
2077     const int scanLength = w * 4;
2078 
2079     int nbytes = 0;
2080     if (!SAFE_TO_MULT(numLines, scanLength)) {
2081         return -1;
2082     }
2083 
2084     nbytes = numLines * scanLength;
2085 
2086     jpixels = (*env)->NewIntArray(env, nbytes);
2087     if (JNU_IsNull(env, jpixels)) {
2088         (*env)->ExceptionClear(env);
2089         JNU_ThrowOutOfMemoryError(env, "Out of Memory");
2090         return -1;
2091     }
2092 
2093     for (y = 0; y < h; y += numLines) {
2094         if (y + numLines > h) {
2095             numLines = h - y;
2096             nbytes = numLines * scanLength;
2097         }
2098 
2099         (*env)->CallObjectMethod(env, imageP->jimage,
2100                                  g_BImgGetRGBMID, 0, y,
2101                                  w, numLines,
2102                                  jpixels, 0, w);
2103         if ((*env)->ExceptionOccurred(env)) {
2104             (*env)->DeleteLocalRef(env, jpixels);
2105             return -1;
2106         }
2107 
2108         pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);
2109         if (pixels == NULL) {
2110             (*env)->DeleteLocalRef(env, jpixels);
2111             return -1;
2112         }
2113 
2114         memcpy(dP, pixels, nbytes);
2115         dP += nbytes;
2116 
2117         (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels,
2118                                               JNI_ABORT);
2119     }
2120 
2121     /* Need to release the array */
2122     (*env)->DeleteLocalRef(env, jpixels);
2123 
2124     return 0;
2125 }
2126 
2127 static int
cvtDefaultToCustom(JNIEnv * env,BufImageS_t * imageP,int component,unsigned char * dataP)2128 cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component,
2129                    unsigned char *dataP) {
2130     const RasterS_t *rasterP = &imageP->raster;
2131     const int w = rasterP->width;
2132     const int h = rasterP->height;
2133 
2134     int y;
2135     jintArray jpixels = NULL;
2136     jint *pixels;
2137     unsigned char *dP = dataP;
2138     int numLines = h > NUM_LINES ? NUM_LINES : h;
2139 
2140     /* it is safe to calculate the scan length, because width has been verified
2141      * on creation of the mlib image
2142      */
2143     const int scanLength = w * 4;
2144 
2145     int nbytes = 0;
2146     if (!SAFE_TO_MULT(numLines, scanLength)) {
2147         return -1;
2148     }
2149 
2150     nbytes = numLines * scanLength;
2151 
2152     jpixels = (*env)->NewIntArray(env, nbytes);
2153     if (JNU_IsNull(env, jpixels)) {
2154         (*env)->ExceptionClear(env);
2155         JNU_ThrowOutOfMemoryError(env, "Out of Memory");
2156         return -1;
2157     }
2158 
2159     for (y = 0; y < h; y += numLines) {
2160         if (y + numLines > h) {
2161             numLines = h - y;
2162             nbytes = numLines * scanLength;
2163         }
2164 
2165         pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);
2166         if (pixels == NULL) {
2167             (*env)->DeleteLocalRef(env, jpixels);
2168             return -1;
2169         }
2170 
2171         memcpy(pixels, dP, nbytes);
2172         dP += nbytes;
2173 
2174        (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, 0);
2175 
2176        (*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y,
2177                                 w, numLines, jpixels,
2178                                 0, w);
2179        if ((*env)->ExceptionOccurred(env)) {
2180            (*env)->DeleteLocalRef(env, jpixels);
2181            return -1;
2182        }
2183     }
2184 
2185     /* Need to release the array */
2186     (*env)->DeleteLocalRef(env, jpixels);
2187 
2188     return 0;
2189 }
2190 
2191 static int
allocateArray(JNIEnv * env,BufImageS_t * imageP,mlib_image ** mlibImagePP,void ** dataPP,int isSrc,int cvtToDefault,int addAlpha)2192 allocateArray(JNIEnv *env, BufImageS_t *imageP,
2193               mlib_image **mlibImagePP, void **dataPP, int isSrc,
2194               int cvtToDefault, int addAlpha) {
2195     void *dataP;
2196     unsigned char *cDataP;
2197     RasterS_t *rasterP = &imageP->raster;
2198     ColorModelS_t *cmP = &imageP->cmodel;
2199     int dataType = BYTE_DATA_TYPE;
2200     int width;
2201     int height;
2202     HintS_t *hintP = &imageP->hints;
2203     *dataPP = NULL;
2204 
2205     width = rasterP->width;
2206     height = rasterP->height;
2207 
2208     /* Useful for convolution? */
2209     /* This code is zero'ed out so that it cannot be called */
2210 
2211     /* To do this correctly, we need to expand src and dst in the     */
2212     /* same direction up/down/left/right only if both can be expanded */
2213     /* in that direction.  Expanding right and down is easy -         */
2214     /* increment width.  Expanding top and left requires bumping      */
2215     /* around pointers and incrementing the width/height              */
2216 
2217 #if 0
2218     if (0 && useEdges) {
2219         baseWidth  = rasterP->baseRasterWidth;
2220         baseHeight = rasterP->baseRasterHeight;
2221         baseXoff = rasterP->baseOriginX;
2222         baseYoff = rasterP->baseOriginY;
2223 
2224         if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {
2225             /* Can use edge */
2226             width++;
2227         }
2228         if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {
2229             /* Can use edge */
2230             height++;
2231         }
2232 
2233         if (rasterP->minX > baseXoff ) {
2234             /* Can use edge */
2235             width++;
2236             /* NEED TO BUMP POINTER BACK A PIXELSTRIDE */
2237         }
2238         if (rasterP->minY  > baseYoff) {
2239             /* Can use edge */
2240             height++;
2241             /* NEED TO BUMP POINTER BACK A SCANLINE */
2242         }
2243 
2244 
2245     }
2246 #endif
2247     if (cvtToDefault) {
2248         int status = 0;
2249         *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
2250         if (*mlibImagePP == NULL) {
2251             return -1;
2252         }
2253         cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2254         /* Make sure the image is cleared.
2255          * NB: the image dimension is already verified, so we can
2256          * safely calculate the length of the buffer.
2257          */
2258         memset(cDataP, 0, width*height*4);
2259 
2260         if (!isSrc) {
2261             return 0;
2262         }
2263 
2264         switch(imageP->cmodel.cmType) {
2265         case INDEX_CM_TYPE:
2266             /* REMIND: Need to rearrange according to dst cm */
2267             /* Fix 4213160, 4184283 */
2268             if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {
2269                 return expandICM(env, imageP, (unsigned int *)cDataP);
2270             }
2271             else {
2272                 return cvtCustomToDefault(env, imageP, -1, cDataP);
2273             }
2274 
2275         case DIRECT_CM_TYPE:
2276             switch(imageP->raster.dataType) {
2277             case BYTE_DATA_TYPE:
2278                 return expandPackedBCRdefault(env, rasterP, -1, cDataP,
2279                                               !imageP->cmodel.supportsAlpha);
2280             case SHORT_DATA_TYPE:
2281                 return expandPackedSCRdefault(env, rasterP, -1, cDataP,
2282                                               !imageP->cmodel.supportsAlpha);
2283             case INT_DATA_TYPE:
2284                 return expandPackedICRdefault(env, rasterP, -1, cDataP,
2285                                               !imageP->cmodel.supportsAlpha);
2286             }
2287         } /* switch(imageP->cmodel.cmType) */
2288 
2289         return cvtCustomToDefault(env, imageP, -1, cDataP);
2290     }
2291 
2292     /* Interleaved with shared data */
2293     dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2294                                                        NULL);
2295     if (dataP == NULL) {
2296         return -1;
2297     }
2298 
2299     /* Means we need to fill in alpha */
2300     if (!cvtToDefault && addAlpha) {
2301         *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
2302         if (*mlibImagePP != NULL) {
2303             unsigned int *dstP  = (unsigned int *)
2304                 mlib_ImageGetData(*mlibImagePP);
2305             int dstride = (*mlibImagePP)->stride>>2;
2306             int sstride = hintP->sStride>>2;
2307             unsigned int *srcP = (unsigned int *)
2308                 ((unsigned char *)dataP + hintP->dataOffset);
2309             unsigned int *dP, *sP;
2310             int x, y;
2311             for (y=0; y < height; y++, srcP += sstride, dstP += dstride){
2312                 sP = srcP;
2313                 dP = dstP;
2314                 for (x=0; x < width; x++) {
2315                     dP[x] = sP[x] | 0xff000000;
2316                 }
2317             }
2318         }
2319         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2320                                               JNI_ABORT);
2321         return 0;
2322     }
2323     else if ((hintP->packing & BYTE_INTERLEAVED) == BYTE_INTERLEAVED) {
2324         int nChans = (cmP->isDefaultCompatCM ? 4 : hintP->numChans);
2325         /* Easy case.  It is or is similar to the default CM so use
2326      * the array.  Must be byte data.
2327          */
2328             /* Create the medialib image */
2329         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE,
2330                                               nChans,
2331                                               width,
2332                                               height,
2333                                               hintP->sStride,
2334                                               (unsigned char *)dataP
2335                                               + hintP->dataOffset);
2336     }
2337     else if ((hintP->packing & SHORT_INTERLEAVED) == SHORT_INTERLEAVED) {
2338         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
2339                                               hintP->numChans,
2340                                               width,
2341                                               height,
2342                                               imageP->raster.scanlineStride*2,
2343                                               (unsigned short *)dataP
2344                                               + hintP->channelOffset);
2345     }
2346     else {
2347         /* Release the data array */
2348         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2349                                               JNI_ABORT);
2350         return -1;
2351     }
2352 
2353     *dataPP = dataP;
2354     return 0;
2355 }
2356 
2357 static int
allocateRasterArray(JNIEnv * env,RasterS_t * rasterP,mlib_image ** mlibImagePP,void ** dataPP,int isSrc)2358 allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
2359                     mlib_image **mlibImagePP, void **dataPP, int isSrc) {
2360     void *dataP;
2361     unsigned char *cDataP;
2362     int dataType = BYTE_DATA_TYPE;
2363     int width;
2364     int height;
2365     int dataSize;
2366     int offset;
2367 
2368     *dataPP = NULL;
2369 
2370     width = rasterP->width;
2371     height = rasterP->height;
2372 
2373     if (rasterP->numBands <= 0 || rasterP->numBands > 4) {
2374         /* REMIND: Fix this */
2375         return -1;
2376     }
2377 
2378     /* Useful for convolution? */
2379     /* This code is zero'ed out so that it cannot be called */
2380 
2381     /* To do this correctly, we need to expand src and dst in the     */
2382     /* same direction up/down/left/right only if both can be expanded */
2383     /* in that direction.  Expanding right and down is easy -         */
2384     /* increment width.  Expanding top and left requires bumping      */
2385     /* around pointers and incrementing the width/height              */
2386 
2387 #if 0
2388     if (0 && useEdges) {
2389         baseWidth  = rasterP->baseRasterWidth;
2390         baseHeight = rasterP->baseRasterHeight;
2391         baseXoff = rasterP->baseOriginX;
2392         baseYoff = rasterP->baseOriginY;
2393 
2394         if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {
2395             /* Can use edge */
2396             width++;
2397         }
2398         if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {
2399             /* Can use edge */
2400             height++;
2401         }
2402 
2403         if (rasterP->minX > baseXoff ) {
2404             /* Can use edge */
2405             width++;
2406             /* NEED TO BUMP POINTER BACK A PIXELSTRIDE */
2407         }
2408         if (rasterP->minY  > baseYoff) {
2409             /* Can use edge */
2410             height++;
2411             /* NEED TO BUMP POINTER BACK A SCANLINE */
2412         }
2413 
2414 
2415     }
2416 #endif
2417     switch (rasterP->type) {
2418     case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:
2419         if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&
2420               SAFE_TO_ALLOC_2(width, 4) &&
2421               SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4)))
2422         {
2423             return -1;
2424         }
2425         offset = 4 * rasterP->chanOffsets[0];
2426         dataSize = 4 * (*env)->GetArrayLength(env, rasterP->jdata);
2427 
2428         if (offset < 0 || offset >= dataSize ||
2429             width > rasterP->scanlineStride ||
2430             ((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset)
2431         {
2432             // raster data buffer is too short
2433             return -1;
2434         }
2435         dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2436                                                            NULL);
2437         if (dataP == NULL) {
2438             return -1;
2439         }
2440         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, 4,
2441                                               width, height,
2442                                               rasterP->scanlineStride*4,
2443                                               (unsigned char *)dataP + offset);
2444         *dataPP = dataP;
2445         return 0;
2446     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:
2447         if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&
2448               SAFE_TO_ALLOC_2(rasterP->scanlineStride, height)))
2449         {
2450             return -1;
2451         }
2452         offset = rasterP->chanOffsets[0];
2453         dataSize = (*env)->GetArrayLength(env, rasterP->jdata);
2454 
2455         if (offset < 0 || offset >= dataSize ||
2456             width * rasterP->numBands > rasterP->scanlineStride ||
2457             ((width * rasterP->numBands) +
2458              (height - 1) * rasterP->scanlineStride) > dataSize - offset)
2459         {
2460             // raster data buffer is too short
2461             return -1;
2462         }
2463         dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2464                                                            NULL);
2465         if (dataP == NULL) {
2466             return -1;
2467         }
2468         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, rasterP->numBands,
2469                                               width, height,
2470                                               rasterP->scanlineStride,
2471                                               (unsigned char *)dataP + offset);
2472         *dataPP = dataP;
2473         return 0;
2474     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:
2475         if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&
2476               SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&
2477               SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 2)))
2478         {
2479               return -1;
2480         }
2481         offset = rasterP->chanOffsets[0] * 2;
2482         dataSize = 2 * (*env)->GetArrayLength(env, rasterP->jdata);
2483 
2484         if (offset < 0 || offset >= dataSize ||
2485             width * rasterP->numBands > rasterP->scanlineStride ||
2486             (((width * rasterP->numBands) +
2487              (height - 1) * rasterP->scanlineStride)) * 2 > dataSize - offset)
2488         {
2489             // raster data buffer is too short
2490              return -1;
2491         }
2492         dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2493                                                            NULL);
2494         if (dataP == NULL) {
2495             return -1;
2496         }
2497         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
2498                                                      rasterP->numBands,
2499                                                      width, height,
2500                                                      rasterP->scanlineStride*2,
2501                                                      (unsigned char *)dataP + offset);
2502         *dataPP = dataP;
2503         return 0;
2504 
2505     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
2506         *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2507                                         width, height);
2508         if (*mlibImagePP == NULL) {
2509             return -1;
2510         }
2511         if (!isSrc) return 0;
2512         cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2513         return expandPackedBCR(env, rasterP, -1, cDataP);
2514 
2515     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:
2516         if (rasterP->sppsm.maxBitSize <= 8) {
2517             *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2518                                             width, height);
2519             if (*mlibImagePP == NULL) {
2520                 return -1;
2521             }
2522             if (!isSrc) return 0;
2523             cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2524             return expandPackedSCR(env, rasterP, -1, cDataP);
2525         }
2526         break;
2527     case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:
2528         if (rasterP->sppsm.maxBitSize <= 8) {
2529             *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2530                                             width, height);
2531             if (*mlibImagePP == NULL) {
2532                 return -1;
2533             }
2534             if (!isSrc) return 0;
2535             cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2536             return expandPackedICR(env, rasterP, -1, cDataP);
2537         }
2538         break;
2539     }
2540 
2541     /* Just expand it right now */
2542     switch (rasterP->dataType) {
2543     case BYTE_DATA_TYPE:
2544         if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2545                                              width, height)) == NULL) {
2546             return -1;
2547         }
2548         if (isSrc) {
2549             if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {
2550                 (*sMlibSysFns.deleteImageFP)(*mlibImagePP);
2551                 return -1;
2552             }
2553         }
2554         break;
2555 
2556     case SHORT_DATA_TYPE:
2557         if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_SHORT,
2558                                                     rasterP->numBands,
2559                                                     width, height)) == NULL) {
2560             return -1;
2561         }
2562         if (isSrc) {
2563             if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {
2564                 (*sMlibSysFns.deleteImageFP)(*mlibImagePP);
2565                 return -1;
2566             }
2567         }
2568         break;
2569 
2570     default:
2571         return -1;
2572     }
2573     return 0;
2574 }
2575 
2576 static void
freeArray(JNIEnv * env,BufImageS_t * srcimageP,mlib_image * srcmlibImP,void * srcdataP,BufImageS_t * dstimageP,mlib_image * dstmlibImP,void * dstdataP)2577 freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,
2578           void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,
2579           void *dstdataP) {
2580     jobject srcJdata = (srcimageP != NULL ? srcimageP->raster.jdata : NULL);
2581     jobject dstJdata = (dstimageP != NULL ? dstimageP->raster.jdata : NULL);
2582     freeDataArray(env, srcJdata, srcmlibImP, srcdataP,
2583                   dstJdata, dstmlibImP, dstdataP);
2584 }
2585 static void
freeDataArray(JNIEnv * env,jobject srcJdata,mlib_image * srcmlibImP,void * srcdataP,jobject dstJdata,mlib_image * dstmlibImP,void * dstdataP)2586 freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,
2587           void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,
2588           void *dstdataP)
2589 {
2590     /* Free the medialib image */
2591     if (srcmlibImP) {
2592         (*sMlibSysFns.deleteImageFP)(srcmlibImP);
2593     }
2594 
2595     /* Release the array */
2596     if (srcdataP) {
2597         (*env)->ReleasePrimitiveArrayCritical(env, srcJdata,
2598                                               srcdataP, JNI_ABORT);
2599     }
2600 
2601     /* Free the medialib image */
2602     if (dstmlibImP) {
2603         (*sMlibSysFns.deleteImageFP)(dstmlibImP);
2604     }
2605 
2606     /* Release the array */
2607     if (dstdataP) {
2608         (*env)->ReleasePrimitiveArrayCritical(env, dstJdata,
2609                                               dstdataP, 0);
2610     }
2611 }
2612 
2613 #define ERR_BAD_IMAGE_LAYOUT (-2)
2614 
2615 #define CHECK_DST_ARRAY(start_offset, elements_per_scan, elements_per_pixel) \
2616     do {                                                                     \
2617         int offset = (start_offset);                                         \
2618         int lastScanOffset;                                                  \
2619                                                                              \
2620         if (!SAFE_TO_MULT((elements_per_scan),                               \
2621                           (rasterP->height - 1)))                            \
2622         {                                                                    \
2623             return ERR_BAD_IMAGE_LAYOUT;                                     \
2624         }                                                                    \
2625         lastScanOffset = (elements_per_scan) * (rasterP->height - 1);        \
2626                                                                              \
2627         if (!SAFE_TO_ADD(offset, lastScanOffset)) {                          \
2628             return ERR_BAD_IMAGE_LAYOUT;                                     \
2629         }                                                                    \
2630         lastScanOffset += offset;                                            \
2631                                                                              \
2632         if (!SAFE_TO_MULT((elements_per_pixel), rasterP->width)) {           \
2633             return ERR_BAD_IMAGE_LAYOUT;                                     \
2634         }                                                                    \
2635         offset = (elements_per_pixel) * rasterP->width;                      \
2636                                                                              \
2637         if (!SAFE_TO_ADD(offset, lastScanOffset)) {                          \
2638             return ERR_BAD_IMAGE_LAYOUT;                                     \
2639         }                                                                    \
2640         lastScanOffset += offset;                                            \
2641                                                                              \
2642         if (dataArrayLength < lastScanOffset) {                              \
2643             return ERR_BAD_IMAGE_LAYOUT;                                     \
2644         }                                                                    \
2645     } while(0);                                                              \
2646 
2647 static int
storeImageArray(JNIEnv * env,BufImageS_t * srcP,BufImageS_t * dstP,mlib_image * mlibImP)2648 storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
2649                 mlib_image *mlibImP) {
2650     int mStride;
2651     unsigned char *cmDataP, *dataP, *cDataP;
2652     HintS_t *hintP = &dstP->hints;
2653     RasterS_t *rasterP = &dstP->raster;
2654     jsize dataArrayLength = (*env)->GetArrayLength(env, rasterP->jdata);
2655     int y;
2656 
2657     /* REMIND: Store mlib data type? */
2658 
2659     /* Check if it is an IndexColorModel */
2660     if (dstP->cmodel.cmType == INDEX_CM_TYPE) {
2661         if (dstP->raster.rasterType == COMPONENT_RASTER_TYPE) {
2662             return storeICMarray(env, srcP, dstP, mlibImP);
2663         }
2664         else {
2665             /* Packed or some other custom raster */
2666             cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2667             return cvtDefaultToCustom(env, dstP, -1, cmDataP);
2668         }
2669     }
2670 
2671     if (hintP->packing == BYTE_INTERLEAVED) {
2672         /* Write it back to the destination */
2673         if (rasterP->dataType != BYTE_DATA_TYPE) {
2674             /* We are working with a raster which was marked
2675                as a byte interleaved due to performance reasons.
2676                So, we have to convert the length of the data
2677                array to bytes as well.
2678             */
2679             if (!SAFE_TO_MULT(rasterP->dataSize, dataArrayLength)) {
2680                 return ERR_BAD_IMAGE_LAYOUT;
2681             }
2682             dataArrayLength *= rasterP->dataSize;
2683         }
2684 
2685         CHECK_DST_ARRAY(hintP->dataOffset, hintP->sStride, hintP->numChans);
2686         cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2687         mStride = mlib_ImageGetStride(mlibImP);
2688         dataP = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env,
2689                                                       rasterP->jdata, NULL);
2690         if (dataP == NULL) return 0;
2691         cDataP = dataP + hintP->dataOffset;
2692         for (y=0; y < rasterP->height;
2693              y++, cmDataP += mStride, cDataP += hintP->sStride)
2694         {
2695             memcpy(cDataP, cmDataP, rasterP->width*hintP->numChans);
2696         }
2697         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2698                                               JNI_ABORT);
2699     }
2700     else if (dstP->cmodel.cmType == DIRECT_CM_TYPE) {
2701         /* Just need to move bits */
2702         if (mlibImP->type == MLIB_BYTE) {
2703             if (dstP->hints.packing == PACKED_BYTE_INTER) {
2704                 return setPackedBCRdefault(env, rasterP, -1,
2705                                            (unsigned char *) mlibImP->data,
2706                                            dstP->cmodel.supportsAlpha);
2707             } else if (dstP->hints.packing == PACKED_SHORT_INTER) {
2708                 return setPackedSCRdefault(env, rasterP, -1,
2709                                            (unsigned char *) mlibImP->data,
2710                                            dstP->cmodel.supportsAlpha);
2711             } else if (dstP->hints.packing == PACKED_INT_INTER) {
2712                 return setPackedICRdefault(env, rasterP, -1,
2713                                            (unsigned char *) mlibImP->data,
2714                                            dstP->cmodel.supportsAlpha);
2715             }
2716         }
2717         else if (mlibImP->type == MLIB_SHORT) {
2718             return setPixelsFormMlibImage(env, rasterP, mlibImP);
2719         }
2720     }
2721     else {
2722         return cvtDefaultToCustom(env, dstP, -1,
2723                                   (unsigned char *)mlibImP->data);
2724     }
2725 
2726     return 0;
2727 }
2728 
2729 static int
storeRasterArray(JNIEnv * env,RasterS_t * srcP,RasterS_t * dstP,mlib_image * mlibImP)2730 storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,
2731                 mlib_image *mlibImP) {
2732     unsigned char *cDataP;
2733 
2734     switch(dstP->type) {
2735     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
2736         cDataP  = (unsigned char *) mlib_ImageGetData(mlibImP);
2737         return setPackedBCR(env, dstP, -1, cDataP);
2738 
2739     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:
2740         if (dstP->sppsm.maxBitSize <= 8) {
2741             cDataP  = (unsigned char *) mlib_ImageGetData(mlibImP);
2742             return setPackedSCR(env, dstP, -1, cDataP);
2743         }
2744         break;
2745     case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:
2746         if (dstP->sppsm.maxBitSize <= 8) {
2747             cDataP  = (unsigned char *) mlib_ImageGetData(mlibImP);
2748             return setPackedICR(env, dstP, -1, cDataP);
2749         }
2750     }
2751 
2752     return -1;
2753 }
2754 
2755 
2756 static int
storeICMarray(JNIEnv * env,BufImageS_t * srcP,BufImageS_t * dstP,mlib_image * mlibImP)2757 storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
2758               mlib_image *mlibImP)
2759 {
2760     int *argb;
2761     int x, y;
2762     unsigned char *dataP, *cDataP, *cP;
2763     unsigned char *sP;
2764     int aIdx, rIdx, gIdx, bIdx;
2765     ColorModelS_t *cmodelP = &dstP->cmodel;
2766     RasterS_t *rasterP = &dstP->raster;
2767 
2768     /* REMIND: Only works for RGB */
2769     if (cmodelP->csType != java_awt_color_ColorSpace_TYPE_RGB) {
2770         JNU_ThrowInternalError(env, "Writing to non-RGB images not implemented yet");
2771         return -1;
2772     }
2773 
2774     if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||
2775         srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
2776         srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)
2777     {
2778         aIdx = 0;
2779         rIdx = 1;
2780         gIdx = 2;
2781         bIdx = 3;
2782     }
2783     else if (srcP->imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR||
2784         srcP->imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)
2785     {
2786         aIdx = 0;
2787         rIdx = 3;
2788         gIdx = 2;
2789         bIdx = 1;
2790     }
2791     else if (srcP->imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR){
2792         rIdx = 2;
2793         gIdx = 1;
2794         bIdx = 0;
2795         aIdx = 0;       /* Ignored */
2796     }
2797     else if (srcP->cmodel.cmType == INDEX_CM_TYPE) {
2798         rIdx = 0;
2799         gIdx = 1;
2800         bIdx = 2;
2801         aIdx = 3;   /* Use supportsAlpha to see if it is really there */
2802     }
2803     else {
2804         return -1;
2805     }
2806 
2807     /* Lock down the destination raster */
2808     dataP = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env,
2809                                                   rasterP->jdata, NULL);
2810     if (dataP == NULL) {
2811         return -1;
2812     }
2813     argb = (*env)->GetPrimitiveArrayCritical(env, cmodelP->jrgb, NULL);
2814     if (argb == NULL) {
2815         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2816                                               JNI_ABORT);
2817         return -1;
2818     }
2819 
2820     cDataP = dataP + dstP->hints.dataOffset;
2821     sP = (unsigned char *) mlib_ImageGetData(mlibImP);
2822 
2823     for (y=0; y < rasterP->height; y++, cDataP += rasterP->scanlineStride) {
2824         cP = cDataP;
2825         for (x=0; x < rasterP->width; x++, cP += rasterP->pixelStride) {
2826             *cP = colorMatch(sP[rIdx], sP[gIdx], sP[bIdx], sP[aIdx],
2827                              (unsigned char *)argb, cmodelP->mapSize);
2828             sP += cmodelP->numComponents;
2829         }
2830     }
2831 
2832     (*env)->ReleasePrimitiveArrayCritical(env, cmodelP->jrgb, argb, JNI_ABORT);
2833     (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2834                                           JNI_ABORT);
2835     return -1;
2836 }
2837 
expandICM(JNIEnv * env,BufImageS_t * imageP,unsigned int * mDataP)2838 static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP)
2839 {
2840     ColorModelS_t *cmP = &imageP->cmodel;
2841     RasterS_t *rasterP = &imageP->raster;
2842     HintS_t *hintP     = &imageP->hints;
2843     int *rgb;
2844     int status = 0;
2845     unsigned char *dataP, *cP;
2846     unsigned int *mP;
2847     int width = rasterP->width;
2848     int height = rasterP->height;
2849     int x, y;
2850 
2851     /* Need to grab the lookup tables.  Right now only bytes */
2852     rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, cmP->jrgb, NULL);
2853     CHECK_NULL_RETURN(rgb, -1);
2854 
2855     /* Interleaved with shared data */
2856     dataP = (void *) (*env)->GetPrimitiveArrayCritical(env,
2857                                                        rasterP->jdata, NULL);
2858     if (dataP == NULL) {
2859         /* Release the lookup tables */
2860         (*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb, JNI_ABORT);
2861         return -1;
2862     }
2863 
2864     if (rasterP->dataType == BYTE_DATA_TYPE) {
2865         unsigned char *cDataP = ((unsigned char *)dataP) + hintP->dataOffset;
2866 
2867         for (y=0; y < height; y++) {
2868             mP = mDataP;
2869             cP = cDataP;
2870             for (x=0; x < width; x++, cP += rasterP->pixelStride) {
2871                 *mP++ = rgb[*cP];
2872             }
2873             mDataP += width;
2874             cDataP += rasterP->scanlineStride;
2875         }
2876     }
2877     else if (rasterP->dataType == SHORT_DATA_TYPE) {
2878         unsigned short *sDataP, *sP;
2879         sDataP = ((unsigned short *)dataP) + hintP->channelOffset;
2880 
2881         for (y=0; y < height; y++) {
2882             mP = mDataP;
2883             sP = sDataP;
2884             for (x=0; x < width; x++, sP+=rasterP->pixelStride) {
2885                 *mP++ = rgb[*sP];
2886             }
2887             mDataP += width;
2888             sDataP += rasterP->scanlineStride;
2889         }
2890     }
2891     else {
2892         /* Unknown type */
2893         status = -1;
2894     }
2895     /* Release the lookup table data */
2896     (*env)->ReleasePrimitiveArrayCritical(env, imageP->cmodel.jrgb,
2897                                           rgb, JNI_ABORT);
2898     /* Release the data array */
2899     (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata,
2900                                           dataP, JNI_ABORT);
2901     return status;
2902 }
2903 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
expandPackedBCR(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * outDataP)2904 static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
2905                            unsigned char *outDataP)
2906 {
2907     int x, y, c;
2908     unsigned char *outP = outDataP;
2909     unsigned char *lineInP, *inP;
2910     jarray jInDataP;
2911     jint   *inDataP;
2912     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
2913 
2914     if (rasterP->numBands > MAX_NUMBANDS) {
2915         return -1;
2916     }
2917 
2918     /* Grab data ptr, strides, offsets from raster */
2919     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
2920     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
2921     if (inDataP == NULL) {
2922         return -1;
2923     }
2924     lineInP =  (unsigned char *)inDataP + rasterP->chanOffsets[0];
2925 
2926     if (component < 0) {
2927         for (c=0; c < rasterP->numBands; c++) {
2928             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2929             if (roff[c] < 0) {
2930                 loff[c] = -roff[c];
2931                 roff[c] = 0;
2932             }
2933             else loff[c] = 0;
2934         }
2935         /* Convert the all bands */
2936         if (rasterP->numBands < 4) {
2937             /* Need to put in alpha */
2938             for (y=0; y < rasterP->height; y++) {
2939                 inP = lineInP;
2940                 for (x=0; x < rasterP->width; x++) {
2941                     for (c=0; c < rasterP->numBands; c++) {
2942                         *outP++ = (unsigned char)
2943                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2944                              <<loff[c]);
2945                     }
2946                     inP++;
2947                 }
2948                 lineInP += rasterP->scanlineStride;
2949             }
2950         }
2951         else {
2952             for (y=0; y < rasterP->height; y++) {
2953                 inP = lineInP;
2954                 for (x=0; x < rasterP->width; x++) {
2955                     for (c=0; c < rasterP->numBands; c++) {
2956                         *outP++ = (unsigned char)
2957                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2958                              <<loff[c]);
2959                     }
2960                     inP++;
2961                 }
2962                 lineInP += rasterP->scanlineStride;
2963             }
2964         }
2965     }
2966     else {
2967         c = component;
2968         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2969         if (roff[0] < 0) {
2970             loff[0] = -roff[0];
2971             roff[0] = 0;
2972         }
2973         else loff[c] = 0;
2974         for (y=0; y < rasterP->height; y++) {
2975             inP = lineInP;
2976             for (x=0; x < rasterP->width; x++) {
2977                 *outP++ = (unsigned char)
2978                     ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
2979                 inP++;
2980             }
2981             lineInP += rasterP->scanlineStride;
2982         }
2983     }
2984 
2985     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
2986 
2987     return 0;
2988 }
2989 
2990 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
expandPackedBCRdefault(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * outDataP,int forceAlpha)2991 static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
2992                                   int component, unsigned char *outDataP,
2993                                   int forceAlpha)
2994 {
2995     int x, y, c;
2996     unsigned char *outP = outDataP;
2997     unsigned char *lineInP, *inP;
2998     jarray jInDataP;
2999     jint   *inDataP;
3000     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3001     int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3002     int a = numBands;
3003 
3004     if (rasterP->numBands > MAX_NUMBANDS) {
3005         return -1;
3006     }
3007 
3008     /* Grab data ptr, strides, offsets from raster */
3009     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3010     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3011     if (inDataP == NULL) {
3012         return -1;
3013     }
3014     lineInP =  (unsigned char *)inDataP + rasterP->chanOffsets[0];
3015 
3016     if (component < 0) {
3017         for (c=0; c < rasterP->numBands; c++) {
3018             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3019             if (roff[c] < 0) {
3020                 loff[c] = -roff[c];
3021                 roff[c] = 0;
3022             }
3023             else loff[c] = 0;
3024         }
3025 
3026         /* Need to put in alpha */
3027         if (forceAlpha) {
3028             for (y=0; y < rasterP->height; y++) {
3029                 inP = lineInP;
3030                 for (x=0; x < rasterP->width; x++) {
3031                     *outP++ = 0xff;
3032                     for (c=0; c < numBands; c++) {
3033                         *outP++ = (unsigned char)
3034                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3035                              <<loff[c]);
3036                     }
3037                     inP++;
3038                 }
3039                 lineInP += rasterP->scanlineStride;
3040             }
3041         }
3042         else {
3043             for (y=0; y < rasterP->height; y++) {
3044                 inP = lineInP;
3045                 for (x=0; x < rasterP->width; x++) {
3046                     *outP++ = (unsigned char)
3047                         (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3048                          <<loff[a]);
3049                     for (c=0; c < numBands; c++) {
3050                         *outP++ = (unsigned char)
3051                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3052                              <<loff[c]);
3053                     }
3054                     inP++;
3055                 }
3056                 lineInP += rasterP->scanlineStride;
3057             }
3058         }
3059     }
3060     else {
3061         c = component;
3062         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3063         if (roff[0] < 0) {
3064             loff[0] = -roff[0];
3065             roff[0] = 0;
3066         }
3067         else loff[c] = 0;
3068         for (y=0; y < rasterP->height; y++) {
3069             inP = lineInP;
3070             for (x=0; x < rasterP->width; x++) {
3071                 *outP++ = (unsigned char)
3072                     ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3073                 inP++;
3074             }
3075             lineInP += rasterP->scanlineStride;
3076         }
3077     }
3078 
3079     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3080 
3081     return 0;
3082 }
3083 
3084 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
expandPackedSCR(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * outDataP)3085 static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
3086                            unsigned char *outDataP)
3087 {
3088     int x, y, c;
3089     unsigned char *outP = outDataP;
3090     unsigned short *lineInP, *inP;
3091     jarray jInDataP;
3092     jint   *inDataP;
3093     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3094 
3095     if (rasterP->numBands > MAX_NUMBANDS) {
3096         return -1;
3097     }
3098 
3099     /* Grab data ptr, strides, offsets from raster */
3100     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3101     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3102     if (inDataP == NULL) {
3103         return -1;
3104     }
3105     lineInP =  (unsigned short *)inDataP + rasterP->chanOffsets[0];
3106 
3107     if (component < 0) {
3108         for (c=0; c < rasterP->numBands; c++) {
3109             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3110             if (roff[c] < 0) {
3111                 loff[c] = -roff[c];
3112                 roff[c] = 0;
3113             }
3114             else loff[c] = 0;
3115         }
3116         /* Convert the all bands */
3117         if (rasterP->numBands < 4) {
3118             /* Need to put in alpha */
3119             for (y=0; y < rasterP->height; y++) {
3120                 inP = lineInP;
3121                 for (x=0; x < rasterP->width; x++) {
3122                     for (c=0; c < rasterP->numBands; c++) {
3123                         /*
3124                          *Not correct.  Might need to unpremult,
3125                          * shift, etc
3126                          */
3127                         *outP++ = (unsigned char)
3128                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3129                              <<loff[c]);
3130                     }
3131                     inP++;
3132                 }
3133                 lineInP += rasterP->scanlineStride;
3134             }
3135         } else {
3136             for (y=0; y < rasterP->height; y++) {
3137                 inP = lineInP;
3138                 for (x=0; x < rasterP->width; x++) {
3139                     for (c=0; c < rasterP->numBands; c++) {
3140                         /*
3141                          *Not correct.  Might need to unpremult,
3142                          * shift, etc
3143                          */
3144                         *outP++ = (unsigned char)
3145                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3146                              <<loff[c]);
3147                     }
3148                     inP++;
3149                 }
3150                 lineInP += rasterP->scanlineStride;
3151             }
3152         }
3153     }
3154     else {
3155         c = component;
3156         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3157         if (roff[0] < 0) {
3158             loff[0] = -roff[0];
3159             roff[0] = 0;
3160         }
3161         else loff[c] = 0;
3162         for (y=0; y < rasterP->height; y++) {
3163             inP = lineInP;
3164             for (x=0; x < rasterP->width; x++) {
3165                 *outP++ = (unsigned char)
3166                     ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3167                 inP++;
3168             }
3169             lineInP += rasterP->scanlineStride;
3170         }
3171     }
3172 
3173     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3174 
3175     return 0;
3176 }
3177 
3178 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
expandPackedSCRdefault(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * outDataP,int forceAlpha)3179 static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
3180                                   int component, unsigned char *outDataP,
3181                                   int forceAlpha)
3182 {
3183     int x, y, c;
3184     unsigned char *outP = outDataP;
3185     unsigned short *lineInP, *inP;
3186     jarray jInDataP;
3187     jint   *inDataP;
3188     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3189     int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3190     int a = numBands;
3191 
3192     if (rasterP->numBands > MAX_NUMBANDS) {
3193         return -1;
3194     }
3195 
3196     /* Grab data ptr, strides, offsets from raster */
3197     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3198     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3199     if (inDataP == NULL) {
3200         return -1;
3201     }
3202     lineInP =  (unsigned short *)inDataP + rasterP->chanOffsets[0];
3203 
3204     if (component < 0) {
3205         for (c=0; c < rasterP->numBands; c++) {
3206             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3207             if (roff[c] < 0) {
3208                 loff[c] = -roff[c];
3209                 roff[c] = 0;
3210             }
3211             else loff[c] = 0;
3212         }
3213 
3214         /* Need to put in alpha */
3215         if (forceAlpha) {
3216             for (y=0; y < rasterP->height; y++) {
3217                 inP = lineInP;
3218                 for (x=0; x < rasterP->width; x++) {
3219                     *outP++ = 0xff;
3220                     for (c=0; c < numBands; c++) {
3221                         /*
3222                          * Not correct.  Might need to unpremult,
3223                          * shift, etc
3224                          */
3225                         *outP++ = (unsigned char)
3226                                 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3227                                    <<loff[c]);
3228                     }
3229                     inP++;
3230                 }
3231                 lineInP += rasterP->scanlineStride;
3232             }
3233         }
3234         else {
3235             for (y=0; y < rasterP->height; y++) {
3236                 inP = lineInP;
3237                 for (x=0; x < rasterP->width; x++) {
3238                     *outP++ = (unsigned char)
3239                         (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3240                                    <<loff[a]);
3241                     for (c=0; c < numBands; c++) {
3242                         /*
3243                          * Not correct.  Might need to
3244                          * unpremult, shift, etc
3245                          */
3246                         *outP++ = (unsigned char)
3247                                 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3248                                    <<loff[c]);
3249                     }
3250                     inP++;
3251                 }
3252                 lineInP += rasterP->scanlineStride;
3253             }
3254         }
3255     }
3256     else {
3257         c = component;
3258         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3259         if (roff[0] < 0) {
3260             loff[0] = -roff[0];
3261             roff[0] = 0;
3262         }
3263         else loff[c] = 0;
3264         for (y=0; y < rasterP->height; y++) {
3265             inP = lineInP;
3266             for (x=0; x < rasterP->width; x++) {
3267                 *outP++ = (unsigned char)
3268                         ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3269                 inP++;
3270             }
3271             lineInP += rasterP->scanlineStride;
3272         }
3273     }
3274 
3275     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3276 
3277     return 0;
3278 
3279 }
3280 
3281 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
expandPackedICR(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * outDataP)3282 static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
3283                            unsigned char *outDataP)
3284 {
3285     int x, y, c;
3286     unsigned char *outP = outDataP;
3287     unsigned int *lineInP, *inP;
3288     jarray jInDataP;
3289     jint   *inDataP;
3290     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3291 
3292     if (rasterP->numBands > MAX_NUMBANDS) {
3293         return -1;
3294     }
3295 
3296     /* Grab data ptr, strides, offsets from raster */
3297     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3298     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3299     if (inDataP == NULL) {
3300         return -1;
3301     }
3302     lineInP =  (unsigned int *)inDataP + rasterP->chanOffsets[0];
3303 
3304     if (component < 0) {
3305         for (c=0; c < rasterP->numBands; c++) {
3306             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3307             if (roff[c] < 0) {
3308                 loff[c] = -roff[c];
3309                 roff[c] = 0;
3310             }
3311             else loff[c] = 0;
3312         }
3313         /* Convert the all bands */
3314         if (rasterP->numBands < 4) {
3315             for (y=0; y < rasterP->height; y++) {
3316                 inP = lineInP;
3317                 for (x=0; x < rasterP->width; x++) {
3318                     for (c=0; c < rasterP->numBands; c++) {
3319                         /*
3320                          * Not correct.  Might need to unpremult,
3321                          * shift, etc
3322                          */
3323                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3324                                    <<loff[c]);
3325                     }
3326                     inP++;
3327                 }
3328                 lineInP += rasterP->scanlineStride;
3329             }
3330         }
3331         else {
3332             for (y=0; y < rasterP->height; y++) {
3333                 inP = lineInP;
3334                 for (x=0; x < rasterP->width; x++) {
3335                     for (c=0; c < rasterP->numBands; c++) {
3336                         /*
3337                          * Not correct.  Might need to
3338                          * unpremult, shift, etc
3339                          */
3340                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3341                                    <<loff[c]);
3342                     }
3343                     inP++;
3344                 }
3345                 lineInP += rasterP->scanlineStride;
3346             }
3347         }
3348     }
3349     else {
3350         c = component;
3351         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3352         if (roff[0] < 0) {
3353             loff[0] = -roff[0];
3354             roff[0] = 0;
3355         }
3356         else loff[c] = 0;
3357         for (y=0; y < rasterP->height; y++) {
3358             inP = lineInP;
3359             for (x=0; x < rasterP->width; x++) {
3360                 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);
3361                 inP++;
3362             }
3363             lineInP += rasterP->scanlineStride;
3364         }
3365     }
3366 
3367     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3368 
3369     return 0;
3370 }
3371 
3372 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
expandPackedICRdefault(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * outDataP,int forceAlpha)3373 static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
3374                                   int component, unsigned char *outDataP,
3375                                   int forceAlpha)
3376 {
3377     int x, y, c;
3378     unsigned char *outP = outDataP;
3379     unsigned int *lineInP, *inP;
3380     jarray jInDataP;
3381     jint   *inDataP;
3382     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3383     int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3384     int a = numBands;
3385 
3386     if (rasterP->numBands > MAX_NUMBANDS) {
3387         return -1;
3388     }
3389 
3390     /* Grab data ptr, strides, offsets from raster */
3391     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3392     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3393     if (inDataP == NULL) {
3394         return -1;
3395     }
3396     lineInP =  (unsigned int *)inDataP + rasterP->chanOffsets[0];
3397 
3398     if (component < 0) {
3399         for (c=0; c < rasterP->numBands; c++) {
3400             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3401             if (roff[c] < 0) {
3402                 loff[c] = -roff[c];
3403                 roff[c] = 0;
3404             }
3405             else loff[c] = 0;
3406         }
3407 
3408         /* Need to put in alpha */
3409         if (forceAlpha) {
3410             for (y=0; y < rasterP->height; y++) {
3411                 inP = lineInP;
3412                 for (x=0; x < rasterP->width; x++) {
3413                     *outP++ = 0xff;
3414                     for (c=0; c < numBands; c++) {
3415                         /*
3416                          * Not correct.  Might need to unpremult,
3417                          * shift, etc
3418                          */
3419                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3420                                    <<loff[c]);
3421                     }
3422                     inP++;
3423                 }
3424                 lineInP += rasterP->scanlineStride;
3425             }
3426         }
3427         else {
3428             for (y=0; y < rasterP->height; y++) {
3429                 inP = lineInP;
3430                 for (x=0; x < rasterP->width; x++) {
3431                     *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3432                                    <<loff[a]);
3433                     for (c=0; c < numBands; c++) {
3434                         /*
3435                          * Not correct.  Might need to
3436                          * unpremult, shift, etc
3437                          */
3438                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3439                                    <<loff[c]);
3440                     }
3441                     inP++;
3442                 }
3443                 lineInP += rasterP->scanlineStride;
3444             }
3445         }
3446     }
3447     else {
3448         c = component;
3449         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3450         if (roff[0] < 0) {
3451             loff[0] = -roff[0];
3452             roff[0] = 0;
3453         }
3454         else loff[c] = 0;
3455         for (y=0; y < rasterP->height; y++) {
3456             inP = lineInP;
3457             for (x=0; x < rasterP->width; x++) {
3458                 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);
3459                 inP++;
3460             }
3461             lineInP += rasterP->scanlineStride;
3462         }
3463     }
3464 
3465     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3466 
3467     return 0;
3468 }
3469 
3470 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
setPackedBCR(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * inDataP)3471 static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
3472                         unsigned char *inDataP)
3473 {
3474     int x, y, c;
3475     unsigned char *inP = inDataP;
3476     unsigned char *lineOutP, *outP;
3477     jarray jOutDataP;
3478     jsize dataArrayLength;
3479     unsigned char *outDataP;
3480     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3481 
3482     if (rasterP->numBands > MAX_NUMBANDS) {
3483         return -1;
3484     }
3485 
3486     /* Grab data ptr, strides, offsets from raster */
3487     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3488     if (JNU_IsNull(env, jOutDataP)) {
3489         return -1;
3490     }
3491 
3492     dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3493     CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3494 
3495     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3496     if (outDataP == NULL) {
3497         return -1;
3498     }
3499     lineOutP = outDataP + rasterP->chanOffsets[0];
3500 
3501     if (component < 0) {
3502         for (c=0; c < rasterP->numBands; c++) {
3503             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3504             if (loff[c] < 0) {
3505                 roff[c] = -loff[c];
3506                 loff[c] = 0;
3507             }
3508             else roff[c] = 0;
3509         }
3510         /* Convert the all bands */
3511         for (y=0; y < rasterP->height; y++) {
3512             outP = lineOutP;
3513             *outP = 0;
3514             for (x=0; x < rasterP->width; x++) {
3515                 for (c=0; c < rasterP->numBands; c++, inP++) {
3516                     *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3517                 }
3518                 outP++;
3519             }
3520             lineOutP += rasterP->scanlineStride;
3521         }
3522     }
3523     else {
3524         c = component;
3525         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3526         if (loff[0] < 0) {
3527             roff[0] = -loff[0];
3528             loff[0] = 0;
3529         }
3530         else roff[c] = 0;
3531         for (y=0; y < rasterP->height; y++) {
3532             outP = lineOutP;
3533             for (x=0; x < rasterP->width; x++, inP++) {
3534                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3535                 outP++;
3536             }
3537             lineOutP += rasterP->scanlineStride;
3538         }
3539     }
3540 
3541     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3542 
3543     return 0;
3544 }
3545 
3546 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
setPackedSCR(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * inDataP)3547 static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
3548                            unsigned char *inDataP)
3549 {
3550     int x, y, c;
3551     unsigned char *inP = inDataP;
3552     unsigned short *lineOutP, *outP;
3553     jarray jOutDataP;
3554     jsize dataArrayLength;
3555     unsigned short *outDataP;
3556     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3557 
3558     if (rasterP->numBands > MAX_NUMBANDS) {
3559         return -1;
3560     }
3561 
3562     /* Grab data ptr, strides, offsets from raster */
3563     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3564     if (JNU_IsNull(env, jOutDataP)) {
3565         return -1;
3566     }
3567 
3568     dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3569     CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3570 
3571     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3572     if (outDataP == NULL) {
3573         return -1;
3574     }
3575     lineOutP = outDataP + rasterP->chanOffsets[0];
3576 
3577     if (component < 0) {
3578         for (c=0; c < rasterP->numBands; c++) {
3579             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3580             if (loff[c] < 0) {
3581                 roff[c] = -loff[c];
3582                 loff[c] = 0;
3583             }
3584             else roff[c] = 0;
3585         }
3586         /* Convert the all bands */
3587         for (y=0; y < rasterP->height; y++) {
3588             outP = lineOutP;
3589             for (x=0; x < rasterP->width; x++) {
3590                 for (c=0; c < rasterP->numBands; c++, inP++) {
3591                     /* Not correct.  Might need to unpremult, shift, etc */
3592                     *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3593                 }
3594                 outP++;
3595             }
3596             lineOutP += rasterP->scanlineStride;
3597         }
3598     }
3599     else {
3600         c = component;
3601         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3602         if (loff[0] < 0) {
3603             roff[0] = -loff[0];
3604             loff[0] = 0;
3605         }
3606         else roff[c] = 0;
3607         for (y=0; y < rasterP->height; y++) {
3608             outP = lineOutP;
3609             for (x=0; x < rasterP->width; x++, inP++) {
3610                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3611                 outP++;
3612             }
3613             lineOutP += rasterP->scanlineStride;
3614         }
3615     }
3616 
3617     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3618 
3619     return 0;
3620 }
3621 
3622 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
setPackedICR(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * inDataP)3623 static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
3624                            unsigned char *inDataP)
3625 {
3626     int x, y, c;
3627     unsigned char *inP = inDataP;
3628     unsigned int *lineOutP, *outP;
3629     jarray jOutDataP;
3630     jsize dataArrayLength;
3631     unsigned int *outDataP;
3632     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3633 
3634     if (rasterP->numBands > MAX_NUMBANDS) {
3635         return -1;
3636     }
3637 
3638     /* Grab data ptr, strides, offsets from raster */
3639     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3640     if (JNU_IsNull(env, jOutDataP)) {
3641         return -1;
3642     }
3643 
3644     dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3645     CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3646 
3647     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3648     if (outDataP == NULL) {
3649         return -1;
3650     }
3651     lineOutP = outDataP + rasterP->chanOffsets[0];
3652 
3653     if (component < 0) {
3654         for (c=0; c < rasterP->numBands; c++) {
3655             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3656             if (loff[c] < 0) {
3657                 roff[c] = -loff[c];
3658                 loff[c] = 0;
3659             }
3660             else roff[c] = 0;
3661         }
3662         /* Convert the all bands */
3663         for (y=0; y < rasterP->height; y++) {
3664             outP = lineOutP;
3665             for (x=0; x < rasterP->width; x++) {
3666                 for (c=0; c < rasterP->numBands; c++, inP++) {
3667                     /* Not correct.  Might need to unpremult, shift, etc */
3668                     *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3669                 }
3670                 outP++;
3671             }
3672             lineOutP += rasterP->scanlineStride;
3673         }
3674     }
3675     else {
3676         c = component;
3677         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3678         if (loff[0] < 0) {
3679             roff[0] = -loff[0];
3680             loff[0] = 0;
3681         }
3682         else roff[c] = 0;
3683 
3684         for (y=0; y < rasterP->height; y++) {
3685             outP = lineOutP;
3686             for (x=0; x < rasterP->width; x++, inP++) {
3687                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3688                 outP++;
3689             }
3690             lineOutP += rasterP->scanlineStride;
3691         }
3692     }
3693 
3694     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3695 
3696     return 0;
3697 }
3698 
3699 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
setPackedBCRdefault(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * inDataP,int supportsAlpha)3700 static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
3701                                int component, unsigned char *inDataP,
3702                                int supportsAlpha)
3703 {
3704     int x, y, c;
3705     unsigned char *inP = inDataP;
3706     unsigned char *lineOutP, *outP;
3707     jarray jOutDataP;
3708     jsize  dataArrayLength;
3709     unsigned char *outDataP;
3710     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3711     int a = rasterP->numBands - 1;
3712 
3713     if (rasterP->numBands > MAX_NUMBANDS) {
3714         return -1;
3715     }
3716 
3717     /* Grab data ptr, strides, offsets from raster */
3718     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3719     if (JNU_IsNull(env, jOutDataP)) {
3720         return -1;
3721     }
3722 
3723     dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3724     CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3725 
3726     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3727     if (outDataP == NULL) {
3728         return -1;
3729     }
3730     lineOutP = outDataP + rasterP->chanOffsets[0];
3731 
3732     if (component < 0) {
3733         for (c=0; c < rasterP->numBands; c++) {
3734             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3735             if (loff[c] < 0) {
3736                 roff[c] = -loff[c];
3737                 loff[c] = 0;
3738             }
3739             else roff[c] = 0;
3740         }
3741         /* Convert the all bands */
3742         if (supportsAlpha) {
3743             for (y=0; y < rasterP->height; y++) {
3744                 outP = lineOutP;
3745                 *outP = 0;
3746                 for (x=0; x < rasterP->width; x++) {
3747                     *outP |= (*inP<<loff[a]>>roff[a])&
3748                         rasterP->sppsm.maskArray[a];
3749                     inP++;
3750                     for (c=0; c < rasterP->numBands-1; c++, inP++) {
3751                         *outP |= (*inP<<loff[c]>>roff[c])&
3752                             rasterP->sppsm.maskArray[c];
3753                     }
3754                     outP++;
3755                 }
3756                 lineOutP += rasterP->scanlineStride;
3757             }
3758         }
3759         else {
3760             for (y=0; y < rasterP->height; y++) {
3761                 outP = lineOutP;
3762                 *outP = 0;
3763                 for (x=0; x < rasterP->width; x++) {
3764                     inP++;
3765                     for (c=0; c < rasterP->numBands; c++, inP++) {
3766                         *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3767                     }
3768                     outP++;
3769                 }
3770                 lineOutP += rasterP->scanlineStride;
3771             }
3772         }
3773     }
3774     else {
3775         c = component;
3776         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3777         if (loff[0] < 0) {
3778             roff[0] = -loff[0];
3779             loff[0] = 0;
3780         }
3781         else roff[c] = 0;
3782         for (y=0; y < rasterP->height; y++) {
3783             outP = lineOutP;
3784             for (x=0; x < rasterP->width; x++, inP++) {
3785                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3786                 outP++;
3787             }
3788             lineOutP += rasterP->scanlineStride;
3789         }
3790     }
3791 
3792     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3793 
3794     return 0;
3795 }
3796 
3797 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
setPackedSCRdefault(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * inDataP,int supportsAlpha)3798 static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
3799                                int component, unsigned char *inDataP,
3800                                int supportsAlpha)
3801 {
3802     int x, y, c;
3803     unsigned char *inP = inDataP;
3804     unsigned short *lineOutP, *outP;
3805     jarray jOutDataP;
3806     jsize dataArrayLength;
3807     unsigned short *outDataP;
3808     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3809     int a = rasterP->numBands - 1;
3810 
3811     if (rasterP->numBands > MAX_NUMBANDS) {
3812         return -1;
3813     }
3814 
3815     /* Grab data ptr, strides, offsets from raster */
3816     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3817     if (JNU_IsNull(env, jOutDataP)) {
3818         return -1;
3819     }
3820     dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3821     CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3822 
3823     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3824     if (outDataP == NULL) {
3825         return -1;
3826     }
3827     lineOutP = outDataP + rasterP->chanOffsets[0];
3828 
3829     if (component < 0) {
3830         for (c=0; c < rasterP->numBands; c++) {
3831             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3832             if (loff[c] < 0) {
3833                 roff[c] = -loff[c];
3834                 loff[c] = 0;
3835             }
3836             else roff[c] = 0;
3837         }
3838         /* Convert the all bands */
3839         if (supportsAlpha) {
3840             for (y=0; y < rasterP->height; y++) {
3841                 outP = lineOutP;
3842                 for (x=0; x < rasterP->width; x++) {
3843                     *outP |= (*inP<<loff[a]>>roff[a])&
3844                         rasterP->sppsm.maskArray[a];
3845                     inP++;
3846                     for (c=0; c < rasterP->numBands-1; c++, inP++) {
3847                         /* Not correct.  Might need to unpremult, shift, etc */
3848                         *outP |= (*inP<<loff[c]>>roff[c])&
3849                             rasterP->sppsm.maskArray[c];
3850                     }
3851                     outP++;
3852                 }
3853                 lineOutP += rasterP->scanlineStride;
3854             }
3855         }
3856         else {
3857             for (y=0; y < rasterP->height; y++) {
3858                 outP = lineOutP;
3859                 for (x=0; x < rasterP->width; x++) {
3860                     inP++;
3861                     for (c=0; c < rasterP->numBands; c++, inP++) {
3862                         /* Not correct.  Might need to unpremult, shift, etc */
3863                         *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3864                     }
3865                     outP++;
3866                 }
3867                 lineOutP += rasterP->scanlineStride;
3868             }
3869         }
3870     }
3871     else {
3872         c = component;
3873         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3874         if (loff[0] < 0) {
3875             roff[0] = -loff[0];
3876             loff[0] = 0;
3877         }
3878         else roff[c] = 0;
3879         for (y=0; y < rasterP->height; y++) {
3880             outP = lineOutP;
3881             for (x=0; x < rasterP->width; x++, inP++) {
3882                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3883                 outP++;
3884             }
3885             lineOutP += rasterP->scanlineStride;
3886         }
3887     }
3888 
3889     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3890 
3891     return 0;
3892 }
3893 
3894 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
setPackedICRdefault(JNIEnv * env,RasterS_t * rasterP,int component,unsigned char * inDataP,int supportsAlpha)3895 static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
3896                                int component, unsigned char *inDataP,
3897                                int supportsAlpha)
3898 {
3899     int x, y, c;
3900     unsigned char *inP = inDataP;
3901     unsigned int *lineOutP, *outP;
3902     jarray jOutDataP;
3903     jsize dataArrayLength;
3904     unsigned int *outDataP;
3905     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3906     int a = rasterP->numBands - 1;
3907 
3908     if (rasterP->numBands > MAX_NUMBANDS) {
3909         return -1;
3910     }
3911 
3912     /* Grab data ptr, strides, offsets from raster */
3913     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3914     if (JNU_IsNull(env, jOutDataP)) {
3915         return -1;
3916     }
3917 
3918     dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3919     CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3920 
3921     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3922     if (outDataP == NULL) {
3923         return -1;
3924     }
3925     lineOutP = outDataP + rasterP->chanOffsets[0];
3926 
3927     if (component < 0) {
3928         for (c=0; c < rasterP->numBands; c++) {
3929             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3930             if (loff[c] < 0) {
3931                 roff[c] = -loff[c];
3932                 loff[c] = 0;
3933             }
3934             else roff[c] = 0;
3935         }
3936         /* Convert the all bands */
3937         if (supportsAlpha) {
3938             for (y=0; y < rasterP->height; y++) {
3939                 outP = lineOutP;
3940                 for (x=0; x < rasterP->width; x++) {
3941                     *outP |= (*inP<<loff[a]>>roff[a])&
3942                         rasterP->sppsm.maskArray[a];
3943                     inP++;
3944                     for (c=0; c < rasterP->numBands-1; c++, inP++) {
3945                         /* Not correct.  Might need to unpremult, shift, etc */
3946                         *outP |= (*inP<<loff[c]>>roff[c])&
3947                             rasterP->sppsm.maskArray[c];
3948                     }
3949                     outP++;
3950                 }
3951                 lineOutP += rasterP->scanlineStride;
3952             }
3953         }
3954         else {
3955             for (y=0; y < rasterP->height; y++) {
3956                 outP = lineOutP;
3957                 for (x=0; x < rasterP->width; x++) {
3958                     inP++;
3959                     for (c=0; c < rasterP->numBands; c++, inP++) {
3960                         /* Not correct.  Might need to unpremult, shift, etc */
3961                         *outP |= (*inP<<loff[c]>>roff[c])&
3962                             rasterP->sppsm.maskArray[c];
3963                     }
3964                     outP++;
3965                 }
3966                 lineOutP += rasterP->scanlineStride;
3967             }
3968         }
3969     }
3970     else {
3971         c = component;
3972         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3973         if (loff[0] < 0) {
3974             roff[0] = -loff[0];
3975             loff[0] = 0;
3976         }
3977         else roff[c] = 0;
3978 
3979         for (y=0; y < rasterP->height; y++) {
3980             outP = lineOutP;
3981             for (x=0; x < rasterP->width; x++, inP++) {
3982                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3983                 outP++;
3984             }
3985             lineOutP += rasterP->scanlineStride;
3986         }
3987     }
3988 
3989     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3990 
3991     return 0;
3992 }
3993 
3994 /* This is temporary code.  Should go away when there is better color
3995  * conversion code available.
3996  * REMIND:  Ignoring alpha
3997  */
3998 /* returns the absolute value x */
3999 #define ABS(x) ((x) < 0 ? -(x) : (x))
4000 #define CLIP(val,min,max)       ((val < min) ? min : ((val > max) ? max : val))
4001 
4002 static int
colorMatch(int r,int g,int b,int a,unsigned char * argb,int numColors)4003 colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors) {
4004     int besti = 0;
4005     int mindist, i, t, d;
4006     unsigned char red, green, blue;
4007 
4008     r = CLIP(r, 0, 255);
4009     g = CLIP(g, 0, 255);
4010     b = CLIP(b, 0, 255);
4011 
4012     /* look for pure gray match */
4013     if ((r == g) && (g == b)) {
4014         mindist = 256;
4015         for (i = 0 ; i < numColors ; i++, argb+=4) {
4016             red = argb[1];
4017             green = argb[2];
4018             blue = argb[3];
4019             if (! ((red == green) && (green == blue)) ) {
4020                 continue;
4021             }
4022             d = ABS(red - r);
4023             if (d == 0)
4024                 return i;
4025             if (d < mindist) {
4026                 besti = i;
4027                 mindist = d;
4028             }
4029         }
4030         return besti;
4031     }
4032 
4033     /* look for non-pure gray match */
4034     mindist = 256 * 256 * 256;
4035     for (i = 0 ; i < numColors ; i++, argb+=4) {
4036         red = argb[1];
4037         green = argb[2];
4038         blue = argb[3];
4039         t = red - r;
4040         d = t * t;
4041         if (d >= mindist) {
4042             continue;
4043         }
4044         t = green - g;
4045         d += t * t;
4046         if (d >= mindist) {
4047             continue;
4048         }
4049         t = blue - b;
4050         d += t * t;
4051         if (d >= mindist) {
4052             continue;
4053         }
4054         if (d == 0)
4055             return i;
4056         if (d < mindist) {
4057             besti = i;
4058             mindist = d;
4059         }
4060     }
4061 
4062     return besti;
4063 }
4064