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