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 */
77typedef enum {
78 MLIB_CONVMxN,
79 MLIB_AFFINE,
80 MLIB_LOOKUP,
81 MLIB_CONVKERNCVT
82} mlibTypeE_t;
83
84typedef 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
97static 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
103static 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
111static int s_timeIt = 0;
112static int s_printIt = 0;
113static int s_startOff = 0;
114static int s_nomlib = 0;
115
116/***************************************************************************
117 * Static Function Prototypes *
118 ***************************************************************************/
119
120static int
121allocateArray(JNIEnv *env, BufImageS_t *imageP,
122 mlib_image **mlibImagePP, void **dataPP, int isSrc,
123 int cvtToDefault, int addAlpha);
124static int
125allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
126 mlib_image **mlibImagePP, void **dataPP, int isSrc);
127
128static void
129freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,
130 void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,
131 void *dstdataP);
132static void
133freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,
134 void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,
135 void *dstdataP);
136
137static int
138storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
139 mlib_image *mlibImP);
140
141static int
142storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,
143 mlib_image *mlibImP);
144
145static int
146storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
147 mlib_image *mlibImP);
148
149static int
150colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors);
151
152static int
153setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
154 int expandICM, int useAlpha,
155 int premultiply, mlibHintS_t *hintP);
156
157
158static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP);
159static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
160 unsigned char *outDataP);
161static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
162 unsigned char *outDataP);
163static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
164 unsigned char *outDataP);
165static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
166 int component, unsigned char *outDataP,
167 int forceAlpha);
168static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
169 int component, unsigned char *outDataP,
170 int forceAlpha);
171static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
172 int component, unsigned char *outDataP,
173 int forceAlpha);
174static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
175 unsigned char *outDataP);
176static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
177 unsigned char *outDataP);
178static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
179 unsigned char *outDataP);
180static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
181 int component, unsigned char *outDataP,
182 int supportsAlpha);
183static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
184 int component, unsigned char *outDataP,
185 int supportsAlpha);
186static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
187 int component, unsigned char *outDataP,
188 int supportsAlpha);
189
190mlib_start_timer start_timer = NULL;
191mlib_stop_timer stop_timer = NULL;
192
193/***************************************************************************
194 * Debugging Definitions *
195 ***************************************************************************/
196#ifdef DEBUG
197
198static void
199printMedialibError(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
220static int
221getMlibEdgeHint(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 */
244static 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 ***************************************************************************/
277JNIEXPORT jint JNICALL
278Java_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
518JNIEXPORT jint JNICALL
519Java_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
765JNIEXPORT jint JNICALL
766Java_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
897fprintf(stderr,"Src----------------\n");
898fprintf(stderr,"Type : %d\n",src->type);
899fprintf(stderr,"Channels: %d\n",src->channels);
900fprintf(stderr,"Width : %d\n",src->width);
901fprintf(stderr,"Height : %d\n",src->height);
902fprintf(stderr,"Stride : %d\n",src->stride);
903fprintf(stderr,"Flags : %d\n",src->flags);
904
905fprintf(stderr,"Dst----------------\n");
906fprintf(stderr,"Type : %d\n",dst->type);
907fprintf(stderr,"Channels: %d\n",dst->channels);
908fprintf(stderr,"Width : %d\n",dst->width);
909fprintf(stderr,"Height : %d\n",dst->height);
910fprintf(stderr,"Stride : %d\n",dst->stride);
911fprintf(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
983JNIEXPORT jint JNICALL
984Java_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
1066 return 0;
1067 }
1068 }
1069
1070 if (s_printIt) {
1071 printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
1072 matrix[2], matrix[3], matrix[4], matrix[5]);
1073 }
1074
1075 mtx[0] = matrix[0];
1076 mtx[1] = matrix[2];
1077 mtx[2] = matrix[4];
1078 mtx[3] = matrix[1];
1079 mtx[4] = matrix[3];
1080 mtx[5] = matrix[5];
1081
1082 (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
1083
1084 /* Parse the source raster */
1085 if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {
1086 /* Can't handle any custom rasters */
1087 free(srcRasterP);
1088 free(dstRasterP);
1089 return 0;
1090 }
1091
1092 /* Parse the destination raster */
1093 if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {
1094 /* Can't handle any custom images */
1095 awt_freeParsedRaster(srcRasterP, TRUE);
1096 free(dstRasterP);
1097 return 0;
1098 }
1099
1100 /* Allocate the arrays */
1101 if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
1102 /* Must be some problem */
1103 awt_freeParsedRaster(srcRasterP, TRUE);
1104 awt_freeParsedRaster(dstRasterP, TRUE);
1105 return 0;
1106 }
1107 if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
1108 /* Must be some problem */
1109 freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
1110 awt_freeParsedRaster(srcRasterP, TRUE);
1111 awt_freeParsedRaster(dstRasterP, TRUE);
1112 return 0;
1113 }
1114
1115#if 0
1116fprintf(stderr,"Src----------------\n");
1117fprintf(stderr,"Type : %d\n",src->type);
1118fprintf(stderr,"Channels: %d\n",src->channels);
1119fprintf(stderr,"Width : %d\n",src->width);
1120fprintf(stderr,"Height : %d\n",src->height);
1121fprintf(stderr,"Stride : %d\n",src->stride);
1122fprintf(stderr,"Flags : %d\n",src->flags);
1123
1124fprintf(stderr,"Dst----------------\n");
1125fprintf(stderr,"Type : %d\n",dst->type);
1126fprintf(stderr,"Channels: %d\n",dst->channels);
1127fprintf(stderr,"Width : %d\n",dst->width);
1128fprintf(stderr,"Height : %d\n",dst->height);
1129fprintf(stderr,"Stride : %d\n",dst->stride);
1130fprintf(stderr,"Flags : %d\n",dst->flags);
1131#endif
1132
1133 {
1134 unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);
1135
1136 memset(cP, 0, mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));
1137 }
1138
1139 /* Perform the transformation */
1140 if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,
1141 MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))
1142 {
1143 printMedialibError(status);
1144 /* REMIND: Free the regions */
1145 return 0;
1146 }
1147
1148 if (s_printIt) {
1149 if (sdata == NULL) {
1150 dP = (unsigned int *) mlib_ImageGetData(src);
1151 }
1152 else {
1153 dP = (unsigned int *) sdata;
1154 }
1155 printf("src is\n");
1156 for (i=0; i < 20; i++) {
1157 printf("%x ",dP[i]);
1158 }
1159 printf("\n");
1160 if (ddata == NULL) {
1161 dP = (unsigned int *)mlib_ImageGetData(dst);
1162 }
1163 else {
1164 dP = (unsigned int *) ddata;
1165 }
1166 printf("dst is\n");
1167 for (i=0; i < 20; i++) {
1168 printf("%x ",dP[i]);
1169 }
1170 printf("\n");
1171 }
1172
1173 /* Means that we couldn't write directly into the destination buffer */
1174 if (ddata == NULL) {
1175 /* Need to store it back into the array */
1176 if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
1177 (*env)->ExceptionClear(env); // Could not store the array, try another way
1178 retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
1179 }
1180 }
1181
1182 /* Release the pinned memory */
1183 freeDataArray(env, srcRasterP->jdata, src, sdata,
1184 dstRasterP->jdata, dst, ddata);
1185
1186 awt_freeParsedRaster(srcRasterP, TRUE);
1187 awt_freeParsedRaster(dstRasterP, TRUE);
1188
1189 if (s_timeIt) (*stop_timer)(3600,1);
1190
1191 return retStatus;
1192}
1193
1194typedef struct {
1195 jobject jArray;
1196 jsize length;
1197 unsigned char *table;
1198} LookupArrayInfo;
1199
1200#define NLUT 8
1201
1202#ifdef _LITTLE_ENDIAN
1203#define INDEXES { 3, 2, 1, 0, 7, 6, 5, 4 }
1204#else
1205#define INDEXES { 0, 1, 2, 3, 4, 5, 6, 7 }
1206#endif
1207
1208static int lookupShortData(mlib_image* src, mlib_image* dst,
1209 LookupArrayInfo* lookup)
1210{
1211 int x, y;
1212 unsigned int mask = NLUT-1;
1213
1214 unsigned short* srcLine = (unsigned short*)src->data;
1215 unsigned char* dstLine = (unsigned char*)dst->data;
1216
1217 static int indexes[NLUT] = INDEXES;
1218
1219 if (src->width != dst->width || src->height != dst->height) {
1220 return 0;
1221 }
1222
1223 for (y=0; y < src->height; y++) {
1224 int nloop, nx;
1225 int npix = src->width;
1226
1227 unsigned short* srcPixel = srcLine;
1228 unsigned char* dstPixel = dstLine;
1229
1230#ifdef SIMPLE_LOOKUP_LOOP
1231 for (x=0; status && x < width; x++) {
1232 unsigned short s = *srcPixel++;
1233 if (s >= lookup->length) {
1234 /* we can not handle source image using
1235 * byte lookup table. Fall back to processing
1236 * images in java
1237 */
1238 return 0;
1239 }
1240 *dstPixel++ = lookup->table[s];
1241 }
1242#else
1243 /* Get to 32 bit-aligned point */
1244 while(((uintptr_t)dstPixel & 0x3) != 0 && npix>0) {
1245 unsigned short s = *srcPixel++;
1246 if (s >= lookup->length) {
1247 return 0;
1248 }
1249 *dstPixel++ = lookup->table[s];
1250 npix--;
1251 }
1252
1253 /*
1254 * Do NLUT pixels per loop iteration.
1255 * Pack into ints and write out 2 at a time.
1256 */
1257 nloop = npix/NLUT;
1258 nx = npix%NLUT;
1259
1260 for(x=nloop; x!=0; x--) {
1261 int i = 0;
1262 int* dstP = (int*)dstPixel;
1263
1264 for (i = 0; i < NLUT; i++) {
1265 if (srcPixel[i] >= lookup->length) {
1266 return 0;
1267 }
1268 }
1269
1270 dstP[0] = (int)
1271 ((lookup->table[srcPixel[indexes[0]]] << 24) |
1272 (lookup->table[srcPixel[indexes[1]]] << 16) |
1273 (lookup->table[srcPixel[indexes[2]]] << 8) |
1274 lookup->table[srcPixel[indexes[3]]]);
1275 dstP[1] = (int)
1276 ((lookup->table[srcPixel[indexes[4]]] << 24) |
1277 (lookup->table[srcPixel[indexes[5]]] << 16) |
1278 (lookup->table[srcPixel[indexes[6]]] << 8) |
1279 lookup->table[srcPixel[indexes[7]]]);
1280
1281
1282 dstPixel += NLUT;
1283 srcPixel += NLUT;
1284 }
1285
1286 /*
1287 * Complete any remaining pixels
1288 */
1289 for(x=nx; x!=0; x--) {
1290 unsigned short s = *srcPixel++;
1291 if (s >= lookup->length) {
1292 return 0;
1293 }
1294 *dstPixel++ = lookup->table[s];
1295 }
1296#endif
1297
1298 dstLine += dst->stride; // array of bytes, scan stride in bytes
1299 srcLine += src->stride / 2; // array of shorts, scan stride in bytes
1300 }
1301 return 1;
1302}
1303
1304JNIEXPORT jint JNICALL
1305Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject thisLib,
1306 jobject jsrc, jobject jdst,
1307 jobjectArray jtableArrays)
1308{
1309 mlib_image *src;
1310 mlib_image *dst;
1311 void *sdata, *ddata;
1312 unsigned char **tbl;
1313 unsigned char lut[256];
1314 int retStatus = 1;
1315 int i;
1316 mlib_status status;
1317 int lut_nbands;
1318 LookupArrayInfo *jtable;
1319 BufImageS_t *srcImageP, *dstImageP;
1320 int nbands;
1321 int ncomponents;
1322 mlibHintS_t hint;
1323
1324 /* This function requires a lot of local refs ??? Is 64 enough ??? */
1325 if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1326 return 0;
1327
1328 if (s_nomlib) return 0;
1329 if (s_timeIt) (*start_timer)(3600);
1330
1331 /* Parse the source image */
1332 if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {
1333 /* Can't handle any custom images */
1334 return 0;
1335 }
1336
1337 /* Parse the destination image */
1338 if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {
1339 /* Can't handle any custom images */
1340 awt_freeParsedImage(srcImageP, TRUE);
1341 return 0;
1342 }
1343
1344 nbands = setImageHints(env, srcImageP, dstImageP, FALSE, TRUE,
1345 FALSE, &hint);
1346
1347 if (nbands < 1 || nbands > srcImageP->cmodel.numComponents) {
1348 /* Can't handle any custom images */
1349 awt_freeParsedImage(srcImageP, TRUE);
1350 awt_freeParsedImage(dstImageP, TRUE);
1351 return 0;
1352 }
1353
1354 ncomponents = srcImageP->cmodel.isDefaultCompatCM
1355 ? 4
1356 : srcImageP->cmodel.numComponents;
1357
1358 /* Make sure that color order can be used for
1359 * re-ordering of lookup arrays.
1360 */
1361 for (i = 0; i < nbands; i++) {
1362 int idx = srcImageP->hints.colorOrder[i];
1363
1364 if (idx < 0 || idx >= ncomponents) {
1365 awt_freeParsedImage(srcImageP, TRUE);
1366 awt_freeParsedImage(dstImageP, TRUE);
1367 return 0;
1368 }
1369 }
1370
1371 lut_nbands = (*env)->GetArrayLength(env, jtableArrays);
1372
1373 if (lut_nbands > ncomponents) {
1374 lut_nbands = ncomponents;
1375 }
1376
1377 tbl = NULL;
1378 if (SAFE_TO_ALLOC_2(ncomponents, sizeof(unsigned char *))) {
1379 tbl = (unsigned char **)
1380 calloc(1, ncomponents * sizeof(unsigned char *));
1381 }
1382
1383 jtable = NULL;
1384 if (SAFE_TO_ALLOC_2(lut_nbands, sizeof(LookupArrayInfo))) {
1385 jtable = (LookupArrayInfo *)malloc(lut_nbands * sizeof (LookupArrayInfo));
1386 }
1387
1388 if (tbl == NULL || jtable == NULL) {
1389 if (tbl != NULL) free(tbl);
1390 if (jtable != NULL) free(jtable);
1391 awt_freeParsedImage(srcImageP, TRUE);
1392 awt_freeParsedImage(dstImageP, TRUE);
1393 JNU_ThrowNullPointerException(env, "NULL LUT");
1394 return 0;
1395 }
1396 /* Need to grab these pointers before we lock down arrays */
1397 for (i=0; i < lut_nbands; i++) {
1398 jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);
1399
1400 if (jtable[i].jArray != NULL) {
1401 jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);
1402 jtable[i].table = NULL;
1403
1404 if (jtable[i].length < 256) {
1405 /* we may read outside the table during lookup */
1406 jtable[i].jArray = NULL;
1407 jtable[i].length = 0;
1408 }
1409 }
1410 if (jtable[i].jArray == NULL) {
1411 free(tbl);
1412 free(jtable);
1413 awt_freeParsedImage(srcImageP, TRUE);
1414 awt_freeParsedImage(dstImageP, TRUE);
1415 return 0;
1416 }
1417 }
1418
1419 /* Allocate the arrays */
1420 if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) {
1421 /* Must be some problem */
1422 free(tbl);
1423 free(jtable);
1424 awt_freeParsedImage(srcImageP, TRUE);
1425 awt_freeParsedImage(dstImageP, TRUE);
1426 return 0;
1427 }
1428 if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) {
1429 /* Must be some problem */
1430 free(tbl);
1431 free(jtable);
1432 freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
1433 awt_freeParsedImage(srcImageP, TRUE);
1434 awt_freeParsedImage(dstImageP, TRUE);
1435 return 0;
1436 }
1437
1438 /* Set up a straight lut so we don't mess around with alpha */
1439 /*
1440 * NB: medialib lookup routine expects lookup array for each
1441 * component of source image including alpha.
1442 * If lookup table we got form the java layer does not contain
1443 * sufficient number of lookup arrays we add references to identity
1444 * lookup array to make medialib happier.
1445 */
1446 if (lut_nbands < ncomponents) {
1447 int j;
1448 /* REMIND: This should be the size of the input lut!! */
1449 for (j=0; j < 256; j++) {
1450 lut[j] = j;
1451 }
1452 for (j=0; j < ncomponents; j++) {
1453 tbl[j] = lut;
1454 }
1455 }
1456
1457 for (i=0; i < lut_nbands; i++) {
1458 jtable[i].table = (unsigned char *)
1459 (*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);
1460 if (jtable[i].table == NULL) {
1461 /* Free what we've got so far. */
1462 int j;
1463 for (j = 0; j < i; j++) {
1464 (*env)->ReleasePrimitiveArrayCritical(env,
1465 jtable[j].jArray,
1466 (jbyte *) jtable[j].table,
1467 JNI_ABORT);
1468 }
1469 free(tbl);
1470 free(jtable);
1471 freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
1472 awt_freeParsedImage(srcImageP, TRUE);
1473 awt_freeParsedImage(dstImageP, TRUE);
1474 return 0;
1475 }
1476 tbl[srcImageP->hints.colorOrder[i]] = jtable[i].table;
1477 }
1478
1479 if (lut_nbands == 1) {
1480 for (i=1; i < nbands -
1481 srcImageP->cmodel.supportsAlpha; i++) {
1482 tbl[srcImageP->hints.colorOrder[i]] = jtable[0].table;
1483 }
1484 }
1485
1486 /* Mlib needs 16bit lookuptable and must be signed! */
1487 if (src->type == MLIB_SHORT) {
1488 if (dst->type == MLIB_BYTE) {
1489 if (nbands > 1) {
1490 retStatus = 0;
1491 }
1492 else {
1493 retStatus = lookupShortData(src, dst, &jtable[0]);
1494 }
1495 }
1496 /* How about ddata == null? */
1497 }
1498 else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,
1499 (void **)tbl) != MLIB_SUCCESS)) {
1500 printMedialibError(status);
1501 retStatus = 0;
1502 }
1503
1504 /* Release the LUT */
1505 for (i=0; i < lut_nbands; i++) {
1506 (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
1507 (jbyte *) jtable[i].table, JNI_ABORT);
1508 }
1509 free ((void *) jtable);
1510 free ((void *) tbl);
1511
1512 /*
1513 * Means that we couldn't write directly into
1514 * the destination buffer
1515 */
1516 if (ddata == NULL) {
1517
1518 /* Need to store it back into the array */
1519 if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
1520 /* Error */
1521 retStatus = 0;
1522 }
1523 }
1524
1525
1526 /* Release the pinned memory */
1527 freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
1528
1529 awt_freeParsedImage(srcImageP, TRUE);
1530 awt_freeParsedImage(dstImageP, TRUE);
1531
1532 if (s_timeIt) (*stop_timer)(3600, 1);
1533
1534 return retStatus;
1535}
1536
1537JNIEXPORT jint JNICALL
1538Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env,
1539 jobject this,
1540 jobject jsrc,
1541 jobject jdst,
1542 jobjectArray jtableArrays)
1543{
1544 RasterS_t* srcRasterP;
1545 RasterS_t* dstRasterP;
1546 mlib_image* src;
1547 mlib_image* dst;
1548 void* sdata;
1549 void* ddata;
1550 LookupArrayInfo jtable[4];
1551 unsigned char* mlib_lookupTable[4];
1552 int i;
1553 int retStatus = 1;
1554 mlib_status status;
1555 int jlen;
1556 int lut_nbands;
1557 int src_nbands;
1558 int dst_nbands;
1559 unsigned char ilut[256];
1560
1561 /* This function requires a lot of local refs ??? Is 64 enough ??? */
1562 if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1563 return 0;
1564
1565 if (s_nomlib) return 0;
1566 if (s_timeIt) (*start_timer)(3600);
1567
1568 if ((srcRasterP = (RasterS_t*) calloc(1, sizeof(RasterS_t))) == NULL) {
1569 JNU_ThrowOutOfMemoryError(env, "Out of memory");
1570 return -1;
1571 }
1572
1573 if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
1574 JNU_ThrowOutOfMemoryError(env, "Out of memory");
1575 free(srcRasterP);
1576 return -1;
1577 }
1578
1579 /* Parse the source raster - reject custom images */
1580 if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {
1581 free(srcRasterP);
1582 free(dstRasterP);
1583 return 0;
1584 }
1585
1586 /* Parse the destination image - reject custom images */
1587 if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {
1588 awt_freeParsedRaster(srcRasterP, TRUE);
1589 free(dstRasterP);
1590 return 0;
1591 }
1592
1593 jlen = (*env)->GetArrayLength(env, jtableArrays);
1594
1595 lut_nbands = jlen;
1596 src_nbands = srcRasterP->numBands;
1597 dst_nbands = dstRasterP->numBands;
1598
1599 /* adjust number of lookup bands */
1600 if (lut_nbands > src_nbands) {
1601 lut_nbands = src_nbands;
1602 }
1603
1604 /* MediaLib can't do more than 4 bands */
1605 if (src_nbands <= 0 || src_nbands > 4 ||
1606 dst_nbands <= 0 || dst_nbands > 4 ||
1607 lut_nbands <= 0 || lut_nbands > 4 ||
1608 src_nbands != dst_nbands ||
1609 ((lut_nbands != 1) && (lut_nbands != src_nbands)))
1610 {
1611 // we should free parsed rasters here
1612 awt_freeParsedRaster(srcRasterP, TRUE);
1613 awt_freeParsedRaster(dstRasterP, TRUE);
1614 return 0;
1615 }
1616
1617 /* Allocate the raster arrays */
1618 if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
1619 /* Must be some problem */
1620 awt_freeParsedRaster(srcRasterP, TRUE);
1621 awt_freeParsedRaster(dstRasterP, TRUE);
1622 return 0;
1623 }
1624 if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
1625 /* Must be some problem */
1626 freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
1627 awt_freeParsedRaster(srcRasterP, TRUE);
1628 awt_freeParsedRaster(dstRasterP, TRUE);
1629 return 0;
1630 }
1631
1632 /*
1633 * Well, until now we have analyzed number of bands in
1634 * src and dst rasters.
1635 * However, it is not enough because medialib lookup routine uses
1636 * number of channels of medialib image. Note that in certain
1637 * case number of channels may differs form the number of bands.
1638 * Good example is raster that is used in TYPE_INT_RGB buffered
1639 * image: it has 3 bands, but their medialib representation has
1640 * 4 channels.
1641 *
1642 * In order to avoid the lookup routine failure, we need:
1643 *
1644 * 1. verify that src and dst have same number of channels.
1645 * 2. provide lookup array for every channel. If we have "extra"
1646 * channel (like the raster described above) then we need to
1647 * provide identical lookup array.
1648 */
1649 if (src->channels != dst->channels) {
1650 freeDataArray(env, srcRasterP->jdata, src, sdata,
1651 dstRasterP->jdata, dst, ddata);
1652
1653 awt_freeParsedRaster(srcRasterP, TRUE);
1654 awt_freeParsedRaster(dstRasterP, TRUE);
1655 return 0;
1656 }
1657
1658 if (src_nbands < src->channels) {
1659 for (i = 0; i < 256; i++) {
1660 ilut[i] = i;
1661 }
1662 }
1663
1664
1665 /* Get references to the lookup table arrays */
1666 /* Need to grab these pointers before we lock down arrays */
1667 for (i=0; i < lut_nbands; i++) {
1668 jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);
1669 jtable[i].table = NULL;
1670 if (jtable[i].jArray != NULL) {
1671 jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);
1672 if (jtable[i].length < 256) {
1673 /* we may read outside the table during lookup */
1674 jtable[i].jArray = NULL;
1675 }
1676 }
1677
1678 if (jtable[i].jArray == NULL)
1679 {
1680 freeDataArray(env, srcRasterP->jdata, src, sdata,
1681 dstRasterP->jdata, dst, ddata);
1682
1683 awt_freeParsedRaster(srcRasterP, TRUE);
1684 awt_freeParsedRaster(dstRasterP, TRUE);
1685 return 0;
1686 }
1687 }
1688
1689 for (i=0; i < lut_nbands; i++) {
1690 jtable[i].table = (unsigned char *)
1691 (*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);
1692 if (jtable[i].table == NULL) {
1693 /* Free what we've got so far. */
1694 int j;
1695 for (j = 0; j < i; j++) {
1696 (*env)->ReleasePrimitiveArrayCritical(env,
1697 jtable[j].jArray,
1698 (jbyte *) jtable[j].table,
1699 JNI_ABORT);
1700 }
1701 freeDataArray(env, srcRasterP->jdata, src, sdata,
1702 dstRasterP->jdata, dst, ddata);
1703 awt_freeParsedRaster(srcRasterP, TRUE);
1704 awt_freeParsedRaster(dstRasterP, TRUE);
1705 return 0;
1706 }
1707 mlib_lookupTable[i] = jtable[i].table;
1708 }
1709
1710 /*
1711 * Medialib routine expects lookup array for each band of raster.
1712 * Setup the rest of lookup arrays if supplied lookup table
1713 * contains single lookup array.
1714 */
1715 for (i = lut_nbands; i < src_nbands; i++) {
1716 mlib_lookupTable[i] = jtable[0].table;
1717 }
1718
1719 /*
1720 * Setup lookup array for "extra" channels
1721 */
1722 for ( ; i < src->channels; i++) {
1723 mlib_lookupTable[i] = ilut;
1724 }
1725
1726 /* Mlib needs 16bit lookuptable and must be signed! */
1727 if (src->type == MLIB_SHORT) {
1728 if (dst->type == MLIB_BYTE) {
1729 if (lut_nbands > 1) {
1730 retStatus = 0;
1731 } else {
1732 retStatus = lookupShortData(src, dst, &jtable[0]);
1733 }
1734 }
1735 /* How about ddata == null? */
1736 } else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,
1737 (void **)mlib_lookupTable) != MLIB_SUCCESS)) {
1738 printMedialibError(status);
1739 retStatus = 0;
1740 }
1741
1742 /* Release the LUT */
1743 for (i=0; i < lut_nbands; i++) {
1744 (*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,
1745 (jbyte *) jtable[i].table, JNI_ABORT);
1746 }
1747
1748 /*
1749 * Means that we couldn't write directly into
1750 * the destination buffer
1751 */
1752 if (ddata == NULL) {
1753 if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
1754 retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);
1755 }
1756 }
1757
1758 /* Release the pinned memory */
1759 freeDataArray(env, srcRasterP->jdata, src, sdata,
1760 dstRasterP->jdata, dst, ddata);
1761
1762 awt_freeParsedRaster(srcRasterP, TRUE);
1763 awt_freeParsedRaster(dstRasterP, TRUE);
1764
1765 if (s_timeIt) (*stop_timer)(3600, 1);
1766
1767 return retStatus;
1768}
1769
1770
1771JNIEXPORT jboolean JNICALL
1772Java_sun_awt_image_ImagingLib_init(JNIEnv *env, jclass thisClass) {
1773 char *start;
1774 if (getenv("IMLIB_DEBUG")) {
1775 start_timer = awt_setMlibStartTimer();
1776 stop_timer = awt_setMlibStopTimer();
1777 if (start_timer && stop_timer) {
1778 s_timeIt = 1;
1779 }
1780 }
1781
1782 if (getenv("IMLIB_PRINT")) {
1783 s_printIt = 1;
1784 }
1785 if ((start = getenv("IMLIB_START")) != NULL) {
1786 sscanf(start, "%d", &s_startOff);
1787 }
1788
1789 if (getenv ("IMLIB_NOMLIB")) {
1790 s_nomlib = 1;
1791 return JNI_FALSE;
1792 }
1793
1794 /* This function is platform-dependent and is in awt_mlib.c */
1795 if (awt_getImagingLib(env, (mlibFnS_t *)&sMlibFns, &sMlibSysFns) !=
1796 MLIB_SUCCESS)
1797 {
1798 s_nomlib = 1;
1799 return JNI_FALSE;
1800 }
1801 return JNI_TRUE;
1802}
1803
1804/* REMIND: How to specify border? */
1805static void extendEdge(JNIEnv *env, BufImageS_t *imageP,
1806 int *widthP, int *heightP) {
1807 RasterS_t *rasterP = &imageP->raster;
1808 int width;
1809 int height;
1810 /* Useful for convolution? */
1811
1812 jobject jbaseraster = (*env)->GetObjectField(env, rasterP->jraster,
1813 g_RasterBaseRasterID);
1814 width = rasterP->width;
1815 height = rasterP->height;
1816#ifdef WORKING
1817 if (! JNU_IsNull(env, jbaseraster) &&
1818 !(*env)->IsSameObject(env, rasterP->jraster, jbaseraster)) {
1819 int xOff;
1820 int yOff;
1821 int baseWidth;
1822 int baseHeight;
1823 int baseXoff;
1824 int baseYoff;
1825 /* Not the same object so get the width and height */
1826 xOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterXOffsetID);
1827 yOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterYOffsetID);
1828 baseWidth = (*env)->GetIntField(env, jbaseraster, g_RasterWidthID);
1829 baseHeight = (*env)->GetIntField(env, jbaseraster, g_RasterHeightID);
1830 baseXoff = (*env)->GetIntField(env, jbaseraster, g_RasterXOffsetID);
1831 baseYoff = (*env)->GetIntField(env, jbaseraster, g_RasterYOffsetID);
1832
1833 if (xOff + rasterP->width < baseXoff + baseWidth) {
1834 /* Can use edge */
1835 width++;
1836 }
1837 if (yOff + rasterP->height < baseYoff + baseHeight) {
1838 /* Can use edge */
1839 height++;
1840 }
1841
1842 }
1843#endif
1844
1845}
1846
1847static int
1848setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
1849 int expandICM, int useAlpha,
1850 int premultiply, mlibHintS_t *hintP)
1851{
1852 ColorModelS_t *srcCMP = &srcP->cmodel;
1853 ColorModelS_t *dstCMP = &dstP->cmodel;
1854 int nbands = 0;
1855 int ncomponents;
1856
1857 hintP->dataType = srcP->raster.dataType;
1858 hintP->addAlpha = FALSE;
1859
1860 /* Are the color spaces the same? */
1861 if (srcCMP->csType != dstCMP->csType) {
1862 /* If the src is GRAY and dst RGB, we can handle it */
1863 if (!(srcCMP->csType == java_awt_color_ColorSpace_TYPE_GRAY &&
1864 dstCMP->csType == java_awt_color_ColorSpace_TYPE_RGB)) {
1865 /* Nope, need to handle that in java for now */
1866 return -1;
1867 }
1868 else {
1869 hintP->cvtSrcToDefault = TRUE;
1870 }
1871 }
1872 else {
1873 if (srcP->hints.needToExpand) {
1874 hintP->cvtSrcToDefault = TRUE;
1875 }
1876 else {
1877 /* Need to initialize this */
1878 hintP->cvtSrcToDefault = FALSE;
1879 }
1880 }
1881
1882 ncomponents = srcCMP->numComponents;
1883 if ((useAlpha == 0) && srcCMP->supportsAlpha) {
1884 ncomponents--; /* ?? */
1885 /* Not really, more like shrink src to get rid of alpha */
1886 hintP->cvtSrcToDefault = TRUE;
1887 }
1888
1889 hintP->dataType = srcP->raster.dataType;
1890 if (hintP->cvtSrcToDefault == FALSE) {
1891 if (srcCMP->cmType == INDEX_CM_TYPE) {
1892 if (expandICM) {
1893 nbands = srcCMP->numComponents;
1894 hintP->cvtSrcToDefault = TRUE;
1895
1896 if (dstCMP->isDefaultCompatCM) {
1897 hintP->allocDefaultDst = FALSE;
1898 hintP->cvtToDst = FALSE;
1899 }
1900 else if (dstCMP->isDefaultCompatCM) {
1901 hintP->allocDefaultDst = FALSE;
1902 hintP->cvtToDst = FALSE;
1903 }
1904 }
1905 else {
1906 nbands = 1;
1907 hintP->cvtSrcToDefault = FALSE;
1908 }
1909
1910 }
1911 else {
1912 if (srcP->hints.packing & INTERLEAVED) {
1913 nbands = srcCMP->numComponents;
1914 }
1915 else {
1916 nbands = 1;
1917 }
1918
1919 /* Look at the packing */
1920 if ((srcP->hints.packing&BYTE_INTERLEAVED)==BYTE_INTERLEAVED ||
1921 (srcP->hints.packing&SHORT_INTERLEAVED)==SHORT_INTERLEAVED||
1922 (srcP->hints.packing&BYTE_SINGLE_BAND) == BYTE_SINGLE_BAND||
1923 (srcP->hints.packing&SHORT_SINGLE_BAND)==SHORT_SINGLE_BAND||
1924 (srcP->hints.packing&BYTE_BANDED) == BYTE_BANDED ||
1925 (srcP->hints.packing&SHORT_BANDED) == SHORT_BANDED) {
1926 /* Can use src directly */
1927 hintP->cvtSrcToDefault = FALSE;
1928 }
1929 else {
1930 /* Must be packed or custom */
1931 hintP->cvtSrcToDefault = TRUE;
1932 }
1933 }
1934 }
1935 if (hintP->cvtSrcToDefault) {
1936 /* By definition */
1937 nbands = 4; /* What about alpha? */
1938 hintP->dataType = BYTE_DATA_TYPE;
1939 hintP->needToCopy = TRUE;
1940
1941 if (srcP->imageType == dstP->imageType) {
1942 hintP->cvtToDst = TRUE;
1943 }
1944 else if (dstP->cmodel.isDefaultCM) {
1945 /* Not necessarily */
1946 hintP->cvtToDst = FALSE;
1947 }
1948 else {
1949 hintP->cvtToDst = TRUE;
1950 }
1951 }
1952 else {
1953 int srcImageType = srcP->imageType;
1954 int dstImageType = dstP->imageType;
1955 /* Special case where we need to fill in alpha values */
1956 if (srcCMP->isDefaultCompatCM && dstCMP->isDefaultCompatCM) {
1957 int i;
1958 if (!srcCMP->supportsAlpha &&dstCMP->supportsAlpha) {
1959 hintP->addAlpha = TRUE;
1960 }
1961 for (i=0; i < srcCMP->numComponents; i++) {
1962 if (srcP->hints.colorOrder[i] != dstP->hints.colorOrder[i]){
1963 if (!srcCMP->isDefaultCM) {
1964 hintP->cvtSrcToDefault = TRUE;
1965 srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1966 }
1967 if (!dstCMP->isDefaultCM) {
1968 hintP->cvtToDst = TRUE;
1969 dstImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1970 }
1971
1972 break;
1973 }
1974 }
1975 }
1976 else if (srcCMP->cmType != INDEX_CM_TYPE &&
1977 !srcCMP->supportsAlpha && dstCMP->supportsAlpha)
1978 {
1979 /* We've already handled the index case. This is for the rest of the cases */
1980 srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1981 hintP->cvtSrcToDefault = TRUE;
1982 }
1983
1984 hintP->allocDefaultDst = FALSE;
1985 if (srcImageType == dstImageType) {
1986 /* Same image type so use it */
1987 hintP->cvtToDst = FALSE;
1988 }
1989 else if (srcImageType == TYPE_INT_RGB &&
1990 (dstImageType == TYPE_INT_ARGB ||
1991 dstImageType == TYPE_INT_ARGB_PRE)) {
1992 hintP->cvtToDst = FALSE;
1993 }
1994 else if (srcImageType == TYPE_INT_BGR &&
1995 (dstImageType == TYPE_4BYTE_ABGR ||
1996 dstImageType == TYPE_4BYTE_ABGR_PRE)) {
1997 hintP->cvtToDst = FALSE;
1998 }
1999 else if (srcP->hints.packing == dstP->hints.packing) {
2000 /* Now what? */
2001
2002 /* Check color order */
2003
2004 /* Check if just need to scale the data */
2005
2006 hintP->cvtToDst = TRUE;
2007 }
2008 else {
2009 /* Don't know what it is so convert it */
2010 hintP->allocDefaultDst = TRUE;
2011 hintP->cvtToDst = TRUE;
2012 }
2013 hintP->needToCopy = (ncomponents > nbands);
2014 }
2015
2016 return nbands;
2017}
2018
2019
2020static int
2021expandPacked(JNIEnv *env, BufImageS_t *img, ColorModelS_t *cmP,
2022 RasterS_t *rasterP, int component, unsigned char *bdataP) {
2023
2024 if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {
2025 switch (rasterP->dataType) {
2026 case BYTE_DATA_TYPE:
2027 if (expandPackedBCR(env, rasterP, component, bdataP) < 0) {
2028 /* Must have been an error */
2029 return -1;
2030 }
2031 break;
2032
2033 case SHORT_DATA_TYPE:
2034 if (expandPackedICR(env, rasterP, component, bdataP) < 0) {
2035 /* Must have been an error */
2036 return -1;
2037 }
2038 break;
2039
2040 case INT_DATA_TYPE:
2041 if (expandPackedICR(env, rasterP, component, bdataP) < 0) {
2042 /* Must have been an error */
2043 return -1;
2044 }
2045 break;
2046
2047 default:
2048 /* REMIND: Return some sort of error */
2049 return -1;
2050 }
2051 }
2052 else {
2053 /* REMIND: Return some sort of error */
2054 return -1;
2055 }
2056
2057 return 0;
2058}
2059
2060#define NUM_LINES 10
2061
2062static int
2063cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,
2064 unsigned char *dataP) {
2065 const RasterS_t *rasterP = &imageP->raster;
2066 const int w = rasterP->width;
2067 const int h = rasterP->height;
2068
2069 int y;
2070 jintArray jpixels = NULL;
2071 jint *pixels;
2072 unsigned char *dP = dataP;
2073 int numLines = h > NUM_LINES ? NUM_LINES : h;
2074
2075 /* it is safe to calculate the scan length, because width has been verified
2076 * on creation of the mlib image
2077 */
2078 const int scanLength = w * 4;
2079
2080 int nbytes = 0;
2081 if (!SAFE_TO_MULT(numLines, scanLength)) {
2082 return -1;
2083 }
2084
2085 nbytes = numLines * scanLength;
2086
2087 jpixels = (*env)->NewIntArray(env, nbytes);
2088 if (JNU_IsNull(env, jpixels)) {
2089 (*env)->ExceptionClear(env);
2090 JNU_ThrowOutOfMemoryError(env, "Out of Memory");
2091 return -1;
2092 }
2093
2094 for (y = 0; y < h; y += numLines) {
2095 if (y + numLines > h) {
2096 numLines = h - y;
2097 nbytes = numLines * scanLength;
2098 }
2099
2100 (*env)->CallObjectMethod(env, imageP->jimage,
2101 g_BImgGetRGBMID, 0, y,
2102 w, numLines,
2103 jpixels, 0, w);
2104 if ((*env)->ExceptionOccurred(env)) {
2105 (*env)->DeleteLocalRef(env, jpixels);
2106 return -1;
2107 }
2108
2109 pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);
2110 if (pixels == NULL) {
2111 (*env)->DeleteLocalRef(env, jpixels);
2112 return -1;
2113 }
2114
2115 memcpy(dP, pixels, nbytes);
2116 dP += nbytes;
2117
2118 (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels,
2119 JNI_ABORT);
2120 }
2121
2122 /* Need to release the array */
2123 (*env)->DeleteLocalRef(env, jpixels);
2124
2125 return 0;
2126}
2127
2128static int
2129cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component,
2130 unsigned char *dataP) {
2131 const RasterS_t *rasterP = &imageP->raster;
2132 const int w = rasterP->width;
2133 const int h = rasterP->height;
2134
2135 int y;
2136 jintArray jpixels = NULL;
2137 jint *pixels;
2138 unsigned char *dP = dataP;
2139 int numLines = h > NUM_LINES ? NUM_LINES : h;
2140
2141 /* it is safe to calculate the scan length, because width has been verified
2142 * on creation of the mlib image
2143 */
2144 const int scanLength = w * 4;
2145
2146 int nbytes = 0;
2147 if (!SAFE_TO_MULT(numLines, scanLength)) {
2148 return -1;
2149 }
2150
2151 nbytes = numLines * scanLength;
2152
2153 jpixels = (*env)->NewIntArray(env, nbytes);
2154 if (JNU_IsNull(env, jpixels)) {
2155 (*env)->ExceptionClear(env);
2156 JNU_ThrowOutOfMemoryError(env, "Out of Memory");
2157 return -1;
2158 }
2159
2160 for (y = 0; y < h; y += numLines) {
2161 if (y + numLines > h) {
2162 numLines = h - y;
2163 nbytes = numLines * scanLength;
2164 }
2165
2166 pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);
2167 if (pixels == NULL) {
2168 (*env)->DeleteLocalRef(env, jpixels);
2169 return -1;
2170 }
2171
2172 memcpy(pixels, dP, nbytes);
2173 dP += nbytes;
2174
2175 (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, 0);
2176
2177 (*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y,
2178 w, numLines, jpixels,
2179 0, w);
2180 if ((*env)->ExceptionOccurred(env)) {
2181 (*env)->DeleteLocalRef(env, jpixels);
2182 return -1;
2183 }
2184 }
2185
2186 /* Need to release the array */
2187 (*env)->DeleteLocalRef(env, jpixels);
2188
2189 return 0;
2190}
2191
2192static int
2193allocateArray(JNIEnv *env, BufImageS_t *imageP,
2194 mlib_image **mlibImagePP, void **dataPP, int isSrc,
2195 int cvtToDefault, int addAlpha) {
2196 void *dataP;
2197 unsigned char *cDataP;
2198 RasterS_t *rasterP = &imageP->raster;
2199 ColorModelS_t *cmP = &imageP->cmodel;
2200 int dataType = BYTE_DATA_TYPE;
2201 int width;
2202 int height;
2203 HintS_t *hintP = &imageP->hints;
2204 *dataPP = NULL;
2205
2206 width = rasterP->width;
2207 height = rasterP->height;
2208
2209 /* Useful for convolution? */
2210 /* This code is zero'ed out so that it cannot be called */
2211
2212 /* To do this correctly, we need to expand src and dst in the */
2213 /* same direction up/down/left/right only if both can be expanded */
2214 /* in that direction. Expanding right and down is easy - */
2215 /* increment width. Expanding top and left requires bumping */
2216 /* around pointers and incrementing the width/height */
2217
2218#if 0
2219 if (0 && useEdges) {
2220 baseWidth = rasterP->baseRasterWidth;
2221 baseHeight = rasterP->baseRasterHeight;
2222 baseXoff = rasterP->baseOriginX;
2223 baseYoff = rasterP->baseOriginY;
2224
2225 if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {
2226 /* Can use edge */
2227 width++;
2228 }
2229 if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {
2230 /* Can use edge */
2231 height++;
2232 }
2233
2234 if (rasterP->minX > baseXoff ) {
2235 /* Can use edge */
2236 width++;
2237 /* NEED TO BUMP POINTER BACK A PIXELSTRIDE */
2238 }
2239 if (rasterP->minY > baseYoff) {
2240 /* Can use edge */
2241 height++;
2242 /* NEED TO BUMP POINTER BACK A SCANLINE */
2243 }
2244
2245
2246 }
2247#endif
2248 if (cvtToDefault) {
2249 int status = 0;
2250 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
2251 if (*mlibImagePP == NULL) {
2252 return -1;
2253 }
2254 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2255 /* Make sure the image is cleared.
2256 * NB: the image dimension is already verified, so we can
2257 * safely calculate the length of the buffer.
2258 */
2259 memset(cDataP, 0, width*height*4);
2260
2261 if (!isSrc) {
2262 return 0;
2263 }
2264
2265 switch(imageP->cmodel.cmType) {
2266 case INDEX_CM_TYPE:
2267 /* REMIND: Need to rearrange according to dst cm */
2268 /* Fix 4213160, 4184283 */
2269 if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {
2270 return expandICM(env, imageP, (unsigned int *)cDataP);
2271 }
2272 else {
2273 return cvtCustomToDefault(env, imageP, -1, cDataP);
2274 }
2275
2276 case DIRECT_CM_TYPE:
2277 switch(imageP->raster.dataType) {
2278 case BYTE_DATA_TYPE:
2279 return expandPackedBCRdefault(env, rasterP, -1, cDataP,
2280 !imageP->cmodel.supportsAlpha);
2281 case SHORT_DATA_TYPE:
2282 return expandPackedSCRdefault(env, rasterP, -1, cDataP,
2283 !imageP->cmodel.supportsAlpha);
2284 case INT_DATA_TYPE:
2285 return expandPackedICRdefault(env, rasterP, -1, cDataP,
2286 !imageP->cmodel.supportsAlpha);
2287 }
2288 } /* switch(imageP->cmodel.cmType) */
2289
2290 return cvtCustomToDefault(env, imageP, -1, cDataP);
2291 }
2292
2293 /* Interleaved with shared data */
2294 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2295 NULL);
2296 if (dataP == NULL) {
2297 return -1;
2298 }
2299
2300 /* Means we need to fill in alpha */
2301 if (!cvtToDefault && addAlpha) {
2302 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
2303 if (*mlibImagePP != NULL) {
2304 unsigned int *dstP = (unsigned int *)
2305 mlib_ImageGetData(*mlibImagePP);
2306 int dstride = (*mlibImagePP)->stride>>2;
2307 int sstride = hintP->sStride>>2;
2308 unsigned int *srcP = (unsigned int *)
2309 ((unsigned char *)dataP + hintP->dataOffset);
2310 unsigned int *dP, *sP;
2311 int x, y;
2312 for (y=0; y < height; y++, srcP += sstride, dstP += dstride){
2313 sP = srcP;
2314 dP = dstP;
2315 for (x=0; x < width; x++) {
2316 dP[x] = sP[x] | 0xff000000;
2317 }
2318 }
2319 }
2320 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2321 JNI_ABORT);
2322 return 0;
2323 }
2324 else if ((hintP->packing & BYTE_INTERLEAVED) == BYTE_INTERLEAVED) {
2325 int nChans = (cmP->isDefaultCompatCM ? 4 : hintP->numChans);
2326 /* Easy case. It is or is similar to the default CM so use
2327 * the array. Must be byte data.
2328 */
2329 /* Create the medialib image */
2330 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE,
2331 nChans,
2332 width,
2333 height,
2334 hintP->sStride,
2335 (unsigned char *)dataP
2336 + hintP->dataOffset);
2337 }
2338 else if ((hintP->packing & SHORT_INTERLEAVED) == SHORT_INTERLEAVED) {
2339 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
2340 hintP->numChans,
2341 width,
2342 height,
2343 imageP->raster.scanlineStride*2,
2344 (unsigned short *)dataP
2345 + hintP->channelOffset);
2346 }
2347 else {
2348 /* Release the data array */
2349 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2350 JNI_ABORT);
2351 return -1;
2352 }
2353
2354 *dataPP = dataP;
2355 return 0;
2356}
2357
2358static int
2359allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
2360 mlib_image **mlibImagePP, void **dataPP, int isSrc) {
2361 void *dataP;
2362 unsigned char *cDataP;
2363 int dataType = BYTE_DATA_TYPE;
2364 int width;
2365 int height;
2366 int dataSize;
2367 int offset;
2368
2369 *dataPP = NULL;
2370
2371 width = rasterP->width;
2372 height = rasterP->height;
2373
2374 if (rasterP->numBands <= 0 || rasterP->numBands > 4) {
2375 /* REMIND: Fix this */
2376 return -1;
2377 }
2378
2379 /* Useful for convolution? */
2380 /* This code is zero'ed out so that it cannot be called */
2381
2382 /* To do this correctly, we need to expand src and dst in the */
2383 /* same direction up/down/left/right only if both can be expanded */
2384 /* in that direction. Expanding right and down is easy - */
2385 /* increment width. Expanding top and left requires bumping */
2386 /* around pointers and incrementing the width/height */
2387
2388#if 0
2389 if (0 && useEdges) {
2390 baseWidth = rasterP->baseRasterWidth;
2391 baseHeight = rasterP->baseRasterHeight;
2392 baseXoff = rasterP->baseOriginX;
2393 baseYoff = rasterP->baseOriginY;
2394
2395 if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {
2396 /* Can use edge */
2397 width++;
2398 }
2399 if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {
2400 /* Can use edge */
2401 height++;
2402 }
2403
2404 if (rasterP->minX > baseXoff ) {
2405 /* Can use edge */
2406 width++;
2407 /* NEED TO BUMP POINTER BACK A PIXELSTRIDE */
2408 }
2409 if (rasterP->minY > baseYoff) {
2410 /* Can use edge */
2411 height++;
2412 /* NEED TO BUMP POINTER BACK A SCANLINE */
2413 }
2414
2415
2416 }
2417#endif
2418 switch (rasterP->type) {
2419 case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:
2420 if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&
2421 SAFE_TO_ALLOC_2(width, 4) &&
2422 SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4)))
2423 {
2424 return -1;
2425 }
2426 offset = 4 * rasterP->chanOffsets[0];
2427 dataSize = 4 * (*env)->GetArrayLength(env, rasterP->jdata);
2428
2429 if (offset < 0 || offset >= dataSize ||
2430 width > rasterP->scanlineStride ||
2431 ((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset)
2432 {
2433 // raster data buffer is too short
2434 return -1;
2435 }
2436 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2437 NULL);
2438 if (dataP == NULL) {
2439 return -1;
2440 }
2441 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, 4,
2442 width, height,
2443 rasterP->scanlineStride*4,
2444 (unsigned char *)dataP + offset);
2445 *dataPP = dataP;
2446 return 0;
2447 case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:
2448 if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&
2449 SAFE_TO_ALLOC_2(rasterP->scanlineStride, height)))
2450 {
2451 return -1;
2452 }
2453 offset = rasterP->chanOffsets[0];
2454 dataSize = (*env)->GetArrayLength(env, rasterP->jdata);
2455
2456 if (offset < 0 || offset >= dataSize ||
2457 width * rasterP->numBands > rasterP->scanlineStride ||
2458 ((width * rasterP->numBands) +
2459 (height - 1) * rasterP->scanlineStride) > dataSize - offset)
2460 {
2461 // raster data buffer is too short
2462 return -1;
2463 }
2464 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2465 NULL);
2466 if (dataP == NULL) {
2467 return -1;
2468 }
2469 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, rasterP->numBands,
2470 width, height,
2471 rasterP->scanlineStride,
2472 (unsigned char *)dataP + offset);
2473 *dataPP = dataP;
2474 return 0;
2475 case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:
2476 if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&
2477 SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&
2478 SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 2)))
2479 {
2480 return -1;
2481 }
2482 offset = rasterP->chanOffsets[0] * 2;
2483 dataSize = 2 * (*env)->GetArrayLength(env, rasterP->jdata);
2484
2485 if (offset < 0 || offset >= dataSize ||
2486 width * rasterP->numBands > rasterP->scanlineStride ||
2487 (((width * rasterP->numBands) +
2488 (height - 1) * rasterP->scanlineStride)) * 2 > dataSize - offset)
2489 {
2490 // raster data buffer is too short
2491 return -1;
2492 }
2493 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2494 NULL);
2495 if (dataP == NULL) {
2496 return -1;
2497 }
2498 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
2499 rasterP->numBands,
2500 width, height,
2501 rasterP->scanlineStride*2,
2502 (unsigned char *)dataP + offset);
2503 *dataPP = dataP;
2504 return 0;
2505
2506 case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
2507 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2508 width, height);
2509 if (*mlibImagePP == NULL) {
2510 return -1;
2511 }
2512 if (!isSrc) return 0;
2513 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2514 return expandPackedBCR(env, rasterP, -1, cDataP);
2515
2516 case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:
2517 if (rasterP->sppsm.maxBitSize <= 8) {
2518 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2519 width, height);
2520 if (*mlibImagePP == NULL) {
2521 return -1;
2522 }
2523 if (!isSrc) return 0;
2524 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2525 return expandPackedSCR(env, rasterP, -1, cDataP);
2526 }
2527 break;
2528 case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:
2529 if (rasterP->sppsm.maxBitSize <= 8) {
2530 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2531 width, height);
2532 if (*mlibImagePP == NULL) {
2533 return -1;
2534 }
2535 if (!isSrc) return 0;
2536 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2537 return expandPackedICR(env, rasterP, -1, cDataP);
2538 }
2539 break;
2540 }
2541
2542 /* Just expand it right now */
2543 switch (rasterP->dataType) {
2544 case BYTE_DATA_TYPE:
2545 if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2546 width, height)) == NULL) {
2547 return -1;
2548 }
2549 if (isSrc) {
2550 if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {
2551 (*sMlibSysFns.deleteImageFP)(*mlibImagePP);
2552 return -1;
2553 }
2554 }
2555 break;
2556
2557 case SHORT_DATA_TYPE:
2558 if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_SHORT,
2559 rasterP->numBands,
2560 width, height)) == NULL) {
2561 return -1;
2562 }
2563 if (isSrc) {
2564 if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {
2565 (*sMlibSysFns.deleteImageFP)(*mlibImagePP);
2566 return -1;
2567 }
2568 }
2569 break;
2570
2571 default:
2572 return -1;
2573 }
2574 return 0;
2575}
2576
2577static void
2578freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,
2579 void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,
2580 void *dstdataP) {
2581 jobject srcJdata = (srcimageP != NULL ? srcimageP->raster.jdata : NULL);
2582 jobject dstJdata = (dstimageP != NULL ? dstimageP->raster.jdata : NULL);
2583 freeDataArray(env, srcJdata, srcmlibImP, srcdataP,
2584 dstJdata, dstmlibImP, dstdataP);
2585}
2586static void
2587freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,
2588 void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,
2589 void *dstdataP)
2590{
2591 /* Free the medialib image */
2592 if (srcmlibImP) {
2593 (*sMlibSysFns.deleteImageFP)(srcmlibImP);
2594 }
2595
2596 /* Release the array */
2597 if (srcdataP) {
2598 (*env)->ReleasePrimitiveArrayCritical(env, srcJdata,
2599 srcdataP, JNI_ABORT);
2600 }
2601
2602 /* Free the medialib image */
2603 if (dstmlibImP) {
2604 (*sMlibSysFns.deleteImageFP)(dstmlibImP);
2605 }
2606
2607 /* Release the array */
2608 if (dstdataP) {
2609 (*env)->ReleasePrimitiveArrayCritical(env, dstJdata,
2610 dstdataP, 0);
2611 }
2612}
2613
2614#define ERR_BAD_IMAGE_LAYOUT (-2)
2615
2616#define CHECK_DST_ARRAY(start_offset, elements_per_scan, elements_per_pixel) \
2617 do { \
2618 int offset = (start_offset); \
2619 int lastScanOffset; \
2620 \
2621 if (!SAFE_TO_MULT((elements_per_scan), \
2622 (rasterP->height - 1))) \
2623 { \
2624 return ERR_BAD_IMAGE_LAYOUT; \
2625 } \
2626 lastScanOffset = (elements_per_scan) * (rasterP->height - 1); \
2627 \
2628 if (!SAFE_TO_ADD(offset, lastScanOffset)) { \
2629 return ERR_BAD_IMAGE_LAYOUT; \
2630 } \
2631 lastScanOffset += offset; \
2632 \
2633 if (!SAFE_TO_MULT((elements_per_pixel), rasterP->width)) { \
2634 return ERR_BAD_IMAGE_LAYOUT; \
2635 } \
2636 offset = (elements_per_pixel) * rasterP->width; \
2637 \
2638 if (!SAFE_TO_ADD(offset, lastScanOffset)) { \
2639 return ERR_BAD_IMAGE_LAYOUT; \
2640 } \
2641 lastScanOffset += offset; \
2642 \
2643 if (dataArrayLength < lastScanOffset) { \
2644 return ERR_BAD_IMAGE_LAYOUT; \
2645 } \
2646 } while(0); \
2647
2648static int
2649storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
2650 mlib_image *mlibImP) {
2651 int mStride;
2652 unsigned char *cmDataP, *dataP, *cDataP;
2653 HintS_t *hintP = &dstP->hints;
2654 RasterS_t *rasterP = &dstP->raster;
2655 jsize dataArrayLength = (*env)->GetArrayLength(env, rasterP->jdata);
2656 int y;
2657
2658 /* REMIND: Store mlib data type? */
2659
2660 /* Check if it is an IndexColorModel */
2661 if (dstP->cmodel.cmType == INDEX_CM_TYPE) {
2662 if (dstP->raster.rasterType == COMPONENT_RASTER_TYPE) {
2663 return storeICMarray(env, srcP, dstP, mlibImP);
2664 }
2665 else {
2666 /* Packed or some other custom raster */
2667 cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2668 return cvtDefaultToCustom(env, dstP, -1, cmDataP);
2669 }
2670 }
2671
2672 if (hintP->packing == BYTE_INTERLEAVED) {
2673 /* Write it back to the destination */
2674 if (rasterP->dataType != BYTE_DATA_TYPE) {
2675 /* We are working with a raster which was marked
2676 as a byte interleaved due to performance reasons.
2677 So, we have to convert the length of the data
2678 array to bytes as well.
2679 */
2680 if (!SAFE_TO_MULT(rasterP->dataSize, dataArrayLength)) {
2681 return ERR_BAD_IMAGE_LAYOUT;
2682 }
2683 dataArrayLength *= rasterP->dataSize;
2684 }
2685
2686 CHECK_DST_ARRAY(hintP->dataOffset, hintP->sStride, hintP->numChans);
2687 cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2688 mStride = mlib_ImageGetStride(mlibImP);
2689 dataP = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env,
2690 rasterP->jdata, NULL);
2691 if (dataP == NULL) return 0;
2692 cDataP = dataP + hintP->dataOffset;
2693 for (y=0; y < rasterP->height;
2694 y++, cmDataP += mStride, cDataP += hintP->sStride)
2695 {
2696 memcpy(cDataP, cmDataP, rasterP->width*hintP->numChans);
2697 }
2698 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2699 JNI_ABORT);
2700 }
2701 else if (dstP->cmodel.cmType == DIRECT_CM_TYPE) {
2702 /* Just need to move bits */
2703 if (mlibImP->type == MLIB_BYTE) {
2704 if (dstP->hints.packing == PACKED_BYTE_INTER) {
2705 return setPackedBCRdefault(env, rasterP, -1,
2706 (unsigned char *) mlibImP->data,
2707 dstP->cmodel.supportsAlpha);
2708 } else if (dstP->hints.packing == PACKED_SHORT_INTER) {
2709 return setPackedSCRdefault(env, rasterP, -1,
2710 (unsigned char *) mlibImP->data,
2711 dstP->cmodel.supportsAlpha);
2712 } else if (dstP->hints.packing == PACKED_INT_INTER) {
2713 return setPackedICRdefault(env, rasterP, -1,
2714 (unsigned char *) mlibImP->data,
2715 dstP->cmodel.supportsAlpha);
2716 }
2717 }
2718 else if (mlibImP->type == MLIB_SHORT) {
2719 return setPixelsFormMlibImage(env, rasterP, mlibImP);
2720 }
2721 }
2722 else {
2723 return cvtDefaultToCustom(env, dstP, -1,
2724 (unsigned char *)mlibImP->data);
2725 }
2726
2727 return 0;
2728}
2729
2730static int
2731storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,
2732 mlib_image *mlibImP) {
2733 unsigned char *cDataP;
2734
2735 switch(dstP->type) {
2736 case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
2737 cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2738 return setPackedBCR(env, dstP, -1, cDataP);
2739
2740 case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:
2741 if (dstP->sppsm.maxBitSize <= 8) {
2742 cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2743 return setPackedSCR(env, dstP, -1, cDataP);
2744 }
2745 break;
2746 case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:
2747 if (dstP->sppsm.maxBitSize <= 8) {
2748 cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2749 return setPackedICR(env, dstP, -1, cDataP);
2750 }
2751 }
2752
2753 return -1;
2754}
2755
2756
2757static int
2758storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
2759 mlib_image *mlibImP)
2760{
2761 int *argb;
2762 int x, y;
2763 unsigned char *dataP, *cDataP, *cP;
2764 unsigned char *sP;
2765 int aIdx, rIdx, gIdx, bIdx;
2766 ColorModelS_t *cmodelP = &dstP->cmodel;
2767 RasterS_t *rasterP = &dstP->raster;
2768
2769 /* REMIND: Only works for RGB */
2770 if (cmodelP->csType != java_awt_color_ColorSpace_TYPE_RGB) {
2771 JNU_ThrowInternalError(env, "Writing to non-RGB images not implemented yet");
2772 return -1;
2773 }
2774
2775 if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||
2776 srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
2777 srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)
2778 {
2779 aIdx = 0;
2780 rIdx = 1;
2781 gIdx = 2;
2782 bIdx = 3;
2783 }
2784 else if (srcP->imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR||
2785 srcP->imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)
2786 {
2787 aIdx = 0;
2788 rIdx = 3;
2789 gIdx = 2;
2790 bIdx = 1;
2791 }
2792 else if (srcP->imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR){
2793 rIdx = 2;
2794 gIdx = 1;
2795 bIdx = 0;
2796 aIdx = 0; /* Ignored */
2797 }
2798 else if (srcP->cmodel.cmType == INDEX_CM_TYPE) {
2799 rIdx = 0;
2800 gIdx = 1;
2801 bIdx = 2;
2802 aIdx = 3; /* Use supportsAlpha to see if it is really there */
2803 }
2804 else {
2805 return -1;
2806 }
2807
2808 /* Lock down the destination raster */
2809 dataP = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env,
2810 rasterP->jdata, NULL);
2811 if (dataP == NULL) {
2812 return -1;
2813 }
2814 argb = (*env)->GetPrimitiveArrayCritical(env, cmodelP->jrgb, NULL);
2815 if (argb == NULL) {
2816 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2817 JNI_ABORT);
2818 return -1;
2819 }
2820
2821 cDataP = dataP + dstP->hints.dataOffset;
2822 sP = (unsigned char *) mlib_ImageGetData(mlibImP);
2823
2824 for (y=0; y < rasterP->height; y++, cDataP += rasterP->scanlineStride) {
2825 cP = cDataP;
2826 for (x=0; x < rasterP->width; x++, cP += rasterP->pixelStride) {
2827 *cP = colorMatch(sP[rIdx], sP[gIdx], sP[bIdx], sP[aIdx],
2828 (unsigned char *)argb, cmodelP->mapSize);
2829 sP += cmodelP->numComponents;
2830 }
2831 }
2832
2833 (*env)->ReleasePrimitiveArrayCritical(env, cmodelP->jrgb, argb, JNI_ABORT);
2834 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2835 JNI_ABORT);
2836 return -1;
2837}
2838
2839static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP)
2840{
2841 ColorModelS_t *cmP = &imageP->cmodel;
2842 RasterS_t *rasterP = &imageP->raster;
2843 HintS_t *hintP = &imageP->hints;
2844 int *rgb;
2845 int status = 0;
2846 unsigned char *dataP, *cP;
2847 unsigned int *mP;
2848 int width = rasterP->width;
2849 int height = rasterP->height;
2850 int x, y;
2851
2852 /* Need to grab the lookup tables. Right now only bytes */
2853 rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, cmP->jrgb, NULL);
2854 CHECK_NULL_RETURN(rgb, -1);
2855
2856 /* Interleaved with shared data */
2857 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env,
2858 rasterP->jdata, NULL);
2859 if (dataP == NULL) {
2860 /* Release the lookup tables */
2861 (*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb, JNI_ABORT);
2862 return -1;
2863 }
2864
2865 if (rasterP->dataType == BYTE_DATA_TYPE) {
2866 unsigned char *cDataP = ((unsigned char *)dataP) + hintP->dataOffset;
2867
2868 for (y=0; y < height; y++) {
2869 mP = mDataP;
2870 cP = cDataP;
2871 for (x=0; x < width; x++, cP += rasterP->pixelStride) {
2872 *mP++ = rgb[*cP];
2873 }
2874 mDataP += width;
2875 cDataP += rasterP->scanlineStride;
2876 }
2877 }
2878 else if (rasterP->dataType == SHORT_DATA_TYPE) {
2879 unsigned short *sDataP, *sP;
2880 sDataP = ((unsigned short *)dataP) + hintP->channelOffset;
2881
2882 for (y=0; y < height; y++) {
2883 mP = mDataP;
2884 sP = sDataP;
2885 for (x=0; x < width; x++, sP+=rasterP->pixelStride) {
2886 *mP++ = rgb[*sP];
2887 }
2888 mDataP += width;
2889 sDataP += rasterP->scanlineStride;
2890 }
2891 }
2892 else {
2893 /* Unknown type */
2894 status = -1;
2895 }
2896 /* Release the lookup table data */
2897 (*env)->ReleasePrimitiveArrayCritical(env, imageP->cmodel.jrgb,
2898 rgb, JNI_ABORT);
2899 /* Release the data array */
2900 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata,
2901 dataP, JNI_ABORT);
2902 return status;
2903}
2904/* This routine is expecting a ByteComponentRaster with a PackedColorModel */
2905static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
2906 unsigned char *outDataP)
2907{
2908 int x, y, c;
2909 unsigned char *outP = outDataP;
2910 unsigned char *lineInP, *inP;
2911 jarray jInDataP;
2912 jint *inDataP;
2913 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
2914
2915 if (rasterP->numBands > MAX_NUMBANDS) {
2916 return -1;
2917 }
2918
2919 /* Grab data ptr, strides, offsets from raster */
2920 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
2921 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
2922 if (inDataP == NULL) {
2923 return -1;
2924 }
2925 lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0];
2926
2927 if (component < 0) {
2928 for (c=0; c < rasterP->numBands; c++) {
2929 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2930 if (roff[c] < 0) {
2931 loff[c] = -roff[c];
2932 roff[c] = 0;
2933 }
2934 else loff[c] = 0;
2935 }
2936 /* Convert the all bands */
2937 if (rasterP->numBands < 4) {
2938 /* Need to put in alpha */
2939 for (y=0; y < rasterP->height; y++) {
2940 inP = lineInP;
2941 for (x=0; x < rasterP->width; x++) {
2942 for (c=0; c < rasterP->numBands; c++) {
2943 *outP++ = (unsigned char)
2944 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2945 <<loff[c]);
2946 }
2947 inP++;
2948 }
2949 lineInP += rasterP->scanlineStride;
2950 }
2951 }
2952 else {
2953 for (y=0; y < rasterP->height; y++) {
2954 inP = lineInP;
2955 for (x=0; x < rasterP->width; x++) {
2956 for (c=0; c < rasterP->numBands; c++) {
2957 *outP++ = (unsigned char)
2958 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2959 <<loff[c]);
2960 }
2961 inP++;
2962 }
2963 lineInP += rasterP->scanlineStride;
2964 }
2965 }
2966 }
2967 else {
2968 c = component;
2969 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2970 if (roff[0] < 0) {
2971 loff[0] = -roff[0];
2972 roff[0] = 0;
2973 }
2974 else loff[c] = 0;
2975 for (y=0; y < rasterP->height; y++) {
2976 inP = lineInP;
2977 for (x=0; x < rasterP->width; x++) {
2978 *outP++ = (unsigned char)
2979 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
2980 inP++;
2981 }
2982 lineInP += rasterP->scanlineStride;
2983 }
2984 }
2985
2986 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
2987
2988 return 0;
2989}
2990
2991/* This routine is expecting a ByteComponentRaster with a PackedColorModel */
2992static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
2993 int component, unsigned char *outDataP,
2994 int forceAlpha)
2995{
2996 int x, y, c;
2997 unsigned char *outP = outDataP;
2998 unsigned char *lineInP, *inP;
2999 jarray jInDataP;
3000 jint *inDataP;
3001 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3002 int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3003 int a = numBands;
3004
3005 if (rasterP->numBands > MAX_NUMBANDS) {
3006 return -1;
3007 }
3008
3009 /* Grab data ptr, strides, offsets from raster */
3010 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3011 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3012 if (inDataP == NULL) {
3013 return -1;
3014 }
3015 lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0];
3016
3017 if (component < 0) {
3018 for (c=0; c < rasterP->numBands; c++) {
3019 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3020 if (roff[c] < 0) {
3021 loff[c] = -roff[c];
3022 roff[c] = 0;
3023 }
3024 else loff[c] = 0;
3025 }
3026
3027 /* Need to put in alpha */
3028 if (forceAlpha) {
3029 for (y=0; y < rasterP->height; y++) {
3030 inP = lineInP;
3031 for (x=0; x < rasterP->width; x++) {
3032 *outP++ = 0xff;
3033 for (c=0; c < numBands; c++) {
3034 *outP++ = (unsigned char)
3035 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3036 <<loff[c]);
3037 }
3038 inP++;
3039 }
3040 lineInP += rasterP->scanlineStride;
3041 }
3042 }
3043 else {
3044 for (y=0; y < rasterP->height; y++) {
3045 inP = lineInP;
3046 for (x=0; x < rasterP->width; x++) {
3047 *outP++ = (unsigned char)
3048 (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3049 <<loff[a]);
3050 for (c=0; c < numBands; c++) {
3051 *outP++ = (unsigned char)
3052 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3053 <<loff[c]);
3054 }
3055 inP++;
3056 }
3057 lineInP += rasterP->scanlineStride;
3058 }
3059 }
3060 }
3061 else {
3062 c = component;
3063 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3064 if (roff[0] < 0) {
3065 loff[0] = -roff[0];
3066 roff[0] = 0;
3067 }
3068 else loff[c] = 0;
3069 for (y=0; y < rasterP->height; y++) {
3070 inP = lineInP;
3071 for (x=0; x < rasterP->width; x++) {
3072 *outP++ = (unsigned char)
3073 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3074 inP++;
3075 }
3076 lineInP += rasterP->scanlineStride;
3077 }
3078 }
3079
3080 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3081
3082 return 0;
3083}
3084
3085/* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3086static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
3087 unsigned char *outDataP)
3088{
3089 int x, y, c;
3090 unsigned char *outP = outDataP;
3091 unsigned short *lineInP, *inP;
3092 jarray jInDataP;
3093 jint *inDataP;
3094 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3095
3096 if (rasterP->numBands > MAX_NUMBANDS) {
3097 return -1;
3098 }
3099
3100 /* Grab data ptr, strides, offsets from raster */
3101 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3102 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3103 if (inDataP == NULL) {
3104 return -1;
3105 }
3106 lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0];
3107
3108 if (component < 0) {
3109 for (c=0; c < rasterP->numBands; c++) {
3110 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3111 if (roff[c] < 0) {
3112 loff[c] = -roff[c];
3113 roff[c] = 0;
3114 }
3115 else loff[c] = 0;
3116 }
3117 /* Convert the all bands */
3118 if (rasterP->numBands < 4) {
3119 /* Need to put in alpha */
3120 for (y=0; y < rasterP->height; y++) {
3121 inP = lineInP;
3122 for (x=0; x < rasterP->width; x++) {
3123 for (c=0; c < rasterP->numBands; c++) {
3124 /*
3125 *Not correct. Might need to unpremult,
3126 * shift, etc
3127 */
3128 *outP++ = (unsigned char)
3129 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3130 <<loff[c]);
3131 }
3132 inP++;
3133 }
3134 lineInP += rasterP->scanlineStride;
3135 }
3136 } else {
3137 for (y=0; y < rasterP->height; y++) {
3138 inP = lineInP;
3139 for (x=0; x < rasterP->width; x++) {
3140 for (c=0; c < rasterP->numBands; c++) {
3141 /*
3142 *Not correct. Might need to unpremult,
3143 * shift, etc
3144 */
3145 *outP++ = (unsigned char)
3146 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3147 <<loff[c]);
3148 }
3149 inP++;
3150 }
3151 lineInP += rasterP->scanlineStride;
3152 }
3153 }
3154 }
3155 else {
3156 c = component;
3157 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3158 if (roff[0] < 0) {
3159 loff[0] = -roff[0];
3160 roff[0] = 0;
3161 }
3162 else loff[c] = 0;
3163 for (y=0; y < rasterP->height; y++) {
3164 inP = lineInP;
3165 for (x=0; x < rasterP->width; x++) {
3166 *outP++ = (unsigned char)
3167 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3168 inP++;
3169 }
3170 lineInP += rasterP->scanlineStride;
3171 }
3172 }
3173
3174 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3175
3176 return 0;
3177}
3178
3179/* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3180static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
3181 int component, unsigned char *outDataP,
3182 int forceAlpha)
3183{
3184 int x, y, c;
3185 unsigned char *outP = outDataP;
3186 unsigned short *lineInP, *inP;
3187 jarray jInDataP;
3188 jint *inDataP;
3189 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3190 int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3191 int a = numBands;
3192
3193 if (rasterP->numBands > MAX_NUMBANDS) {
3194 return -1;
3195 }
3196
3197 /* Grab data ptr, strides, offsets from raster */
3198 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3199 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3200 if (inDataP == NULL) {
3201 return -1;
3202 }
3203 lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0];
3204
3205 if (component < 0) {
3206 for (c=0; c < rasterP->numBands; c++) {
3207 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3208 if (roff[c] < 0) {
3209 loff[c] = -roff[c];
3210 roff[c] = 0;
3211 }
3212 else loff[c] = 0;
3213 }
3214
3215 /* Need to put in alpha */
3216 if (forceAlpha) {
3217 for (y=0; y < rasterP->height; y++) {
3218 inP = lineInP;
3219 for (x=0; x < rasterP->width; x++) {
3220 *outP++ = 0xff;
3221 for (c=0; c < numBands; c++) {
3222 /*
3223 * Not correct. Might need to unpremult,
3224 * shift, etc
3225 */
3226 *outP++ = (unsigned char)
3227 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3228 <<loff[c]);
3229 }
3230 inP++;
3231 }
3232 lineInP += rasterP->scanlineStride;
3233 }
3234 }
3235 else {
3236 for (y=0; y < rasterP->height; y++) {
3237 inP = lineInP;
3238 for (x=0; x < rasterP->width; x++) {
3239 *outP++ = (unsigned char)
3240 (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3241 <<loff[a]);
3242 for (c=0; c < numBands; c++) {
3243 /*
3244 * Not correct. Might need to
3245 * unpremult, shift, etc
3246 */
3247 *outP++ = (unsigned char)
3248 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3249 <<loff[c]);
3250 }
3251 inP++;
3252 }
3253 lineInP += rasterP->scanlineStride;
3254 }
3255 }
3256 }
3257 else {
3258 c = component;
3259 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3260 if (roff[0] < 0) {
3261 loff[0] = -roff[0];
3262 roff[0] = 0;
3263 }
3264 else loff[c] = 0;
3265 for (y=0; y < rasterP->height; y++) {
3266 inP = lineInP;
3267 for (x=0; x < rasterP->width; x++) {
3268 *outP++ = (unsigned char)
3269 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3270 inP++;
3271 }
3272 lineInP += rasterP->scanlineStride;
3273 }
3274 }
3275
3276 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3277
3278 return 0;
3279
3280}
3281
3282/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3283static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
3284 unsigned char *outDataP)
3285{
3286 int x, y, c;
3287 unsigned char *outP = outDataP;
3288 unsigned int *lineInP, *inP;
3289 jarray jInDataP;
3290 jint *inDataP;
3291 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3292
3293 if (rasterP->numBands > MAX_NUMBANDS) {
3294 return -1;
3295 }
3296
3297 /* Grab data ptr, strides, offsets from raster */
3298 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3299 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3300 if (inDataP == NULL) {
3301 return -1;
3302 }
3303 lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0];
3304
3305 if (component < 0) {
3306 for (c=0; c < rasterP->numBands; c++) {
3307 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3308 if (roff[c] < 0) {
3309 loff[c] = -roff[c];
3310 roff[c] = 0;
3311 }
3312 else loff[c] = 0;
3313 }
3314 /* Convert the all bands */
3315 if (rasterP->numBands < 4) {
3316 for (y=0; y < rasterP->height; y++) {
3317 inP = lineInP;
3318 for (x=0; x < rasterP->width; x++) {
3319 for (c=0; c < rasterP->numBands; c++) {
3320 /*
3321 * Not correct. Might need to unpremult,
3322 * shift, etc
3323 */
3324 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3325 <<loff[c]);
3326 }
3327 inP++;
3328 }
3329 lineInP += rasterP->scanlineStride;
3330 }
3331 }
3332 else {
3333 for (y=0; y < rasterP->height; y++) {
3334 inP = lineInP;
3335 for (x=0; x < rasterP->width; x++) {
3336 for (c=0; c < rasterP->numBands; c++) {
3337 /*
3338 * Not correct. Might need to
3339 * unpremult, shift, etc
3340 */
3341 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3342 <<loff[c]);
3343 }
3344 inP++;
3345 }
3346 lineInP += rasterP->scanlineStride;
3347 }
3348 }
3349 }
3350 else {
3351 c = component;
3352 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3353 if (roff[0] < 0) {
3354 loff[0] = -roff[0];
3355 roff[0] = 0;
3356 }
3357 else loff[c] = 0;
3358 for (y=0; y < rasterP->height; y++) {
3359 inP = lineInP;
3360 for (x=0; x < rasterP->width; x++) {
3361 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);
3362 inP++;
3363 }
3364 lineInP += rasterP->scanlineStride;
3365 }
3366 }
3367
3368 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3369
3370 return 0;
3371}
3372
3373/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3374static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
3375 int component, unsigned char *outDataP,
3376 int forceAlpha)
3377{
3378 int x, y, c;
3379 unsigned char *outP = outDataP;
3380 unsigned int *lineInP, *inP;
3381 jarray jInDataP;
3382 jint *inDataP;
3383 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3384 int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3385 int a = numBands;
3386
3387 if (rasterP->numBands > MAX_NUMBANDS) {
3388 return -1;
3389 }
3390
3391 /* Grab data ptr, strides, offsets from raster */
3392 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3393 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3394 if (inDataP == NULL) {
3395 return -1;
3396 }
3397 lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0];
3398
3399 if (component < 0) {
3400 for (c=0; c < rasterP->numBands; c++) {
3401 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3402 if (roff[c] < 0) {
3403 loff[c] = -roff[c];
3404 roff[c] = 0;
3405 }
3406 else loff[c] = 0;
3407 }
3408
3409 /* Need to put in alpha */
3410 if (forceAlpha) {
3411 for (y=0; y < rasterP->height; y++) {
3412 inP = lineInP;
3413 for (x=0; x < rasterP->width; x++) {
3414 *outP++ = 0xff;
3415 for (c=0; c < numBands; c++) {
3416 /*
3417 * Not correct. Might need to unpremult,
3418 * shift, etc
3419 */
3420 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3421 <<loff[c]);
3422 }
3423 inP++;
3424 }
3425 lineInP += rasterP->scanlineStride;
3426 }
3427 }
3428 else {
3429 for (y=0; y < rasterP->height; y++) {
3430 inP = lineInP;
3431 for (x=0; x < rasterP->width; x++) {
3432 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3433 <<loff[a]);
3434 for (c=0; c < numBands; c++) {
3435 /*
3436 * Not correct. Might need to
3437 * unpremult, shift, etc
3438 */
3439 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3440 <<loff[c]);
3441 }
3442 inP++;
3443 }
3444 lineInP += rasterP->scanlineStride;
3445 }
3446 }
3447 }
3448 else {
3449 c = component;
3450 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3451 if (roff[0] < 0) {
3452 loff[0] = -roff[0];
3453 roff[0] = 0;
3454 }
3455 else loff[c] = 0;
3456 for (y=0; y < rasterP->height; y++) {
3457 inP = lineInP;
3458 for (x=0; x < rasterP->width; x++) {
3459 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);
3460 inP++;
3461 }
3462 lineInP += rasterP->scanlineStride;
3463 }
3464 }
3465
3466 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3467
3468 return 0;
3469}
3470
3471/* This routine is expecting a ByteComponentRaster with a PackedColorModel */
3472static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
3473 unsigned char *inDataP)
3474{
3475 int x, y, c;
3476 unsigned char *inP = inDataP;
3477 unsigned char *lineOutP, *outP;
3478 jarray jOutDataP;
3479 jsize dataArrayLength;
3480 unsigned char *outDataP;
3481 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3482
3483 if (rasterP->numBands > MAX_NUMBANDS) {
3484 return -1;
3485 }
3486
3487 /* Grab data ptr, strides, offsets from raster */
3488 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3489 if (JNU_IsNull(env, jOutDataP)) {
3490 return -1;
3491 }
3492
3493 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3494 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3495
3496 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3497 if (outDataP == NULL) {
3498 return -1;
3499 }
3500 lineOutP = outDataP + rasterP->chanOffsets[0];
3501
3502 if (component < 0) {
3503 for (c=0; c < rasterP->numBands; c++) {
3504 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3505 if (loff[c] < 0) {
3506 roff[c] = -loff[c];
3507 loff[c] = 0;
3508 }
3509 else roff[c] = 0;
3510 }
3511 /* Convert the all bands */
3512 for (y=0; y < rasterP->height; y++) {
3513 outP = lineOutP;
3514 *outP = 0;
3515 for (x=0; x < rasterP->width; x++) {
3516 for (c=0; c < rasterP->numBands; c++, inP++) {
3517 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3518 }
3519 outP++;
3520 }
3521 lineOutP += rasterP->scanlineStride;
3522 }
3523 }
3524 else {
3525 c = component;
3526 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3527 if (loff[0] < 0) {
3528 roff[0] = -loff[0];
3529 loff[0] = 0;
3530 }
3531 else roff[c] = 0;
3532 for (y=0; y < rasterP->height; y++) {
3533 outP = lineOutP;
3534 for (x=0; x < rasterP->width; x++, inP++) {
3535 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3536 outP++;
3537 }
3538 lineOutP += rasterP->scanlineStride;
3539 }
3540 }
3541
3542 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3543
3544 return 0;
3545}
3546
3547/* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3548static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
3549 unsigned char *inDataP)
3550{
3551 int x, y, c;
3552 unsigned char *inP = inDataP;
3553 unsigned short *lineOutP, *outP;
3554 jarray jOutDataP;
3555 jsize dataArrayLength;
3556 unsigned short *outDataP;
3557 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3558
3559 if (rasterP->numBands > MAX_NUMBANDS) {
3560 return -1;
3561 }
3562
3563 /* Grab data ptr, strides, offsets from raster */
3564 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3565 if (JNU_IsNull(env, jOutDataP)) {
3566 return -1;
3567 }
3568
3569 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3570 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3571
3572 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3573 if (outDataP == NULL) {
3574 return -1;
3575 }
3576 lineOutP = outDataP + rasterP->chanOffsets[0];
3577
3578 if (component < 0) {
3579 for (c=0; c < rasterP->numBands; c++) {
3580 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3581 if (loff[c] < 0) {
3582 roff[c] = -loff[c];
3583 loff[c] = 0;
3584 }
3585 else roff[c] = 0;
3586 }
3587 /* Convert the all bands */
3588 for (y=0; y < rasterP->height; y++) {
3589 outP = lineOutP;
3590 for (x=0; x < rasterP->width; x++) {
3591 for (c=0; c < rasterP->numBands; c++, inP++) {
3592 /* Not correct. Might need to unpremult, shift, etc */
3593 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3594 }
3595 outP++;
3596 }
3597 lineOutP += rasterP->scanlineStride;
3598 }
3599 }
3600 else {
3601 c = component;
3602 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3603 if (loff[0] < 0) {
3604 roff[0] = -loff[0];
3605 loff[0] = 0;
3606 }
3607 else roff[c] = 0;
3608 for (y=0; y < rasterP->height; y++) {
3609 outP = lineOutP;
3610 for (x=0; x < rasterP->width; x++, inP++) {
3611 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3612 outP++;
3613 }
3614 lineOutP += rasterP->scanlineStride;
3615 }
3616 }
3617
3618 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3619
3620 return 0;
3621}
3622
3623/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3624static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
3625 unsigned char *inDataP)
3626{
3627 int x, y, c;
3628 unsigned char *inP = inDataP;
3629 unsigned int *lineOutP, *outP;
3630 jarray jOutDataP;
3631 jsize dataArrayLength;
3632 unsigned int *outDataP;
3633 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3634
3635 if (rasterP->numBands > MAX_NUMBANDS) {
3636 return -1;
3637 }
3638
3639 /* Grab data ptr, strides, offsets from raster */
3640 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3641 if (JNU_IsNull(env, jOutDataP)) {
3642 return -1;
3643 }
3644
3645 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3646 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3647
3648 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3649 if (outDataP == NULL) {
3650 return -1;
3651 }
3652 lineOutP = outDataP + rasterP->chanOffsets[0];
3653
3654 if (component < 0) {
3655 for (c=0; c < rasterP->numBands; c++) {
3656 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3657 if (loff[c] < 0) {
3658 roff[c] = -loff[c];
3659 loff[c] = 0;
3660 }
3661 else roff[c] = 0;
3662 }
3663 /* Convert the all bands */
3664 for (y=0; y < rasterP->height; y++) {
3665 outP = lineOutP;
3666 for (x=0; x < rasterP->width; x++) {
3667 for (c=0; c < rasterP->numBands; c++, inP++) {
3668 /* Not correct. Might need to unpremult, shift, etc */
3669 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3670 }
3671 outP++;
3672 }
3673 lineOutP += rasterP->scanlineStride;
3674 }
3675 }
3676 else {
3677 c = component;
3678 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3679 if (loff[0] < 0) {
3680 roff[0] = -loff[0];
3681 loff[0] = 0;
3682 }
3683 else roff[c] = 0;
3684
3685 for (y=0; y < rasterP->height; y++) {
3686 outP = lineOutP;
3687 for (x=0; x < rasterP->width; x++, inP++) {
3688 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3689 outP++;
3690 }
3691 lineOutP += rasterP->scanlineStride;
3692 }
3693 }
3694
3695 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3696
3697 return 0;
3698}
3699
3700/* This routine is expecting a ByteComponentRaster with a PackedColorModel */
3701static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
3702 int component, unsigned char *inDataP,
3703 int supportsAlpha)
3704{
3705 int x, y, c;
3706 unsigned char *inP = inDataP;
3707 unsigned char *lineOutP, *outP;
3708 jarray jOutDataP;
3709 jsize dataArrayLength;
3710 unsigned char *outDataP;
3711 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3712 int a = rasterP->numBands - 1;
3713
3714 if (rasterP->numBands > MAX_NUMBANDS) {
3715 return -1;
3716 }
3717
3718 /* Grab data ptr, strides, offsets from raster */
3719 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3720 if (JNU_IsNull(env, jOutDataP)) {
3721 return -1;
3722 }
3723
3724 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3725 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3726
3727 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3728 if (outDataP == NULL) {
3729 return -1;
3730 }
3731 lineOutP = outDataP + rasterP->chanOffsets[0];
3732
3733 if (component < 0) {
3734 for (c=0; c < rasterP->numBands; c++) {
3735 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3736 if (loff[c] < 0) {
3737 roff[c] = -loff[c];
3738 loff[c] = 0;
3739 }
3740 else roff[c] = 0;
3741 }
3742 /* Convert the all bands */
3743 if (supportsAlpha) {
3744 for (y=0; y < rasterP->height; y++) {
3745 outP = lineOutP;
3746 *outP = 0;
3747 for (x=0; x < rasterP->width; x++) {
3748 *outP |= (*inP<<loff[a]>>roff[a])&
3749 rasterP->sppsm.maskArray[a];
3750 inP++;
3751 for (c=0; c < rasterP->numBands-1; c++, inP++) {
3752 *outP |= (*inP<<loff[c]>>roff[c])&
3753 rasterP->sppsm.maskArray[c];
3754 }
3755 outP++;
3756 }
3757 lineOutP += rasterP->scanlineStride;
3758 }
3759 }
3760 else {
3761 for (y=0; y < rasterP->height; y++) {
3762 outP = lineOutP;
3763 *outP = 0;
3764 for (x=0; x < rasterP->width; x++) {
3765 inP++;
3766 for (c=0; c < rasterP->numBands; c++, inP++) {
3767 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3768 }
3769 outP++;
3770 }
3771 lineOutP += rasterP->scanlineStride;
3772 }
3773 }
3774 }
3775 else {
3776 c = component;
3777 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3778 if (loff[0] < 0) {
3779 roff[0] = -loff[0];
3780 loff[0] = 0;
3781 }
3782 else roff[c] = 0;
3783 for (y=0; y < rasterP->height; y++) {
3784 outP = lineOutP;
3785 for (x=0; x < rasterP->width; x++, inP++) {
3786 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3787 outP++;
3788 }
3789 lineOutP += rasterP->scanlineStride;
3790 }
3791 }
3792
3793 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3794
3795 return 0;
3796}
3797
3798/* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3799static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
3800 int component, unsigned char *inDataP,
3801 int supportsAlpha)
3802{
3803 int x, y, c;
3804 unsigned char *inP = inDataP;
3805 unsigned short *lineOutP, *outP;
3806 jarray jOutDataP;
3807 jsize dataArrayLength;
3808 unsigned short *outDataP;
3809 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3810 int a = rasterP->numBands - 1;
3811
3812 if (rasterP->numBands > MAX_NUMBANDS) {
3813 return -1;
3814 }
3815
3816 /* Grab data ptr, strides, offsets from raster */
3817 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3818 if (JNU_IsNull(env, jOutDataP)) {
3819 return -1;
3820 }
3821 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3822 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3823
3824 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3825 if (outDataP == NULL) {
3826 return -1;
3827 }
3828 lineOutP = outDataP + rasterP->chanOffsets[0];
3829
3830 if (component < 0) {
3831 for (c=0; c < rasterP->numBands; c++) {
3832 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3833 if (loff[c] < 0) {
3834 roff[c] = -loff[c];
3835 loff[c] = 0;
3836 }
3837 else roff[c] = 0;
3838 }
3839 /* Convert the all bands */
3840 if (supportsAlpha) {
3841 for (y=0; y < rasterP->height; y++) {
3842 outP = lineOutP;
3843 for (x=0; x < rasterP->width; x++) {
3844 *outP |= (*inP<<loff[a]>>roff[a])&
3845 rasterP->sppsm.maskArray[a];
3846 inP++;
3847 for (c=0; c < rasterP->numBands-1; c++, inP++) {
3848 /* Not correct. Might need to unpremult, shift, etc */
3849 *outP |= (*inP<<loff[c]>>roff[c])&
3850 rasterP->sppsm.maskArray[c];
3851 }
3852 outP++;
3853 }
3854 lineOutP += rasterP->scanlineStride;
3855 }
3856 }
3857 else {
3858 for (y=0; y < rasterP->height; y++) {
3859 outP = lineOutP;
3860 for (x=0; x < rasterP->width; x++) {
3861 inP++;
3862 for (c=0; c < rasterP->numBands; c++, inP++) {
3863 /* Not correct. Might need to unpremult, shift, etc */
3864 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3865 }
3866 outP++;
3867 }
3868 lineOutP += rasterP->scanlineStride;
3869 }
3870 }
3871 }
3872 else {
3873 c = component;
3874 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3875 if (loff[0] < 0) {
3876 roff[0] = -loff[0];
3877 loff[0] = 0;
3878 }
3879 else roff[c] = 0;
3880 for (y=0; y < rasterP->height; y++) {
3881 outP = lineOutP;
3882 for (x=0; x < rasterP->width; x++, inP++) {
3883 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3884 outP++;
3885 }
3886 lineOutP += rasterP->scanlineStride;
3887 }
3888 }
3889
3890 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3891
3892 return 0;
3893}
3894
3895/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3896static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
3897 int component, unsigned char *inDataP,
3898 int supportsAlpha)
3899{
3900 int x, y, c;
3901 unsigned char *inP = inDataP;
3902 unsigned int *lineOutP, *outP;
3903 jarray jOutDataP;
3904 jsize dataArrayLength;
3905 unsigned int *outDataP;
3906 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3907 int a = rasterP->numBands - 1;
3908
3909 if (rasterP->numBands > MAX_NUMBANDS) {
3910 return -1;
3911 }
3912
3913 /* Grab data ptr, strides, offsets from raster */
3914 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3915 if (JNU_IsNull(env, jOutDataP)) {
3916 return -1;
3917 }
3918
3919 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);
3920 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);
3921
3922 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3923 if (outDataP == NULL) {
3924 return -1;
3925 }
3926 lineOutP = outDataP + rasterP->chanOffsets[0];
3927
3928 if (component < 0) {
3929 for (c=0; c < rasterP->numBands; c++) {
3930 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3931 if (loff[c] < 0) {
3932 roff[c] = -loff[c];
3933 loff[c] = 0;
3934 }
3935 else roff[c] = 0;
3936 }
3937 /* Convert the all bands */
3938 if (supportsAlpha) {
3939 for (y=0; y < rasterP->height; y++) {
3940 outP = lineOutP;
3941 for (x=0; x < rasterP->width; x++) {
3942 *outP |= (*inP<<loff[a]>>roff[a])&
3943 rasterP->sppsm.maskArray[a];
3944 inP++;
3945 for (c=0; c < rasterP->numBands-1; c++, inP++) {
3946 /* Not correct. Might need to unpremult, shift, etc */
3947 *outP |= (*inP<<loff[c]>>roff[c])&
3948 rasterP->sppsm.maskArray[c];
3949 }
3950 outP++;
3951 }
3952 lineOutP += rasterP->scanlineStride;
3953 }
3954 }
3955 else {
3956 for (y=0; y < rasterP->height; y++) {
3957 outP = lineOutP;
3958 for (x=0; x < rasterP->width; x++) {
3959 inP++;
3960 for (c=0; c < rasterP->numBands; c++, inP++) {
3961 /* Not correct. Might need to unpremult, shift, etc */
3962 *outP |= (*inP<<loff[c]>>roff[c])&
3963 rasterP->sppsm.maskArray[c];
3964 }
3965 outP++;
3966 }
3967 lineOutP += rasterP->scanlineStride;
3968 }
3969 }
3970 }
3971 else {
3972 c = component;
3973 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3974 if (loff[0] < 0) {
3975 roff[0] = -loff[0];
3976 loff[0] = 0;
3977 }
3978 else roff[c] = 0;
3979
3980 for (y=0; y < rasterP->height; y++) {
3981 outP = lineOutP;
3982 for (x=0; x < rasterP->width; x++, inP++) {
3983 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3984 outP++;
3985 }
3986 lineOutP += rasterP->scanlineStride;
3987 }
3988 }
3989
3990 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3991
3992 return 0;
3993}
3994
3995/* This is temporary code. Should go away when there is better color
3996 * conversion code available.
3997 * REMIND: Ignoring alpha
3998 */
3999/* returns the absolute value x */
4000#define ABS(x) ((x) < 0 ? -(x) : (x))
4001#define CLIP(val,min,max) ((val < min) ? min : ((val > max) ? max : val))
4002
4003static int
4004colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors) {
4005 int besti = 0;
4006 int mindist, i, t, d;
4007 unsigned char red, green, blue;
4008
4009 r = CLIP(r, 0, 255);
4010 g = CLIP(g, 0, 255);
4011 b = CLIP(b, 0, 255);
4012
4013 /* look for pure gray match */
4014 if ((r == g) && (g == b)) {
4015 mindist = 256;
4016 for (i = 0 ; i < numColors ; i++, argb+=4) {
4017 red = argb[1];
4018 green = argb[2];
4019 blue = argb[3];
4020 if (! ((red == green) && (green == blue)) ) {
4021 continue;
4022 }
4023 d = ABS(red - r);
4024 if (d == 0)
4025 return i;
4026 if (d < mindist) {
4027 besti = i;
4028 mindist = d;
4029 }
4030 }
4031 return besti;
4032 }
4033
4034 /* look for non-pure gray match */
4035 mindist = 256 * 256 * 256;
4036 for (i = 0 ; i < numColors ; i++, argb+=4) {
4037 red = argb[1];
4038 green = argb[2];
4039 blue = argb[3];
4040 t = red - r;
4041 d = t * t;
4042 if (d >= mindist) {
4043 continue;
4044 }
4045 t = green - g;
4046 d += t * t;
4047 if (d >= mindist) {
4048 continue;
4049 }
4050 t = blue - b;
4051 d += t * t;
4052 if (d >= mindist) {
4053 continue;
4054 }
4055 if (d == 0)
4056 return i;
4057 if (d < mindist) {
4058 besti = i;
4059 mindist = d;
4060 }
4061 }
4062
4063 return besti;
4064}
4065