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