1 /* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include "sun_awt_image_ImagingLib.h" 30 #include "java_awt_Transparency.h" 31 #include "java_awt_image_AffineTransformOp.h" 32 #include "java_awt_image_BufferedImage.h" 33 #include "java_awt_color_ColorSpace.h" 34 #include "java_awt_image_ConvolveOp.h" 35 #include "sun_awt_image_IntegerComponentRaster.h" 36 #include "awt_ImagingLib.h" 37 #include "awt_parseImage.h" 38 #include "imageInitIDs.h" 39 #include <jni.h> 40 #include <jni_util.h> 41 #include <assert.h> 42 #include "awt_Mlib.h" 43 #include "gdefs.h" 44 #include "safe_alloc.h" 45 #include "safe_math.h" 46 47 /*************************************************************************** 48 * Definitions * 49 ***************************************************************************/ 50 #define jio_fprintf fprintf 51 52 #ifndef TRUE 53 #define TRUE 1 54 #endif /* TRUE */ 55 56 #ifndef FALSE 57 #define FALSE 0 58 #endif /* FALSE */ 59 60 #define TYPE_CUSTOM java_awt_image_BufferedImage_TYPE_CUSTOM 61 #define TYPE_INT_RGB java_awt_image_BufferedImage_TYPE_INT_RGB 62 #define TYPE_INT_ARGB java_awt_image_BufferedImage_TYPE_INT_ARGB 63 #define TYPE_INT_ARGB_PRE java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE 64 #define TYPE_INT_BGR java_awt_image_BufferedImage_TYPE_INT_BGR 65 #define TYPE_4BYTE_ABGR java_awt_image_BufferedImage_TYPE_4BYTE_ABGR 66 #define TYPE_4BYTE_ABGR_PRE java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE 67 68 /* (alpha*color)>>nbits + alpha>>(nbits-1) */ 69 #define BLEND(color, alpha, alphaNbits) \ 70 ((((alpha)*(color))>>(alphaNbits)) + ((alpha) >> ((alphaNbits)-1))) 71 72 /* ((color - (alpha>>(nBits-1)))<<nBits)/alpha */ 73 #define UNBLEND(color, alpha, alphaNbits) \ 74 ((((color)-((alpha)>>((alphaNbits)-1)))<<(alphaNbits))/(alpha)) 75 76 /* Enumeration of all of the mlib functions used */ 77 typedef enum { 78 MLIB_CONVMxN, 79 MLIB_AFFINE, 80 MLIB_LOOKUP, 81 MLIB_CONVKERNCVT 82 } mlibTypeE_t; 83 84 typedef struct { 85 int dataType; /* One of BYTE_DATA_TYPE, SHORT_DATA_TYPE, */ 86 int needToCopy; 87 int cvtSrcToDefault; /* If TRUE, convert the src to def CM (pre?) */ 88 int allocDefaultDst; /* If TRUE, alloc def CM dst buffer */ 89 int cvtToDst; /* If TRUE, convert dst buffer to Dst CM */ 90 int addAlpha; 91 } mlibHintS_t; 92 93 /*************************************************************************** 94 * Static Variables/Structures * 95 ***************************************************************************/ 96 97 static mlibSysFnS_t sMlibSysFns = { 98 NULL, // placeholder for j2d_mlib_ImageCreate 99 NULL, // placeholder for j2d_mlib_ImageCreateStruct 100 NULL, // placeholder for j2d_mlib_ImageDelete 101 }; 102 103 static mlibFnS_t sMlibFns[] = { 104 {NULL, "j2d_mlib_ImageConvMxN"}, 105 {NULL, "j2d_mlib_ImageAffine"}, 106 {NULL, "j2d_mlib_ImageLookUp"}, 107 {NULL, "j2d_mlib_ImageConvKernelConvert"}, 108 {NULL, NULL}, 109 }; 110 111 static int s_timeIt = 0; 112 static int s_printIt = 0; 113 static int s_startOff = 0; 114 static int s_nomlib = 0; 115 116 /*************************************************************************** 117 * Static Function Prototypes * 118 ***************************************************************************/ 119 120 static int 121 allocateArray(JNIEnv *env, BufImageS_t *imageP, 122 mlib_image **mlibImagePP, void **dataPP, int isSrc, 123 int cvtToDefault, int addAlpha); 124 static int 125 allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, 126 mlib_image **mlibImagePP, void **dataPP, int isSrc); 127 128 static void 129 freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP, 130 void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP, 131 void *dstdataP); 132 static void 133 freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP, 134 void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP, 135 void *dstdataP); 136 137 static int 138 storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, 139 mlib_image *mlibImP); 140 141 static int 142 storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP, 143 mlib_image *mlibImP); 144 145 static int 146 storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, 147 mlib_image *mlibImP); 148 149 static int 150 colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors); 151 152 static int 153 setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, 154 int expandICM, int useAlpha, 155 int premultiply, mlibHintS_t *hintP); 156 157 158 static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP); 159 static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component, 160 unsigned char *outDataP); 161 static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component, 162 unsigned char *outDataP); 163 static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component, 164 unsigned char *outDataP); 165 static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP, 166 int component, unsigned char *outDataP, 167 int forceAlpha); 168 static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP, 169 int component, unsigned char *outDataP, 170 int forceAlpha); 171 static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP, 172 int component, unsigned char *outDataP, 173 int forceAlpha); 174 static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component, 175 unsigned char *outDataP); 176 static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component, 177 unsigned char *outDataP); 178 static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component, 179 unsigned char *outDataP); 180 static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP, 181 int component, unsigned char *outDataP, 182 int supportsAlpha); 183 static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP, 184 int component, unsigned char *outDataP, 185 int supportsAlpha); 186 static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP, 187 int component, unsigned char *outDataP, 188 int supportsAlpha); 189 190 mlib_start_timer start_timer = NULL; 191 mlib_stop_timer stop_timer = NULL; 192 193 /*************************************************************************** 194 * Debugging Definitions * 195 ***************************************************************************/ 196 #ifdef DEBUG 197 198 static void 199 printMedialibError(int status) { 200 switch(status) { 201 case MLIB_FAILURE: 202 jio_fprintf(stderr, "failure\n"); 203 break; 204 case MLIB_NULLPOINTER: 205 jio_fprintf(stderr, "null pointer\n"); 206 break; 207 case MLIB_OUTOFRANGE: 208 jio_fprintf (stderr, "out of range\n"); 209 break; 210 default: 211 jio_fprintf (stderr, "medialib error\n"); 212 break; 213 } 214 } 215 #else /* ! DEBUG */ 216 # define printMedialibError(x) 217 218 #endif /* ! DEBUG */ 219 220 static int 221 getMlibEdgeHint(jint edgeHint) { 222 switch (edgeHint) { 223 case java_awt_image_ConvolveOp_EDGE_NO_OP: 224 return MLIB_EDGE_DST_COPY_SRC; 225 case java_awt_image_ConvolveOp_EDGE_ZERO_FILL: 226 default: 227 return MLIB_EDGE_DST_FILL_ZERO; 228 } 229 } 230 231 /* 232 * We have to make sure that awt_setPixels can be safely applied to the given pair of 233 * raster and mlib image. 234 * 235 * In particular, make sure that 236 * - dimension is the same 237 * - number of channels in mlib image corresponds to the number of bands in the raster 238 * - sample size in image and raster are the same. 239 * 240 * Returns: 241 * -1 to indicate failure, 242 * 1 to indicate success 243 */ 244 static int setPixelsFormMlibImage(JNIEnv *env, RasterS_t *rasterP, mlib_image* img) { 245 if (rasterP->width != img->width || rasterP->height != img->height) { 246 /* dimension does not match */ 247 return -1; 248 } 249 250 if (rasterP->numBands != img->channels) { 251 /* number of bands does not match */ 252 return -1; 253 } 254 255 switch (rasterP->dataType) { 256 case BYTE_DATA_TYPE: 257 if (img->type != MLIB_BYTE) { 258 return -1; 259 } 260 break; 261 case SHORT_DATA_TYPE: 262 if (img->type != MLIB_SHORT && img->type != MLIB_USHORT) { 263 return -1; 264 } 265 break; 266 default: 267 /* awt_setPixels does not support such rasters */ 268 return -1; 269 } 270 271 return awt_setPixels(env, rasterP, mlib_ImageGetData(img)); 272 } 273 274 /*************************************************************************** 275 * External Functions * 276 ***************************************************************************/ 277 JNIEXPORT jint JNICALL 278 Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this, 279 jobject jsrc, jobject jdst, 280 jobject jkernel, jint edgeHint) 281 { 282 void *sdata, *ddata; 283 mlib_image *src; 284 mlib_image *dst; 285 int i, scale; 286 mlib_d64 *dkern; 287 mlib_s32 *kdata; 288 int klen; 289 float kmax; 290 mlib_s32 cmask; 291 mlib_status status; 292 int retStatus = 1; 293 float *kern; 294 BufImageS_t *srcImageP, *dstImageP; 295 jobject jdata; 296 int kwidth; 297 int kheight; 298 int w, h; 299 int x, y; 300 mlibHintS_t hint; 301 int nbands; 302 303 /* This function requires a lot of local refs ??? Is 64 enough ??? */ 304 if ((*env)->EnsureLocalCapacity(env, 64) < 0) 305 return 0; 306 307 if (s_nomlib) return 0; 308 if (s_timeIt) (*start_timer)(3600); 309 310 kwidth = (*env)->GetIntField(env, jkernel, g_KernelWidthID); 311 kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID); 312 jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID); 313 klen = (*env)->GetArrayLength(env, jdata); 314 kern = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL); 315 if (kern == NULL) { 316 /* out of memory exception already thrown */ 317 return 0; 318 } 319 320 if ((kwidth&0x1) == 0) { 321 /* Kernel has even width */ 322 w = kwidth+1; 323 } 324 else { 325 w = kwidth; 326 } 327 if ((kheight&0x1) == 0) { 328 /* Kernel has even height */ 329 h = kheight+1; 330 } 331 else { 332 h = kheight; 333 } 334 335 dkern = NULL; 336 if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) { 337 dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64)); 338 } 339 if (dkern == NULL) { 340 (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT); 341 return 0; 342 } 343 344 /* Need to flip and find max value of the kernel. 345 * Also, save the kernel values as mlib_d64 values. 346 * The flip is to operate correctly with medialib, 347 * which doesn't do the mathemetically correct thing, 348 * i.e. it doesn't rotate the kernel by 180 degrees. 349 * REMIND: This should perhaps be done at the Java 350 * level by ConvolveOp. 351 * REMIND: Should the max test be looking at absolute 352 * values? 353 * REMIND: What if klen != kheight * kwidth? 354 */ 355 kmax = kern[klen-1]; 356 i = klen-1; 357 for (y=0; y < kheight; y++) { 358 for (x=0; x < kwidth; x++, i--) { 359 dkern[y*w+x] = (mlib_d64) kern[i]; 360 if (kern[i] > kmax) { 361 kmax = kern[i]; 362 } 363 } 364 } 365 366 (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT); 367 368 if (kmax > 1<<16) { 369 /* We can only handle 16 bit max */ 370 free(dkern); 371 return 0; 372 } 373 374 375 /* Parse the source image */ 376 if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) { 377 /* Can't handle any custom images */ 378 free(dkern); 379 return 0; 380 } 381 382 /* Parse the destination image */ 383 if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) { 384 /* Can't handle any custom images */ 385 awt_freeParsedImage(srcImageP, TRUE); 386 free(dkern); 387 return 0; 388 } 389 390 nbands = setImageHints(env, srcImageP, dstImageP, TRUE, TRUE, 391 FALSE, &hint); 392 if (nbands < 1) { 393 /* Can't handle any custom images */ 394 awt_freeParsedImage(srcImageP, TRUE); 395 awt_freeParsedImage(dstImageP, TRUE); 396 free(dkern); 397 return 0; 398 } 399 /* Allocate the arrays */ 400 if (allocateArray(env, srcImageP, &src, &sdata, TRUE, 401 hint.cvtSrcToDefault, hint.addAlpha) < 0) { 402 /* Must be some problem */ 403 awt_freeParsedImage(srcImageP, TRUE); 404 awt_freeParsedImage(dstImageP, TRUE); 405 free(dkern); 406 return 0; 407 } 408 if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, 409 hint.cvtToDst, FALSE) < 0) { 410 /* Must be some problem */ 411 freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL); 412 awt_freeParsedImage(srcImageP, TRUE); 413 awt_freeParsedImage(dstImageP, TRUE); 414 free(dkern); 415 return 0; 416 } 417 418 kdata = NULL; 419 if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) { 420 kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32)); 421 } 422 if (kdata == NULL) { 423 freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata); 424 awt_freeParsedImage(srcImageP, TRUE); 425 awt_freeParsedImage(dstImageP, TRUE); 426 free(dkern); 427 return 0; 428 } 429 430 if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h, 431 mlib_ImageGetType(src)) != MLIB_SUCCESS) { 432 freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata); 433 awt_freeParsedImage(srcImageP, TRUE); 434 awt_freeParsedImage(dstImageP, TRUE); 435 free(dkern); 436 free(kdata); 437 return 0; 438 } 439 440 if (s_printIt) { 441 fprintf(stderr, "Orig Kernel(len=%d):\n",klen); 442 for (y=kheight-1; y >= 0; y--) { 443 for (x=kwidth-1; x >= 0; x--) { 444 fprintf(stderr, "%g ", dkern[y*w+x]); 445 } 446 fprintf(stderr, "\n"); 447 } 448 fprintf(stderr, "New Kernel(scale=%d):\n", scale); 449 for (y=kheight-1; y >= 0; y--) { 450 for (x=kwidth-1; x >= 0; x--) { 451 fprintf(stderr, "%d ", kdata[y*w+x]); 452 } 453 fprintf(stderr, "\n"); 454 } 455 } 456 457 cmask = (1<<src->channels)-1; 458 status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h, 459 (w-1)/2, (h-1)/2, scale, cmask, 460 getMlibEdgeHint(edgeHint)); 461 462 if (status != MLIB_SUCCESS) { 463 printMedialibError(status); 464 retStatus = 0; 465 } 466 467 if (s_printIt) { 468 unsigned int *dP; 469 if (s_startOff != 0) { 470 printf("Starting at %d\n", s_startOff); 471 } 472 if (sdata == NULL) { 473 dP = (unsigned int *) mlib_ImageGetData(src); 474 } 475 else { 476 dP = (unsigned int *) sdata; 477 } 478 printf("src is\n"); 479 for (i=0; i < 20; i++) { 480 printf("%x ",dP[s_startOff+i]); 481 } 482 printf("\n"); 483 if (ddata == NULL) { 484 dP = (unsigned int *)mlib_ImageGetData(dst); 485 } 486 else { 487 dP = (unsigned int *) ddata; 488 } 489 printf("dst is \n"); 490 for (i=0; i < 20; i++) { 491 printf("%x ",dP[s_startOff+i]); 492 } 493 printf("\n"); 494 } 495 496 /* Means that we couldn't write directly into the destination buffer */ 497 if (ddata == NULL) { 498 499 /* Need to store it back into the array */ 500 if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) { 501 /* Error */ 502 retStatus = 0; 503 } 504 } 505 506 /* Release the pinned memory */ 507 freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata); 508 awt_freeParsedImage(srcImageP, TRUE); 509 awt_freeParsedImage(dstImageP, TRUE); 510 free(dkern); 511 free(kdata); 512 513 if (s_timeIt) (*stop_timer)(3600, 1); 514 515 return retStatus; 516 } 517 518 JNIEXPORT jint JNICALL 519 Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this, 520 jobject jsrc, jobject jdst, 521 jobject jkernel, jint edgeHint) 522 { 523 mlib_image *src; 524 mlib_image *dst; 525 int i, scale; 526 mlib_d64 *dkern; 527 mlib_s32 *kdata; 528 int klen; 529 float kmax; 530 int retStatus = 1; 531 mlib_status status; 532 mlib_s32 cmask; 533 void *sdata; 534 void *ddata; 535 RasterS_t *srcRasterP; 536 RasterS_t *dstRasterP; 537 int kwidth; 538 int kheight; 539 int w, h; 540 int x, y; 541 jobject jdata; 542 float *kern; 543 544 /* This function requires a lot of local refs ??? Is 64 enough ??? */ 545 if ((*env)->EnsureLocalCapacity(env, 64) < 0) 546 return 0; 547 548 if (s_nomlib) return 0; 549 if (s_timeIt) (*start_timer)(3600); 550 551 kwidth = (*env)->GetIntField(env, jkernel, g_KernelWidthID); 552 kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID); 553 jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID); 554 klen = (*env)->GetArrayLength(env, jdata); 555 kern = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL); 556 if (kern == NULL) { 557 /* out of memory exception already thrown */ 558 return 0; 559 } 560 561 if ((kwidth&0x1) == 0) { 562 /* Kernel has even width */ 563 w = kwidth+1; 564 } 565 else { 566 w = kwidth; 567 } 568 if ((kheight&0x1) == 0) { 569 /* Kernel has even height */ 570 h = kheight+1; 571 } 572 else { 573 h = kheight; 574 } 575 576 dkern = NULL; 577 if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) { 578 dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64)); 579 } 580 if (dkern == NULL) { 581 (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT); 582 return 0; 583 } 584 585 /* Need to flip and find max value of the kernel. 586 * Also, save the kernel values as mlib_d64 values. 587 * The flip is to operate correctly with medialib, 588 * which doesn't do the mathemetically correct thing, 589 * i.e. it doesn't rotate the kernel by 180 degrees. 590 * REMIND: This should perhaps be done at the Java 591 * level by ConvolveOp. 592 * REMIND: Should the max test be looking at absolute 593 * values? 594 * REMIND: What if klen != kheight * kwidth? 595 */ 596 kmax = kern[klen-1]; 597 i = klen-1; 598 for (y=0; y < kheight; y++) { 599 for (x=0; x < kwidth; x++, i--) { 600 dkern[y*w+x] = (mlib_d64) kern[i]; 601 if (kern[i] > kmax) { 602 kmax = kern[i]; 603 } 604 } 605 } 606 607 (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT); 608 609 if (kmax > 1<<16) { 610 /* We can only handle 16 bit max */ 611 free(dkern); 612 return 0; 613 } 614 615 /* Parse the source image */ 616 if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { 617 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 618 free(dkern); 619 return -1; 620 } 621 622 if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { 623 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 624 free(srcRasterP); 625 free(dkern); 626 return -1; 627 } 628 629 /* Parse the source raster */ 630 if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) { 631 /* Can't handle any custom rasters */ 632 free(srcRasterP); 633 free(dstRasterP); 634 free(dkern); 635 return 0; 636 } 637 638 /* Parse the destination raster */ 639 if (awt_parseRaster(env, jdst, dstRasterP) <= 0) { 640 /* Can't handle any custom images */ 641 awt_freeParsedRaster(srcRasterP, TRUE); 642 free(dstRasterP); 643 free(dkern); 644 return 0; 645 } 646 647 /* Allocate the arrays */ 648 if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) { 649 /* Must be some problem */ 650 awt_freeParsedRaster(srcRasterP, TRUE); 651 awt_freeParsedRaster(dstRasterP, TRUE); 652 free(dkern); 653 return 0; 654 } 655 if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) { 656 /* Must be some problem */ 657 freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL); 658 awt_freeParsedRaster(srcRasterP, TRUE); 659 awt_freeParsedRaster(dstRasterP, TRUE); 660 free(dkern); 661 return 0; 662 } 663 664 kdata = NULL; 665 if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) { 666 kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32)); 667 } 668 if (kdata == NULL) { 669 freeDataArray(env, srcRasterP->jdata, src, sdata, 670 dstRasterP->jdata, dst, ddata); 671 awt_freeParsedRaster(srcRasterP, TRUE); 672 awt_freeParsedRaster(dstRasterP, TRUE); 673 free(dkern); 674 return 0; 675 } 676 677 if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h, 678 mlib_ImageGetType(src)) != MLIB_SUCCESS) { 679 freeDataArray(env, srcRasterP->jdata, src, sdata, 680 dstRasterP->jdata, dst, ddata); 681 awt_freeParsedRaster(srcRasterP, TRUE); 682 awt_freeParsedRaster(dstRasterP, TRUE); 683 free(dkern); 684 free(kdata); 685 return 0; 686 } 687 688 if (s_printIt) { 689 fprintf(stderr, "Orig Kernel(len=%d):\n",klen); 690 for (y=kheight-1; y >= 0; y--) { 691 for (x=kwidth-1; x >= 0; x--) { 692 fprintf(stderr, "%g ", dkern[y*w+x]); 693 } 694 fprintf(stderr, "\n"); 695 } 696 fprintf(stderr, "New Kernel(scale=%d):\n", scale); 697 for (y=kheight-1; y >= 0; y--) { 698 for (x=kwidth-1; x >= 0; x--) { 699 fprintf(stderr, "%d ", kdata[y*w+x]); 700 } 701 fprintf(stderr, "\n"); 702 } 703 } 704 705 cmask = (1<<src->channels)-1; 706 status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h, 707 (w-1)/2, (h-1)/2, scale, cmask, 708 getMlibEdgeHint(edgeHint)); 709 710 if (status != MLIB_SUCCESS) { 711 printMedialibError(status); 712 retStatus = 0; 713 } 714 715 if (s_printIt) { 716 unsigned int *dP; 717 if (s_startOff != 0) { 718 printf("Starting at %d\n", s_startOff); 719 } 720 if (sdata == NULL) { 721 dP = (unsigned int *) mlib_ImageGetData(src); 722 } 723 else { 724 dP = (unsigned int *) sdata; 725 } 726 printf("src is\n"); 727 for (i=0; i < 20; i++) { 728 printf("%x ",dP[s_startOff+i]); 729 } 730 printf("\n"); 731 if (ddata == NULL) { 732 dP = (unsigned int *)mlib_ImageGetData(dst); 733 } 734 else { 735 dP = (unsigned int *) ddata; 736 } 737 printf("dst is\n"); 738 for (i=0; i < 20; i++) { 739 printf("%x ",dP[s_startOff+i]); 740 } 741 printf("\n"); 742 } 743 744 /* Means that we couldn't write directly into the destination buffer */ 745 if (ddata == NULL) { 746 if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) { 747 retStatus = setPixelsFormMlibImage(env, dstRasterP, dst); 748 } 749 } 750 751 /* Release the pinned memory */ 752 freeDataArray(env, srcRasterP->jdata, src, sdata, 753 dstRasterP->jdata, dst, ddata); 754 awt_freeParsedRaster(srcRasterP, TRUE); 755 awt_freeParsedRaster(dstRasterP, TRUE); 756 free(dkern); 757 free(kdata); 758 759 if (s_timeIt) (*stop_timer)(3600,1); 760 761 return retStatus; 762 } 763 764 765 JNIEXPORT jint JNICALL 766 Java_sun_awt_image_ImagingLib_transformBI(JNIEnv *env, jobject this, 767 jobject jsrc, 768 jobject jdst, 769 jdoubleArray jmatrix, 770 jint interpType) 771 { 772 mlib_image *src; 773 mlib_image *dst; 774 int i; 775 int j = 0; 776 int retStatus = 1; 777 mlib_status status; 778 double *matrix; 779 mlib_d64 mtx[6]; 780 void *sdata; 781 void *ddata; 782 BufImageS_t *srcImageP; 783 BufImageS_t *dstImageP; 784 mlib_filter filter; 785 mlibHintS_t hint; 786 unsigned int *dP; 787 int useIndexed; 788 int nbands; 789 790 /* This function requires a lot of local refs ??? Is 64 enough ??? */ 791 if ((*env)->EnsureLocalCapacity(env, 64) < 0) 792 return 0; 793 794 if (s_nomlib) return 0; 795 if (s_timeIt) { 796 (*start_timer)(3600); 797 } 798 799 switch(interpType) { 800 case java_awt_image_AffineTransformOp_TYPE_BILINEAR: 801 filter = MLIB_BILINEAR; 802 break; 803 case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR: 804 filter = MLIB_NEAREST; 805 break; 806 case java_awt_image_AffineTransformOp_TYPE_BICUBIC: 807 filter = MLIB_BICUBIC; 808 break; 809 default: 810 JNU_ThrowInternalError(env, "Unknown interpolation type"); 811 return -1; 812 } 813 814 if ((*env)->GetArrayLength(env, jmatrix) < 6) { 815 /* 816 * Very unlikely, however we should check for this: 817 * if given matrix array is too short, we can't handle it 818 */ 819 return 0; 820 } 821 822 matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL); 823 if (matrix == NULL) { 824 /* out of memory error already thrown */ 825 return 0; 826 } 827 828 /* Check for invalid double value in transformation matrix */ 829 for (j = 0; j < 6; j++) { 830 831 if (!(IS_FINITE(matrix[j]))) { 832 (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT); 833 return 0; 834 } 835 } 836 837 if (s_printIt) { 838 printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1], 839 matrix[2], matrix[3], matrix[4], matrix[5]); 840 } 841 842 mtx[0] = matrix[0]; 843 mtx[1] = matrix[2]; 844 mtx[2] = matrix[4]; 845 mtx[3] = matrix[1]; 846 mtx[4] = matrix[3]; 847 mtx[5] = matrix[5]; 848 849 (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT); 850 851 /* Parse the source image */ 852 if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) { 853 /* Can't handle any custom images */ 854 return 0; 855 } 856 857 /* Parse the destination image */ 858 if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) { 859 /* Can't handle any custom images */ 860 awt_freeParsedImage(srcImageP, TRUE); 861 return 0; 862 } 863 864 /* REMIND!! Can't assume that it is the same LUT!! */ 865 /* Fix 4213160, 4184283 */ 866 useIndexed = (srcImageP->cmodel.cmType == INDEX_CM_TYPE && 867 dstImageP->cmodel.cmType == INDEX_CM_TYPE && 868 srcImageP->raster.rasterType == dstImageP->raster.rasterType && 869 srcImageP->raster.rasterType == COMPONENT_RASTER_TYPE); 870 871 nbands = setImageHints(env, srcImageP, dstImageP, !useIndexed, TRUE, 872 FALSE, &hint); 873 if (nbands < 1) { 874 /* Can't handle any custom images */ 875 awt_freeParsedImage(srcImageP, TRUE); 876 awt_freeParsedImage(dstImageP, TRUE); 877 return 0; 878 } 879 880 /* Allocate the arrays */ 881 if (allocateArray(env, srcImageP, &src, &sdata, TRUE, 882 hint.cvtSrcToDefault, hint.addAlpha) < 0) { 883 /* Must be some problem */ 884 awt_freeParsedImage(srcImageP, TRUE); 885 awt_freeParsedImage(dstImageP, TRUE); 886 return 0; 887 } 888 if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, 889 hint.cvtToDst, FALSE) < 0) { 890 /* Must be some problem */ 891 freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL); 892 awt_freeParsedImage(srcImageP, TRUE); 893 awt_freeParsedImage(dstImageP, TRUE); 894 return 0; 895 } 896 #if 0 897 fprintf(stderr,"Src----------------\n"); 898 fprintf(stderr,"Type : %d\n",src->type); 899 fprintf(stderr,"Channels: %d\n",src->channels); 900 fprintf(stderr,"Width : %d\n",src->width); 901 fprintf(stderr,"Height : %d\n",src->height); 902 fprintf(stderr,"Stride : %d\n",src->stride); 903 fprintf(stderr,"Flags : %d\n",src->flags); 904 905 fprintf(stderr,"Dst----------------\n"); 906 fprintf(stderr,"Type : %d\n",dst->type); 907 fprintf(stderr,"Channels: %d\n",dst->channels); 908 fprintf(stderr,"Width : %d\n",dst->width); 909 fprintf(stderr,"Height : %d\n",dst->height); 910 fprintf(stderr,"Stride : %d\n",dst->stride); 911 fprintf(stderr,"Flags : %d\n",dst->flags); 912 #endif 913 914 if (dstImageP->cmodel.cmType == INDEX_CM_TYPE) { 915 /* Need to clear the destination to the transparent pixel */ 916 unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst); 917 918 memset(cP, dstImageP->cmodel.transIdx, 919 mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst)); 920 } 921 /* Perform the transformation */ 922 if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter, 923 MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS)) 924 { 925 printMedialibError(status); 926 freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata); 927 awt_freeParsedImage(srcImageP, TRUE); 928 awt_freeParsedImage(dstImageP, TRUE); 929 930 return 0; 931 } 932 933 if (s_printIt) { 934 if (sdata == NULL) { 935 dP = (unsigned int *) mlib_ImageGetData(src); 936 } 937 else { 938 dP = (unsigned int *) sdata; 939 } 940 printf("src is\n"); 941 for (i=0; i < 20; i++) { 942 printf("%x ",dP[i]); 943 } 944 printf("\n"); 945 if (ddata == NULL) { 946 dP = (unsigned int *)mlib_ImageGetData(dst); 947 } 948 else { 949 dP = (unsigned int *) ddata; 950 } 951 printf("dst is\n"); 952 for (i=0; i < 20; i++) { 953 printf("%x ",dP[i]); 954 } 955 printf("\n"); 956 } 957 958 /* Means that we couldn't write directly into the destination buffer */ 959 if (ddata == NULL) { 960 freeDataArray(env, srcImageP->raster.jdata, src, sdata, 961 NULL, NULL, NULL); 962 /* Need to store it back into the array */ 963 if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) { 964 /* Error */ 965 retStatus = 0; 966 } 967 freeDataArray(env, NULL, NULL, NULL, dstImageP->raster.jdata, 968 dst, ddata); 969 } 970 else { 971 /* Release the pinned memory */ 972 freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata); 973 } 974 975 awt_freeParsedImage(srcImageP, TRUE); 976 awt_freeParsedImage(dstImageP, TRUE); 977 978 if (s_timeIt) (*stop_timer)(3600,1); 979 980 return retStatus; 981 } 982 983 JNIEXPORT jint JNICALL 984 Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv *env, jobject this, 985 jobject jsrc, 986 jobject jdst, 987 jdoubleArray jmatrix, 988 jint interpType) 989 { 990 mlib_image *src; 991 mlib_image *dst; 992 int i; 993 int j = 0; 994 int retStatus = 1; 995 mlib_status status; 996 double *matrix; 997 mlib_d64 mtx[6]; 998 void *sdata; 999 void *ddata; 1000 RasterS_t *srcRasterP; 1001 RasterS_t *dstRasterP; 1002 mlib_filter filter; 1003 unsigned int *dP; 1004 1005 /* This function requires a lot of local refs ??? Is 64 enough ??? */ 1006 if ((*env)->EnsureLocalCapacity(env, 64) < 0) 1007 return 0; 1008 1009 if (s_nomlib) return 0; 1010 if (s_timeIt) { 1011 (*start_timer)(3600); 1012 } 1013 1014 switch(interpType) { 1015 case java_awt_image_AffineTransformOp_TYPE_BILINEAR: 1016 filter = MLIB_BILINEAR; 1017 break; 1018 case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR: 1019 filter = MLIB_NEAREST; 1020 break; 1021 case java_awt_image_AffineTransformOp_TYPE_BICUBIC: 1022 filter = MLIB_BICUBIC; 1023 break; 1024 default: 1025 JNU_ThrowInternalError(env, "Unknown interpolation type"); 1026 return -1; 1027 } 1028 1029 if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { 1030 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 1031 return -1; 1032 } 1033 1034 if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { 1035 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 1036 free(srcRasterP); 1037 return -1; 1038 } 1039 1040 if ((*env)->GetArrayLength(env, jmatrix) < 6) { 1041 /* 1042 * Very unlikely, however we should check for this: 1043 * if given matrix array is too short, we can't handle it. 1044 */ 1045 free(srcRasterP); 1046 free(dstRasterP); 1047 return 0; 1048 } 1049 1050 matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL); 1051 if (matrix == NULL) { 1052 /* out of memory error already thrown */ 1053 free(srcRasterP); 1054 free(dstRasterP); 1055 return 0; 1056 } 1057 1058 /* Check for invalid double value in transformation matrix */ 1059 for (j = 0; j < 6; j++) { 1060 1061 if (!(IS_FINITE(matrix[j]))) { 1062 (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT); 1063 free(srcRasterP); 1064 free(dstRasterP); 1065 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 1116 fprintf(stderr,"Src----------------\n"); 1117 fprintf(stderr,"Type : %d\n",src->type); 1118 fprintf(stderr,"Channels: %d\n",src->channels); 1119 fprintf(stderr,"Width : %d\n",src->width); 1120 fprintf(stderr,"Height : %d\n",src->height); 1121 fprintf(stderr,"Stride : %d\n",src->stride); 1122 fprintf(stderr,"Flags : %d\n",src->flags); 1123 1124 fprintf(stderr,"Dst----------------\n"); 1125 fprintf(stderr,"Type : %d\n",dst->type); 1126 fprintf(stderr,"Channels: %d\n",dst->channels); 1127 fprintf(stderr,"Width : %d\n",dst->width); 1128 fprintf(stderr,"Height : %d\n",dst->height); 1129 fprintf(stderr,"Stride : %d\n",dst->stride); 1130 fprintf(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 1194 typedef 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 1208 static 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 1304 JNIEXPORT jint JNICALL 1305 Java_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 1537 JNIEXPORT jint JNICALL 1538 Java_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 1771 JNIEXPORT jboolean JNICALL 1772 Java_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? */ 1805 static 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 1847 static int 1848 setImageHints(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 2020 static int 2021 expandPacked(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 2062 static int 2063 cvtCustomToDefault(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 2128 static int 2129 cvtDefaultToCustom(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 2192 static int 2193 allocateArray(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 2358 static int 2359 allocateRasterArray(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 2577 static void 2578 freeArray(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 } 2586 static void 2587 freeDataArray(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 2648 static int 2649 storeImageArray(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 2730 static int 2731 storeRasterArray(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 2757 static int 2758 storeICMarray(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 2839 static 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 */ 2905 static 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 */ 2992 static 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 */ 3086 static 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 */ 3180 static 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*/ 3283 static 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*/ 3374 static 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 */ 3472 static 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 */ 3548 static 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*/ 3624 static 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 */ 3701 static 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 */ 3799 static 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*/ 3896 static 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 4003 static int 4004 colorMatch(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 }