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(height, rasterP->scanlineStride, 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 height * 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(height, rasterP->scanlineStride))) 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 height * rasterP->scanlineStride > dataSize - offset) 2459 { 2460 // raster data buffer is too short 2461 return -1; 2462 } 2463 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata, 2464 NULL); 2465 if (dataP == NULL) { 2466 return -1; 2467 } 2468 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, rasterP->numBands, 2469 width, height, 2470 rasterP->scanlineStride, 2471 (unsigned char *)dataP + offset); 2472 *dataPP = dataP; 2473 return 0; 2474 case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES: 2475 if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) && 2476 SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) && 2477 SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 2))) 2478 { 2479 return -1; 2480 } 2481 offset = rasterP->chanOffsets[0] * 2; 2482 dataSize = 2 * (*env)->GetArrayLength(env, rasterP->jdata); 2483 2484 if (offset < 0 || offset >= dataSize || 2485 width * rasterP->numBands > rasterP->scanlineStride || 2486 height * rasterP->scanlineStride * 2 > dataSize - offset) 2487 { 2488 // raster data buffer is too short 2489 return -1; 2490 } 2491 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata, 2492 NULL); 2493 if (dataP == NULL) { 2494 return -1; 2495 } 2496 *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT, 2497 rasterP->numBands, 2498 width, height, 2499 rasterP->scanlineStride*2, 2500 (unsigned char *)dataP + offset); 2501 *dataPP = dataP; 2502 return 0; 2503 2504 case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES: 2505 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, 2506 width, height); 2507 if (*mlibImagePP == NULL) { 2508 return -1; 2509 } 2510 if (!isSrc) return 0; 2511 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); 2512 return expandPackedBCR(env, rasterP, -1, cDataP); 2513 2514 case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES: 2515 if (rasterP->sppsm.maxBitSize <= 8) { 2516 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, 2517 width, height); 2518 if (*mlibImagePP == NULL) { 2519 return -1; 2520 } 2521 if (!isSrc) return 0; 2522 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); 2523 return expandPackedSCR(env, rasterP, -1, cDataP); 2524 } 2525 break; 2526 case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES: 2527 if (rasterP->sppsm.maxBitSize <= 8) { 2528 *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, 2529 width, height); 2530 if (*mlibImagePP == NULL) { 2531 return -1; 2532 } 2533 if (!isSrc) return 0; 2534 cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); 2535 return expandPackedICR(env, rasterP, -1, cDataP); 2536 } 2537 break; 2538 } 2539 2540 /* Just expand it right now */ 2541 switch (rasterP->dataType) { 2542 case BYTE_DATA_TYPE: 2543 if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, 2544 width, height)) == NULL) { 2545 return -1; 2546 } 2547 if (isSrc) { 2548 if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) { 2549 (*sMlibSysFns.deleteImageFP)(*mlibImagePP); 2550 return -1; 2551 } 2552 } 2553 break; 2554 2555 case SHORT_DATA_TYPE: 2556 if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_SHORT, 2557 rasterP->numBands, 2558 width, height)) == NULL) { 2559 return -1; 2560 } 2561 if (isSrc) { 2562 if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) { 2563 (*sMlibSysFns.deleteImageFP)(*mlibImagePP); 2564 return -1; 2565 } 2566 } 2567 break; 2568 2569 default: 2570 return -1; 2571 } 2572 return 0; 2573 } 2574 2575 static void 2576 freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP, 2577 void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP, 2578 void *dstdataP) { 2579 jobject srcJdata = (srcimageP != NULL ? srcimageP->raster.jdata : NULL); 2580 jobject dstJdata = (dstimageP != NULL ? dstimageP->raster.jdata : NULL); 2581 freeDataArray(env, srcJdata, srcmlibImP, srcdataP, 2582 dstJdata, dstmlibImP, dstdataP); 2583 } 2584 static void 2585 freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP, 2586 void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP, 2587 void *dstdataP) 2588 { 2589 /* Free the medialib image */ 2590 if (srcmlibImP) { 2591 (*sMlibSysFns.deleteImageFP)(srcmlibImP); 2592 } 2593 2594 /* Release the array */ 2595 if (srcdataP) { 2596 (*env)->ReleasePrimitiveArrayCritical(env, srcJdata, 2597 srcdataP, JNI_ABORT); 2598 } 2599 2600 /* Free the medialib image */ 2601 if (dstmlibImP) { 2602 (*sMlibSysFns.deleteImageFP)(dstmlibImP); 2603 } 2604 2605 /* Release the array */ 2606 if (dstdataP) { 2607 (*env)->ReleasePrimitiveArrayCritical(env, dstJdata, 2608 dstdataP, 0); 2609 } 2610 } 2611 2612 #define ERR_BAD_IMAGE_LAYOUT (-2) 2613 2614 #define CHECK_DST_ARRAY(start_offset, elements_per_scan, elements_per_pixel) \ 2615 do { \ 2616 int offset = (start_offset); \ 2617 int lastScanOffset; \ 2618 \ 2619 if (!SAFE_TO_MULT((elements_per_scan), \ 2620 (rasterP->height - 1))) \ 2621 { \ 2622 return ERR_BAD_IMAGE_LAYOUT; \ 2623 } \ 2624 lastScanOffset = (elements_per_scan) * (rasterP->height - 1); \ 2625 \ 2626 if (!SAFE_TO_ADD(offset, lastScanOffset)) { \ 2627 return ERR_BAD_IMAGE_LAYOUT; \ 2628 } \ 2629 lastScanOffset += offset; \ 2630 \ 2631 if (!SAFE_TO_MULT((elements_per_pixel), rasterP->width)) { \ 2632 return ERR_BAD_IMAGE_LAYOUT; \ 2633 } \ 2634 offset = (elements_per_pixel) * rasterP->width; \ 2635 \ 2636 if (!SAFE_TO_ADD(offset, lastScanOffset)) { \ 2637 return ERR_BAD_IMAGE_LAYOUT; \ 2638 } \ 2639 lastScanOffset += offset; \ 2640 \ 2641 if (dataArrayLength < lastScanOffset) { \ 2642 return ERR_BAD_IMAGE_LAYOUT; \ 2643 } \ 2644 } while(0); \ 2645 2646 static int 2647 storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, 2648 mlib_image *mlibImP) { 2649 int mStride; 2650 unsigned char *cmDataP, *dataP, *cDataP; 2651 HintS_t *hintP = &dstP->hints; 2652 RasterS_t *rasterP = &dstP->raster; 2653 jsize dataArrayLength = (*env)->GetArrayLength(env, rasterP->jdata); 2654 int y; 2655 2656 /* REMIND: Store mlib data type? */ 2657 2658 /* Check if it is an IndexColorModel */ 2659 if (dstP->cmodel.cmType == INDEX_CM_TYPE) { 2660 if (dstP->raster.rasterType == COMPONENT_RASTER_TYPE) { 2661 return storeICMarray(env, srcP, dstP, mlibImP); 2662 } 2663 else { 2664 /* Packed or some other custom raster */ 2665 cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP); 2666 return cvtDefaultToCustom(env, dstP, -1, cmDataP); 2667 } 2668 } 2669 2670 if (hintP->packing == BYTE_INTERLEAVED) { 2671 /* Write it back to the destination */ 2672 if (rasterP->dataType != BYTE_DATA_TYPE) { 2673 /* We are working with a raster which was marked 2674 as a byte interleaved due to performance reasons. 2675 So, we have to convert the length of the data 2676 array to bytes as well. 2677 */ 2678 if (!SAFE_TO_MULT(rasterP->dataSize, dataArrayLength)) { 2679 return ERR_BAD_IMAGE_LAYOUT; 2680 } 2681 dataArrayLength *= rasterP->dataSize; 2682 } 2683 2684 CHECK_DST_ARRAY(hintP->dataOffset, hintP->sStride, hintP->numChans); 2685 cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP); 2686 mStride = mlib_ImageGetStride(mlibImP); 2687 dataP = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env, 2688 rasterP->jdata, NULL); 2689 if (dataP == NULL) return 0; 2690 cDataP = dataP + hintP->dataOffset; 2691 for (y=0; y < rasterP->height; 2692 y++, cmDataP += mStride, cDataP += hintP->sStride) 2693 { 2694 memcpy(cDataP, cmDataP, rasterP->width*hintP->numChans); 2695 } 2696 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP, 2697 JNI_ABORT); 2698 } 2699 else if (dstP->cmodel.cmType == DIRECT_CM_TYPE) { 2700 /* Just need to move bits */ 2701 if (mlibImP->type == MLIB_BYTE) { 2702 if (dstP->hints.packing == PACKED_BYTE_INTER) { 2703 return setPackedBCRdefault(env, rasterP, -1, 2704 (unsigned char *) mlibImP->data, 2705 dstP->cmodel.supportsAlpha); 2706 } else if (dstP->hints.packing == PACKED_SHORT_INTER) { 2707 return setPackedSCRdefault(env, rasterP, -1, 2708 (unsigned char *) mlibImP->data, 2709 dstP->cmodel.supportsAlpha); 2710 } else if (dstP->hints.packing == PACKED_INT_INTER) { 2711 return setPackedICRdefault(env, rasterP, -1, 2712 (unsigned char *) mlibImP->data, 2713 dstP->cmodel.supportsAlpha); 2714 } 2715 } 2716 else if (mlibImP->type == MLIB_SHORT) { 2717 return setPixelsFormMlibImage(env, rasterP, mlibImP); 2718 } 2719 } 2720 else { 2721 return cvtDefaultToCustom(env, dstP, -1, 2722 (unsigned char *)mlibImP->data); 2723 } 2724 2725 return 0; 2726 } 2727 2728 static int 2729 storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP, 2730 mlib_image *mlibImP) { 2731 unsigned char *cDataP; 2732 2733 switch(dstP->type) { 2734 case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES: 2735 cDataP = (unsigned char *) mlib_ImageGetData(mlibImP); 2736 return setPackedBCR(env, dstP, -1, cDataP); 2737 2738 case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES: 2739 if (dstP->sppsm.maxBitSize <= 8) { 2740 cDataP = (unsigned char *) mlib_ImageGetData(mlibImP); 2741 return setPackedSCR(env, dstP, -1, cDataP); 2742 } 2743 break; 2744 case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES: 2745 if (dstP->sppsm.maxBitSize <= 8) { 2746 cDataP = (unsigned char *) mlib_ImageGetData(mlibImP); 2747 return setPackedICR(env, dstP, -1, cDataP); 2748 } 2749 } 2750 2751 return -1; 2752 } 2753 2754 2755 static int 2756 storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, 2757 mlib_image *mlibImP) 2758 { 2759 int *argb; 2760 int x, y; 2761 unsigned char *dataP, *cDataP, *cP; 2762 unsigned char *sP; 2763 int aIdx, rIdx, gIdx, bIdx; 2764 ColorModelS_t *cmodelP = &dstP->cmodel; 2765 RasterS_t *rasterP = &dstP->raster; 2766 2767 /* REMIND: Only works for RGB */ 2768 if (cmodelP->csType != java_awt_color_ColorSpace_TYPE_RGB) { 2769 JNU_ThrowInternalError(env, "Writing to non-RGB images not implemented yet"); 2770 return -1; 2771 } 2772 2773 if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB || 2774 srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE || 2775 srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB) 2776 { 2777 aIdx = 0; 2778 rIdx = 1; 2779 gIdx = 2; 2780 bIdx = 3; 2781 } 2782 else if (srcP->imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR|| 2783 srcP->imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE) 2784 { 2785 aIdx = 0; 2786 rIdx = 3; 2787 gIdx = 2; 2788 bIdx = 1; 2789 } 2790 else if (srcP->imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR){ 2791 rIdx = 2; 2792 gIdx = 1; 2793 bIdx = 0; 2794 aIdx = 0; /* Ignored */ 2795 } 2796 else if (srcP->cmodel.cmType == INDEX_CM_TYPE) { 2797 rIdx = 0; 2798 gIdx = 1; 2799 bIdx = 2; 2800 aIdx = 3; /* Use supportsAlpha to see if it is really there */ 2801 } 2802 else { 2803 return -1; 2804 } 2805 2806 /* Lock down the destination raster */ 2807 dataP = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, 2808 rasterP->jdata, NULL); 2809 if (dataP == NULL) { 2810 return -1; 2811 } 2812 argb = (*env)->GetPrimitiveArrayCritical(env, cmodelP->jrgb, NULL); 2813 if (argb == NULL) { 2814 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP, 2815 JNI_ABORT); 2816 return -1; 2817 } 2818 2819 cDataP = dataP + dstP->hints.dataOffset; 2820 sP = (unsigned char *) mlib_ImageGetData(mlibImP); 2821 2822 for (y=0; y < rasterP->height; y++, cDataP += rasterP->scanlineStride) { 2823 cP = cDataP; 2824 for (x=0; x < rasterP->width; x++, cP += rasterP->pixelStride) { 2825 *cP = colorMatch(sP[rIdx], sP[gIdx], sP[bIdx], sP[aIdx], 2826 (unsigned char *)argb, cmodelP->mapSize); 2827 sP += cmodelP->numComponents; 2828 } 2829 } 2830 2831 (*env)->ReleasePrimitiveArrayCritical(env, cmodelP->jrgb, argb, JNI_ABORT); 2832 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP, 2833 JNI_ABORT); 2834 return -1; 2835 } 2836 2837 static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP) 2838 { 2839 ColorModelS_t *cmP = &imageP->cmodel; 2840 RasterS_t *rasterP = &imageP->raster; 2841 HintS_t *hintP = &imageP->hints; 2842 int *rgb; 2843 int status = 0; 2844 unsigned char *dataP, *cP; 2845 unsigned int *mP; 2846 int width = rasterP->width; 2847 int height = rasterP->height; 2848 int x, y; 2849 2850 /* Need to grab the lookup tables. Right now only bytes */ 2851 rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, cmP->jrgb, NULL); 2852 CHECK_NULL_RETURN(rgb, -1); 2853 2854 /* Interleaved with shared data */ 2855 dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, 2856 rasterP->jdata, NULL); 2857 if (dataP == NULL) { 2858 /* Release the lookup tables */ 2859 (*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb, JNI_ABORT); 2860 return -1; 2861 } 2862 2863 if (rasterP->dataType == BYTE_DATA_TYPE) { 2864 unsigned char *cDataP = ((unsigned char *)dataP) + hintP->dataOffset; 2865 2866 for (y=0; y < height; y++) { 2867 mP = mDataP; 2868 cP = cDataP; 2869 for (x=0; x < width; x++, cP += rasterP->pixelStride) { 2870 *mP++ = rgb[*cP]; 2871 } 2872 mDataP += width; 2873 cDataP += rasterP->scanlineStride; 2874 } 2875 } 2876 else if (rasterP->dataType == SHORT_DATA_TYPE) { 2877 unsigned short *sDataP, *sP; 2878 sDataP = ((unsigned short *)dataP) + hintP->channelOffset; 2879 2880 for (y=0; y < height; y++) { 2881 mP = mDataP; 2882 sP = sDataP; 2883 for (x=0; x < width; x++, sP+=rasterP->pixelStride) { 2884 *mP++ = rgb[*sP]; 2885 } 2886 mDataP += width; 2887 sDataP += rasterP->scanlineStride; 2888 } 2889 } 2890 else { 2891 /* Unknown type */ 2892 status = -1; 2893 } 2894 /* Release the lookup table data */ 2895 (*env)->ReleasePrimitiveArrayCritical(env, imageP->cmodel.jrgb, 2896 rgb, JNI_ABORT); 2897 /* Release the data array */ 2898 (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, 2899 dataP, JNI_ABORT); 2900 return status; 2901 } 2902 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */ 2903 static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component, 2904 unsigned char *outDataP) 2905 { 2906 int x, y, c; 2907 unsigned char *outP = outDataP; 2908 unsigned char *lineInP, *inP; 2909 jarray jInDataP; 2910 jint *inDataP; 2911 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 2912 2913 if (rasterP->numBands > MAX_NUMBANDS) { 2914 return -1; 2915 } 2916 2917 /* Grab data ptr, strides, offsets from raster */ 2918 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID); 2919 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0); 2920 if (inDataP == NULL) { 2921 return -1; 2922 } 2923 lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0]; 2924 2925 if (component < 0) { 2926 for (c=0; c < rasterP->numBands; c++) { 2927 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 2928 if (roff[c] < 0) { 2929 loff[c] = -roff[c]; 2930 roff[c] = 0; 2931 } 2932 else loff[c] = 0; 2933 } 2934 /* Convert the all bands */ 2935 if (rasterP->numBands < 4) { 2936 /* Need to put in alpha */ 2937 for (y=0; y < rasterP->height; y++) { 2938 inP = lineInP; 2939 for (x=0; x < rasterP->width; x++) { 2940 for (c=0; c < rasterP->numBands; c++) { 2941 *outP++ = (unsigned char) 2942 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 2943 <<loff[c]); 2944 } 2945 inP++; 2946 } 2947 lineInP += rasterP->scanlineStride; 2948 } 2949 } 2950 else { 2951 for (y=0; y < rasterP->height; y++) { 2952 inP = lineInP; 2953 for (x=0; x < rasterP->width; x++) { 2954 for (c=0; c < rasterP->numBands; c++) { 2955 *outP++ = (unsigned char) 2956 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 2957 <<loff[c]); 2958 } 2959 inP++; 2960 } 2961 lineInP += rasterP->scanlineStride; 2962 } 2963 } 2964 } 2965 else { 2966 c = component; 2967 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 2968 if (roff[0] < 0) { 2969 loff[0] = -roff[0]; 2970 roff[0] = 0; 2971 } 2972 else loff[c] = 0; 2973 for (y=0; y < rasterP->height; y++) { 2974 inP = lineInP; 2975 for (x=0; x < rasterP->width; x++) { 2976 *outP++ = (unsigned char) 2977 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]; 2978 inP++; 2979 } 2980 lineInP += rasterP->scanlineStride; 2981 } 2982 } 2983 2984 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT); 2985 2986 return 0; 2987 } 2988 2989 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */ 2990 static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP, 2991 int component, unsigned char *outDataP, 2992 int forceAlpha) 2993 { 2994 int x, y, c; 2995 unsigned char *outP = outDataP; 2996 unsigned char *lineInP, *inP; 2997 jarray jInDataP; 2998 jint *inDataP; 2999 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3000 int numBands = rasterP->numBands - (forceAlpha ? 0 : 1); 3001 int a = numBands; 3002 3003 if (rasterP->numBands > MAX_NUMBANDS) { 3004 return -1; 3005 } 3006 3007 /* Grab data ptr, strides, offsets from raster */ 3008 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID); 3009 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0); 3010 if (inDataP == NULL) { 3011 return -1; 3012 } 3013 lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0]; 3014 3015 if (component < 0) { 3016 for (c=0; c < rasterP->numBands; c++) { 3017 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3018 if (roff[c] < 0) { 3019 loff[c] = -roff[c]; 3020 roff[c] = 0; 3021 } 3022 else loff[c] = 0; 3023 } 3024 3025 /* Need to put in alpha */ 3026 if (forceAlpha) { 3027 for (y=0; y < rasterP->height; y++) { 3028 inP = lineInP; 3029 for (x=0; x < rasterP->width; x++) { 3030 *outP++ = 0xff; 3031 for (c=0; c < numBands; c++) { 3032 *outP++ = (unsigned char) 3033 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3034 <<loff[c]); 3035 } 3036 inP++; 3037 } 3038 lineInP += rasterP->scanlineStride; 3039 } 3040 } 3041 else { 3042 for (y=0; y < rasterP->height; y++) { 3043 inP = lineInP; 3044 for (x=0; x < rasterP->width; x++) { 3045 *outP++ = (unsigned char) 3046 (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a]) 3047 <<loff[a]); 3048 for (c=0; c < numBands; c++) { 3049 *outP++ = (unsigned char) 3050 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3051 <<loff[c]); 3052 } 3053 inP++; 3054 } 3055 lineInP += rasterP->scanlineStride; 3056 } 3057 } 3058 } 3059 else { 3060 c = component; 3061 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3062 if (roff[0] < 0) { 3063 loff[0] = -roff[0]; 3064 roff[0] = 0; 3065 } 3066 else loff[c] = 0; 3067 for (y=0; y < rasterP->height; y++) { 3068 inP = lineInP; 3069 for (x=0; x < rasterP->width; x++) { 3070 *outP++ = (unsigned char) 3071 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]; 3072 inP++; 3073 } 3074 lineInP += rasterP->scanlineStride; 3075 } 3076 } 3077 3078 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT); 3079 3080 return 0; 3081 } 3082 3083 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */ 3084 static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component, 3085 unsigned char *outDataP) 3086 { 3087 int x, y, c; 3088 unsigned char *outP = outDataP; 3089 unsigned short *lineInP, *inP; 3090 jarray jInDataP; 3091 jint *inDataP; 3092 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3093 3094 if (rasterP->numBands > MAX_NUMBANDS) { 3095 return -1; 3096 } 3097 3098 /* Grab data ptr, strides, offsets from raster */ 3099 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID); 3100 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0); 3101 if (inDataP == NULL) { 3102 return -1; 3103 } 3104 lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0]; 3105 3106 if (component < 0) { 3107 for (c=0; c < rasterP->numBands; c++) { 3108 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3109 if (roff[c] < 0) { 3110 loff[c] = -roff[c]; 3111 roff[c] = 0; 3112 } 3113 else loff[c] = 0; 3114 } 3115 /* Convert the all bands */ 3116 if (rasterP->numBands < 4) { 3117 /* Need to put in alpha */ 3118 for (y=0; y < rasterP->height; y++) { 3119 inP = lineInP; 3120 for (x=0; x < rasterP->width; x++) { 3121 for (c=0; c < rasterP->numBands; c++) { 3122 /* 3123 *Not correct. Might need to unpremult, 3124 * shift, etc 3125 */ 3126 *outP++ = (unsigned char) 3127 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3128 <<loff[c]); 3129 } 3130 inP++; 3131 } 3132 lineInP += rasterP->scanlineStride; 3133 } 3134 } else { 3135 for (y=0; y < rasterP->height; y++) { 3136 inP = lineInP; 3137 for (x=0; x < rasterP->width; x++) { 3138 for (c=0; c < rasterP->numBands; c++) { 3139 /* 3140 *Not correct. Might need to unpremult, 3141 * shift, etc 3142 */ 3143 *outP++ = (unsigned char) 3144 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3145 <<loff[c]); 3146 } 3147 inP++; 3148 } 3149 lineInP += rasterP->scanlineStride; 3150 } 3151 } 3152 } 3153 else { 3154 c = component; 3155 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3156 if (roff[0] < 0) { 3157 loff[0] = -roff[0]; 3158 roff[0] = 0; 3159 } 3160 else loff[c] = 0; 3161 for (y=0; y < rasterP->height; y++) { 3162 inP = lineInP; 3163 for (x=0; x < rasterP->width; x++) { 3164 *outP++ = (unsigned char) 3165 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]; 3166 inP++; 3167 } 3168 lineInP += rasterP->scanlineStride; 3169 } 3170 } 3171 3172 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT); 3173 3174 return 0; 3175 } 3176 3177 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */ 3178 static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP, 3179 int component, unsigned char *outDataP, 3180 int forceAlpha) 3181 { 3182 int x, y, c; 3183 unsigned char *outP = outDataP; 3184 unsigned short *lineInP, *inP; 3185 jarray jInDataP; 3186 jint *inDataP; 3187 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3188 int numBands = rasterP->numBands - (forceAlpha ? 0 : 1); 3189 int a = numBands; 3190 3191 if (rasterP->numBands > MAX_NUMBANDS) { 3192 return -1; 3193 } 3194 3195 /* Grab data ptr, strides, offsets from raster */ 3196 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID); 3197 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0); 3198 if (inDataP == NULL) { 3199 return -1; 3200 } 3201 lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0]; 3202 3203 if (component < 0) { 3204 for (c=0; c < rasterP->numBands; c++) { 3205 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3206 if (roff[c] < 0) { 3207 loff[c] = -roff[c]; 3208 roff[c] = 0; 3209 } 3210 else loff[c] = 0; 3211 } 3212 3213 /* Need to put in alpha */ 3214 if (forceAlpha) { 3215 for (y=0; y < rasterP->height; y++) { 3216 inP = lineInP; 3217 for (x=0; x < rasterP->width; x++) { 3218 *outP++ = 0xff; 3219 for (c=0; c < numBands; c++) { 3220 /* 3221 * Not correct. Might need to unpremult, 3222 * shift, etc 3223 */ 3224 *outP++ = (unsigned char) 3225 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3226 <<loff[c]); 3227 } 3228 inP++; 3229 } 3230 lineInP += rasterP->scanlineStride; 3231 } 3232 } 3233 else { 3234 for (y=0; y < rasterP->height; y++) { 3235 inP = lineInP; 3236 for (x=0; x < rasterP->width; x++) { 3237 *outP++ = (unsigned char) 3238 (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a]) 3239 <<loff[a]); 3240 for (c=0; c < numBands; c++) { 3241 /* 3242 * Not correct. Might need to 3243 * unpremult, shift, etc 3244 */ 3245 *outP++ = (unsigned char) 3246 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3247 <<loff[c]); 3248 } 3249 inP++; 3250 } 3251 lineInP += rasterP->scanlineStride; 3252 } 3253 } 3254 } 3255 else { 3256 c = component; 3257 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3258 if (roff[0] < 0) { 3259 loff[0] = -roff[0]; 3260 roff[0] = 0; 3261 } 3262 else loff[c] = 0; 3263 for (y=0; y < rasterP->height; y++) { 3264 inP = lineInP; 3265 for (x=0; x < rasterP->width; x++) { 3266 *outP++ = (unsigned char) 3267 ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]; 3268 inP++; 3269 } 3270 lineInP += rasterP->scanlineStride; 3271 } 3272 } 3273 3274 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT); 3275 3276 return 0; 3277 3278 } 3279 3280 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/ 3281 static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component, 3282 unsigned char *outDataP) 3283 { 3284 int x, y, c; 3285 unsigned char *outP = outDataP; 3286 unsigned int *lineInP, *inP; 3287 jarray jInDataP; 3288 jint *inDataP; 3289 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3290 3291 if (rasterP->numBands > MAX_NUMBANDS) { 3292 return -1; 3293 } 3294 3295 /* Grab data ptr, strides, offsets from raster */ 3296 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID); 3297 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0); 3298 if (inDataP == NULL) { 3299 return -1; 3300 } 3301 lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0]; 3302 3303 if (component < 0) { 3304 for (c=0; c < rasterP->numBands; c++) { 3305 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3306 if (roff[c] < 0) { 3307 loff[c] = -roff[c]; 3308 roff[c] = 0; 3309 } 3310 else loff[c] = 0; 3311 } 3312 /* Convert the all bands */ 3313 if (rasterP->numBands < 4) { 3314 for (y=0; y < rasterP->height; y++) { 3315 inP = lineInP; 3316 for (x=0; x < rasterP->width; x++) { 3317 for (c=0; c < rasterP->numBands; c++) { 3318 /* 3319 * Not correct. Might need to unpremult, 3320 * shift, etc 3321 */ 3322 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3323 <<loff[c]); 3324 } 3325 inP++; 3326 } 3327 lineInP += rasterP->scanlineStride; 3328 } 3329 } 3330 else { 3331 for (y=0; y < rasterP->height; y++) { 3332 inP = lineInP; 3333 for (x=0; x < rasterP->width; x++) { 3334 for (c=0; c < rasterP->numBands; c++) { 3335 /* 3336 * Not correct. Might need to 3337 * unpremult, shift, etc 3338 */ 3339 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3340 <<loff[c]); 3341 } 3342 inP++; 3343 } 3344 lineInP += rasterP->scanlineStride; 3345 } 3346 } 3347 } 3348 else { 3349 c = component; 3350 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3351 if (roff[0] < 0) { 3352 loff[0] = -roff[0]; 3353 roff[0] = 0; 3354 } 3355 else loff[c] = 0; 3356 for (y=0; y < rasterP->height; y++) { 3357 inP = lineInP; 3358 for (x=0; x < rasterP->width; x++) { 3359 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]); 3360 inP++; 3361 } 3362 lineInP += rasterP->scanlineStride; 3363 } 3364 } 3365 3366 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT); 3367 3368 return 0; 3369 } 3370 3371 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/ 3372 static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP, 3373 int component, unsigned char *outDataP, 3374 int forceAlpha) 3375 { 3376 int x, y, c; 3377 unsigned char *outP = outDataP; 3378 unsigned int *lineInP, *inP; 3379 jarray jInDataP; 3380 jint *inDataP; 3381 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3382 int numBands = rasterP->numBands - (forceAlpha ? 0 : 1); 3383 int a = numBands; 3384 3385 if (rasterP->numBands > MAX_NUMBANDS) { 3386 return -1; 3387 } 3388 3389 /* Grab data ptr, strides, offsets from raster */ 3390 jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID); 3391 inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0); 3392 if (inDataP == NULL) { 3393 return -1; 3394 } 3395 lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0]; 3396 3397 if (component < 0) { 3398 for (c=0; c < rasterP->numBands; c++) { 3399 roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3400 if (roff[c] < 0) { 3401 loff[c] = -roff[c]; 3402 roff[c] = 0; 3403 } 3404 else loff[c] = 0; 3405 } 3406 3407 /* Need to put in alpha */ 3408 if (forceAlpha) { 3409 for (y=0; y < rasterP->height; y++) { 3410 inP = lineInP; 3411 for (x=0; x < rasterP->width; x++) { 3412 *outP++ = 0xff; 3413 for (c=0; c < numBands; c++) { 3414 /* 3415 * Not correct. Might need to unpremult, 3416 * shift, etc 3417 */ 3418 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3419 <<loff[c]); 3420 } 3421 inP++; 3422 } 3423 lineInP += rasterP->scanlineStride; 3424 } 3425 } 3426 else { 3427 for (y=0; y < rasterP->height; y++) { 3428 inP = lineInP; 3429 for (x=0; x < rasterP->width; x++) { 3430 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a]) 3431 <<loff[a]); 3432 for (c=0; c < numBands; c++) { 3433 /* 3434 * Not correct. Might need to 3435 * unpremult, shift, etc 3436 */ 3437 *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c]) 3438 <<loff[c]); 3439 } 3440 inP++; 3441 } 3442 lineInP += rasterP->scanlineStride; 3443 } 3444 } 3445 } 3446 else { 3447 c = component; 3448 roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3449 if (roff[0] < 0) { 3450 loff[0] = -roff[0]; 3451 roff[0] = 0; 3452 } 3453 else loff[c] = 0; 3454 for (y=0; y < rasterP->height; y++) { 3455 inP = lineInP; 3456 for (x=0; x < rasterP->width; x++) { 3457 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]); 3458 inP++; 3459 } 3460 lineInP += rasterP->scanlineStride; 3461 } 3462 } 3463 3464 (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT); 3465 3466 return 0; 3467 } 3468 3469 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */ 3470 static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component, 3471 unsigned char *inDataP) 3472 { 3473 int x, y, c; 3474 unsigned char *inP = inDataP; 3475 unsigned char *lineOutP, *outP; 3476 jarray jOutDataP; 3477 jsize dataArrayLength; 3478 unsigned char *outDataP; 3479 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3480 3481 if (rasterP->numBands > MAX_NUMBANDS) { 3482 return -1; 3483 } 3484 3485 /* Grab data ptr, strides, offsets from raster */ 3486 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID); 3487 if (JNU_IsNull(env, jOutDataP)) { 3488 return -1; 3489 } 3490 3491 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP); 3492 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1); 3493 3494 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0); 3495 if (outDataP == NULL) { 3496 return -1; 3497 } 3498 lineOutP = outDataP + rasterP->chanOffsets[0]; 3499 3500 if (component < 0) { 3501 for (c=0; c < rasterP->numBands; c++) { 3502 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3503 if (loff[c] < 0) { 3504 roff[c] = -loff[c]; 3505 loff[c] = 0; 3506 } 3507 else roff[c] = 0; 3508 } 3509 /* Convert the all bands */ 3510 for (y=0; y < rasterP->height; y++) { 3511 outP = lineOutP; 3512 *outP = 0; 3513 for (x=0; x < rasterP->width; x++) { 3514 for (c=0; c < rasterP->numBands; c++, inP++) { 3515 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c]; 3516 } 3517 outP++; 3518 } 3519 lineOutP += rasterP->scanlineStride; 3520 } 3521 } 3522 else { 3523 c = component; 3524 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3525 if (loff[0] < 0) { 3526 roff[0] = -loff[0]; 3527 loff[0] = 0; 3528 } 3529 else roff[c] = 0; 3530 for (y=0; y < rasterP->height; y++) { 3531 outP = lineOutP; 3532 for (x=0; x < rasterP->width; x++, inP++) { 3533 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c]; 3534 outP++; 3535 } 3536 lineOutP += rasterP->scanlineStride; 3537 } 3538 } 3539 3540 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT); 3541 3542 return 0; 3543 } 3544 3545 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */ 3546 static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component, 3547 unsigned char *inDataP) 3548 { 3549 int x, y, c; 3550 unsigned char *inP = inDataP; 3551 unsigned short *lineOutP, *outP; 3552 jarray jOutDataP; 3553 jsize dataArrayLength; 3554 unsigned short *outDataP; 3555 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3556 3557 if (rasterP->numBands > MAX_NUMBANDS) { 3558 return -1; 3559 } 3560 3561 /* Grab data ptr, strides, offsets from raster */ 3562 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID); 3563 if (JNU_IsNull(env, jOutDataP)) { 3564 return -1; 3565 } 3566 3567 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP); 3568 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1); 3569 3570 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0); 3571 if (outDataP == NULL) { 3572 return -1; 3573 } 3574 lineOutP = outDataP + rasterP->chanOffsets[0]; 3575 3576 if (component < 0) { 3577 for (c=0; c < rasterP->numBands; c++) { 3578 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3579 if (loff[c] < 0) { 3580 roff[c] = -loff[c]; 3581 loff[c] = 0; 3582 } 3583 else roff[c] = 0; 3584 } 3585 /* Convert the all bands */ 3586 for (y=0; y < rasterP->height; y++) { 3587 outP = lineOutP; 3588 for (x=0; x < rasterP->width; x++) { 3589 for (c=0; c < rasterP->numBands; c++, inP++) { 3590 /* Not correct. Might need to unpremult, shift, etc */ 3591 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c]; 3592 } 3593 outP++; 3594 } 3595 lineOutP += rasterP->scanlineStride; 3596 } 3597 } 3598 else { 3599 c = component; 3600 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3601 if (loff[0] < 0) { 3602 roff[0] = -loff[0]; 3603 loff[0] = 0; 3604 } 3605 else roff[c] = 0; 3606 for (y=0; y < rasterP->height; y++) { 3607 outP = lineOutP; 3608 for (x=0; x < rasterP->width; x++, inP++) { 3609 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c]; 3610 outP++; 3611 } 3612 lineOutP += rasterP->scanlineStride; 3613 } 3614 } 3615 3616 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT); 3617 3618 return 0; 3619 } 3620 3621 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/ 3622 static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component, 3623 unsigned char *inDataP) 3624 { 3625 int x, y, c; 3626 unsigned char *inP = inDataP; 3627 unsigned int *lineOutP, *outP; 3628 jarray jOutDataP; 3629 jsize dataArrayLength; 3630 unsigned int *outDataP; 3631 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3632 3633 if (rasterP->numBands > MAX_NUMBANDS) { 3634 return -1; 3635 } 3636 3637 /* Grab data ptr, strides, offsets from raster */ 3638 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID); 3639 if (JNU_IsNull(env, jOutDataP)) { 3640 return -1; 3641 } 3642 3643 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP); 3644 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1); 3645 3646 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0); 3647 if (outDataP == NULL) { 3648 return -1; 3649 } 3650 lineOutP = outDataP + rasterP->chanOffsets[0]; 3651 3652 if (component < 0) { 3653 for (c=0; c < rasterP->numBands; c++) { 3654 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3655 if (loff[c] < 0) { 3656 roff[c] = -loff[c]; 3657 loff[c] = 0; 3658 } 3659 else roff[c] = 0; 3660 } 3661 /* Convert the all bands */ 3662 for (y=0; y < rasterP->height; y++) { 3663 outP = lineOutP; 3664 for (x=0; x < rasterP->width; x++) { 3665 for (c=0; c < rasterP->numBands; c++, inP++) { 3666 /* Not correct. Might need to unpremult, shift, etc */ 3667 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c]; 3668 } 3669 outP++; 3670 } 3671 lineOutP += rasterP->scanlineStride; 3672 } 3673 } 3674 else { 3675 c = component; 3676 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3677 if (loff[0] < 0) { 3678 roff[0] = -loff[0]; 3679 loff[0] = 0; 3680 } 3681 else roff[c] = 0; 3682 3683 for (y=0; y < rasterP->height; y++) { 3684 outP = lineOutP; 3685 for (x=0; x < rasterP->width; x++, inP++) { 3686 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c]; 3687 outP++; 3688 } 3689 lineOutP += rasterP->scanlineStride; 3690 } 3691 } 3692 3693 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT); 3694 3695 return 0; 3696 } 3697 3698 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */ 3699 static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP, 3700 int component, unsigned char *inDataP, 3701 int supportsAlpha) 3702 { 3703 int x, y, c; 3704 unsigned char *inP = inDataP; 3705 unsigned char *lineOutP, *outP; 3706 jarray jOutDataP; 3707 jsize dataArrayLength; 3708 unsigned char *outDataP; 3709 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3710 int a = rasterP->numBands - 1; 3711 3712 if (rasterP->numBands > MAX_NUMBANDS) { 3713 return -1; 3714 } 3715 3716 /* Grab data ptr, strides, offsets from raster */ 3717 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID); 3718 if (JNU_IsNull(env, jOutDataP)) { 3719 return -1; 3720 } 3721 3722 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP); 3723 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1); 3724 3725 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0); 3726 if (outDataP == NULL) { 3727 return -1; 3728 } 3729 lineOutP = outDataP + rasterP->chanOffsets[0]; 3730 3731 if (component < 0) { 3732 for (c=0; c < rasterP->numBands; c++) { 3733 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3734 if (loff[c] < 0) { 3735 roff[c] = -loff[c]; 3736 loff[c] = 0; 3737 } 3738 else roff[c] = 0; 3739 } 3740 /* Convert the all bands */ 3741 if (supportsAlpha) { 3742 for (y=0; y < rasterP->height; y++) { 3743 outP = lineOutP; 3744 *outP = 0; 3745 for (x=0; x < rasterP->width; x++) { 3746 *outP |= (*inP<<loff[a]>>roff[a])& 3747 rasterP->sppsm.maskArray[a]; 3748 inP++; 3749 for (c=0; c < rasterP->numBands-1; c++, inP++) { 3750 *outP |= (*inP<<loff[c]>>roff[c])& 3751 rasterP->sppsm.maskArray[c]; 3752 } 3753 outP++; 3754 } 3755 lineOutP += rasterP->scanlineStride; 3756 } 3757 } 3758 else { 3759 for (y=0; y < rasterP->height; y++) { 3760 outP = lineOutP; 3761 *outP = 0; 3762 for (x=0; x < rasterP->width; x++) { 3763 inP++; 3764 for (c=0; c < rasterP->numBands; c++, inP++) { 3765 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c]; 3766 } 3767 outP++; 3768 } 3769 lineOutP += rasterP->scanlineStride; 3770 } 3771 } 3772 } 3773 else { 3774 c = component; 3775 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3776 if (loff[0] < 0) { 3777 roff[0] = -loff[0]; 3778 loff[0] = 0; 3779 } 3780 else roff[c] = 0; 3781 for (y=0; y < rasterP->height; y++) { 3782 outP = lineOutP; 3783 for (x=0; x < rasterP->width; x++, inP++) { 3784 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c]; 3785 outP++; 3786 } 3787 lineOutP += rasterP->scanlineStride; 3788 } 3789 } 3790 3791 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT); 3792 3793 return 0; 3794 } 3795 3796 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */ 3797 static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP, 3798 int component, unsigned char *inDataP, 3799 int supportsAlpha) 3800 { 3801 int x, y, c; 3802 unsigned char *inP = inDataP; 3803 unsigned short *lineOutP, *outP; 3804 jarray jOutDataP; 3805 jsize dataArrayLength; 3806 unsigned short *outDataP; 3807 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3808 int a = rasterP->numBands - 1; 3809 3810 if (rasterP->numBands > MAX_NUMBANDS) { 3811 return -1; 3812 } 3813 3814 /* Grab data ptr, strides, offsets from raster */ 3815 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID); 3816 if (JNU_IsNull(env, jOutDataP)) { 3817 return -1; 3818 } 3819 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP); 3820 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1); 3821 3822 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0); 3823 if (outDataP == NULL) { 3824 return -1; 3825 } 3826 lineOutP = outDataP + rasterP->chanOffsets[0]; 3827 3828 if (component < 0) { 3829 for (c=0; c < rasterP->numBands; c++) { 3830 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3831 if (loff[c] < 0) { 3832 roff[c] = -loff[c]; 3833 loff[c] = 0; 3834 } 3835 else roff[c] = 0; 3836 } 3837 /* Convert the all bands */ 3838 if (supportsAlpha) { 3839 for (y=0; y < rasterP->height; y++) { 3840 outP = lineOutP; 3841 for (x=0; x < rasterP->width; x++) { 3842 *outP |= (*inP<<loff[a]>>roff[a])& 3843 rasterP->sppsm.maskArray[a]; 3844 inP++; 3845 for (c=0; c < rasterP->numBands-1; c++, inP++) { 3846 /* Not correct. Might need to unpremult, shift, etc */ 3847 *outP |= (*inP<<loff[c]>>roff[c])& 3848 rasterP->sppsm.maskArray[c]; 3849 } 3850 outP++; 3851 } 3852 lineOutP += rasterP->scanlineStride; 3853 } 3854 } 3855 else { 3856 for (y=0; y < rasterP->height; y++) { 3857 outP = lineOutP; 3858 for (x=0; x < rasterP->width; x++) { 3859 inP++; 3860 for (c=0; c < rasterP->numBands; c++, inP++) { 3861 /* Not correct. Might need to unpremult, shift, etc */ 3862 *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c]; 3863 } 3864 outP++; 3865 } 3866 lineOutP += rasterP->scanlineStride; 3867 } 3868 } 3869 } 3870 else { 3871 c = component; 3872 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3873 if (loff[0] < 0) { 3874 roff[0] = -loff[0]; 3875 loff[0] = 0; 3876 } 3877 else roff[c] = 0; 3878 for (y=0; y < rasterP->height; y++) { 3879 outP = lineOutP; 3880 for (x=0; x < rasterP->width; x++, inP++) { 3881 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c]; 3882 outP++; 3883 } 3884 lineOutP += rasterP->scanlineStride; 3885 } 3886 } 3887 3888 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT); 3889 3890 return 0; 3891 } 3892 3893 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/ 3894 static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP, 3895 int component, unsigned char *inDataP, 3896 int supportsAlpha) 3897 { 3898 int x, y, c; 3899 unsigned char *inP = inDataP; 3900 unsigned int *lineOutP, *outP; 3901 jarray jOutDataP; 3902 jsize dataArrayLength; 3903 unsigned int *outDataP; 3904 int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS]; 3905 int a = rasterP->numBands - 1; 3906 3907 if (rasterP->numBands > MAX_NUMBANDS) { 3908 return -1; 3909 } 3910 3911 /* Grab data ptr, strides, offsets from raster */ 3912 jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID); 3913 if (JNU_IsNull(env, jOutDataP)) { 3914 return -1; 3915 } 3916 3917 dataArrayLength = (*env)->GetArrayLength(env, jOutDataP); 3918 CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1); 3919 3920 outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0); 3921 if (outDataP == NULL) { 3922 return -1; 3923 } 3924 lineOutP = outDataP + rasterP->chanOffsets[0]; 3925 3926 if (component < 0) { 3927 for (c=0; c < rasterP->numBands; c++) { 3928 loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3929 if (loff[c] < 0) { 3930 roff[c] = -loff[c]; 3931 loff[c] = 0; 3932 } 3933 else roff[c] = 0; 3934 } 3935 /* Convert the all bands */ 3936 if (supportsAlpha) { 3937 for (y=0; y < rasterP->height; y++) { 3938 outP = lineOutP; 3939 for (x=0; x < rasterP->width; x++) { 3940 *outP |= (*inP<<loff[a]>>roff[a])& 3941 rasterP->sppsm.maskArray[a]; 3942 inP++; 3943 for (c=0; c < rasterP->numBands-1; c++, inP++) { 3944 /* Not correct. Might need to unpremult, shift, etc */ 3945 *outP |= (*inP<<loff[c]>>roff[c])& 3946 rasterP->sppsm.maskArray[c]; 3947 } 3948 outP++; 3949 } 3950 lineOutP += rasterP->scanlineStride; 3951 } 3952 } 3953 else { 3954 for (y=0; y < rasterP->height; y++) { 3955 outP = lineOutP; 3956 for (x=0; x < rasterP->width; x++) { 3957 inP++; 3958 for (c=0; c < rasterP->numBands; c++, inP++) { 3959 /* Not correct. Might need to unpremult, shift, etc */ 3960 *outP |= (*inP<<loff[c]>>roff[c])& 3961 rasterP->sppsm.maskArray[c]; 3962 } 3963 outP++; 3964 } 3965 lineOutP += rasterP->scanlineStride; 3966 } 3967 } 3968 } 3969 else { 3970 c = component; 3971 loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8); 3972 if (loff[0] < 0) { 3973 roff[0] = -loff[0]; 3974 loff[0] = 0; 3975 } 3976 else roff[c] = 0; 3977 3978 for (y=0; y < rasterP->height; y++) { 3979 outP = lineOutP; 3980 for (x=0; x < rasterP->width; x++, inP++) { 3981 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c]; 3982 outP++; 3983 } 3984 lineOutP += rasterP->scanlineStride; 3985 } 3986 } 3987 3988 (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT); 3989 3990 return 0; 3991 } 3992 3993 /* This is temporary code. Should go away when there is better color 3994 * conversion code available. 3995 * REMIND: Ignoring alpha 3996 */ 3997 /* returns the absolute value x */ 3998 #define ABS(x) ((x) < 0 ? -(x) : (x)) 3999 #define CLIP(val,min,max) ((val < min) ? min : ((val > max) ? max : val)) 4000 4001 static int 4002 colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors) { 4003 int besti = 0; 4004 int mindist, i, t, d; 4005 unsigned char red, green, blue; 4006 4007 r = CLIP(r, 0, 255); 4008 g = CLIP(g, 0, 255); 4009 b = CLIP(b, 0, 255); 4010 4011 /* look for pure gray match */ 4012 if ((r == g) && (g == b)) { 4013 mindist = 256; 4014 for (i = 0 ; i < numColors ; i++, argb+=4) { 4015 red = argb[1]; 4016 green = argb[2]; 4017 blue = argb[3]; 4018 if (! ((red == green) && (green == blue)) ) { 4019 continue; 4020 } 4021 d = ABS(red - r); 4022 if (d == 0) 4023 return i; 4024 if (d < mindist) { 4025 besti = i; 4026 mindist = d; 4027 } 4028 } 4029 return besti; 4030 } 4031 4032 /* look for non-pure gray match */ 4033 mindist = 256 * 256 * 256; 4034 for (i = 0 ; i < numColors ; i++, argb+=4) { 4035 red = argb[1]; 4036 green = argb[2]; 4037 blue = argb[3]; 4038 t = red - r; 4039 d = t * t; 4040 if (d >= mindist) { 4041 continue; 4042 } 4043 t = green - g; 4044 d += t * t; 4045 if (d >= mindist) { 4046 continue; 4047 } 4048 t = blue - b; 4049 d += t * t; 4050 if (d >= mindist) { 4051 continue; 4052 } 4053 if (d == 0) 4054 return i; 4055 if (d < mindist) { 4056 besti = i; 4057 mindist = d; 4058 } 4059 } 4060 4061 return besti; 4062 }