1 /* 2 * Copyright (c) 1997, 2010, 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 "awt_parseImage.h" 29 #include "imageInitIDs.h" 30 #include "java_awt_Transparency.h" 31 #include "java_awt_image_BufferedImage.h" 32 #include "sun_awt_image_IntegerComponentRaster.h" 33 #include "sun_awt_image_ImagingLib.h" 34 #include "java_awt_color_ColorSpace.h" 35 #include "awt_Mlib.h" 36 #include "safe_alloc.h" 37 38 static int setHints(JNIEnv *env, BufImageS_t *imageP); 39 40 41 42 /* Parse the buffered image. All of the raster information is returned in the 43 * imagePP structure. 44 * 45 * The handleCustom parameter specifies whether or not the caller 46 * can use custom channels. If it is false and a custom channel 47 * is encountered, the returned value will be 0 and all structures 48 * will be deallocated. 49 * 50 * Return value: 51 * -1: Exception 52 * 0: Can't do it. 53 * 1: Success 54 */ 55 int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP, 56 int handleCustom) { 57 BufImageS_t *imageP; 58 int status; 59 jobject jraster; 60 jobject jcmodel; 61 62 /* Make sure the image exists */ 63 if (JNU_IsNull(env, jimage)) { 64 JNU_ThrowNullPointerException(env, "null BufferedImage object"); 65 return -1; 66 } 67 68 if ((imageP = (BufImageS_t *) calloc(1, sizeof(BufImageS_t))) == NULL) { 69 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 70 return -1; 71 } 72 imageP->jimage = jimage; 73 74 /* Retrieve the raster */ 75 if ((jraster = (*env)->GetObjectField(env, jimage, 76 g_BImgRasterID)) == NULL) { 77 free((void *) imageP); 78 JNU_ThrowNullPointerException(env, "null Raster object"); 79 return 0; 80 } 81 82 /* Retrieve the image type */ 83 imageP->imageType = (*env)->GetIntField(env, jimage, g_BImgTypeID); 84 85 /* Parse the raster */ 86 if ((status = awt_parseRaster(env, jraster, &imageP->raster)) <= 0) { 87 free((void *)imageP); 88 return status; 89 } 90 91 /* Retrieve the color model */ 92 if ((jcmodel = (*env)->GetObjectField(env, jimage, g_BImgCMID)) == NULL) { 93 free((void *) imageP); 94 JNU_ThrowNullPointerException(env, "null Raster object"); 95 return 0; 96 } 97 98 /* Parse the color model */ 99 if ((status = awt_parseColorModel(env, jcmodel, imageP->imageType, 100 &imageP->cmodel)) <= 0) { 101 awt_freeParsedRaster(&imageP->raster, FALSE); 102 free((void *)imageP); 103 return 0; 104 } 105 106 /* Set hints */ 107 if ((status = setHints(env, imageP)) <= 0) { 108 awt_freeParsedImage(imageP, TRUE); 109 return 0; 110 } 111 112 *imagePP = imageP; 113 114 return status; 115 } 116 117 /* Parse the raster. All of the raster information is returned in the 118 * rasterP structure. 119 * 120 * Return value: 121 * -1: Exception 122 * 0: Can't do it (Custom channel) 123 * 1: Success 124 */ 125 int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) { 126 jobject joffs = NULL; 127 /* int status;*/ 128 int isDiscrete = TRUE; 129 130 if (JNU_IsNull(env, jraster)) { 131 JNU_ThrowNullPointerException(env, "null Raster object"); 132 return -1; 133 } 134 135 rasterP->jraster = jraster; 136 rasterP->width = (*env)->GetIntField(env, jraster, g_RasterWidthID); 137 rasterP->height = (*env)->GetIntField(env, jraster, g_RasterHeightID); 138 rasterP->numDataElements = (*env)->GetIntField(env, jraster, 139 g_RasterNumDataElementsID); 140 rasterP->numBands = (*env)->GetIntField(env, jraster, 141 g_RasterNumBandsID); 142 143 rasterP->baseOriginX = (*env)->GetIntField(env, jraster, 144 g_RasterBaseOriginXID); 145 rasterP->baseOriginY = (*env)->GetIntField(env, jraster, 146 g_RasterBaseOriginYID); 147 rasterP->minX = (*env)->GetIntField(env, jraster, g_RasterMinXID); 148 rasterP->minY = (*env)->GetIntField(env, jraster, g_RasterMinYID); 149 150 rasterP->jsampleModel = (*env)->GetObjectField(env, jraster, 151 g_RasterSampleModelID); 152 153 if (JNU_IsNull(env, rasterP->jsampleModel)) { 154 JNU_ThrowNullPointerException(env, "null Raster object"); 155 return -1; 156 } 157 158 if (rasterP->numBands <= 0 || 159 rasterP->numBands > MAX_NUMBANDS) 160 { 161 /* 162 * we can't handle such kind of rasters due to limitations 163 * of SPPSampleModelS_t structure and expand/set methods. 164 */ 165 return 0; 166 } 167 168 if ((*env)->IsInstanceOf(env, rasterP->jsampleModel, 169 (*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) { 170 jobject jmask, joffs, jnbits; 171 rasterP->sppsm.maxBitSize = (*env)->GetIntField(env, 172 rasterP->jsampleModel, 173 g_SPPSMmaxBitID); 174 jmask = (*env)->GetObjectField(env, rasterP->jsampleModel, 175 g_SPPSMmaskArrID); 176 joffs = (*env)->GetObjectField(env, rasterP->jsampleModel, 177 g_SPPSMmaskOffID); 178 jnbits = (*env)->GetObjectField(env, rasterP->jsampleModel, 179 g_SPPSMnBitsID); 180 if (jmask == NULL || joffs == NULL || jnbits == NULL || 181 rasterP->sppsm.maxBitSize < 0) 182 { 183 JNU_ThrowInternalError(env, "Can't grab SPPSM fields"); 184 return -1; 185 } 186 (*env)->GetIntArrayRegion(env, jmask, 0, 187 rasterP->numBands, rasterP->sppsm.maskArray); 188 (*env)->GetIntArrayRegion(env, joffs, 0, 189 rasterP->numBands, rasterP->sppsm.offsets); 190 (*env)->GetIntArrayRegion(env, jnbits, 0, 191 rasterP->numBands, rasterP->sppsm.nBits); 192 193 } 194 rasterP->baseRasterWidth = (*env)->GetIntField(env, rasterP->jsampleModel, 195 g_SMWidthID); 196 rasterP->baseRasterHeight = (*env)->GetIntField(env, 197 rasterP->jsampleModel, 198 g_SMHeightID); 199 200 if ((*env)->IsInstanceOf(env, jraster, 201 (*env)->FindClass(env, "sun/awt/image/IntegerComponentRaster"))){ 202 rasterP->jdata = (*env)->GetObjectField(env, jraster, g_ICRdataID); 203 rasterP->dataType = INT_DATA_TYPE; 204 rasterP->dataSize = 4; 205 rasterP->dataIsShared = TRUE; 206 rasterP->rasterType = COMPONENT_RASTER_TYPE; 207 rasterP->type = (*env)->GetIntField(env, jraster, g_ICRtypeID); 208 rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_ICRscanstrID); 209 rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_ICRpixstrID); 210 joffs = (*env)->GetObjectField(env, jraster, g_ICRdataOffsetsID); 211 } 212 else if ((*env)->IsInstanceOf(env, jraster, 213 (*env)->FindClass(env, "sun/awt/image/ByteComponentRaster"))){ 214 rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BCRdataID); 215 rasterP->dataType = BYTE_DATA_TYPE; 216 rasterP->dataSize = 1; 217 rasterP->dataIsShared = TRUE; 218 rasterP->rasterType = COMPONENT_RASTER_TYPE; 219 rasterP->type = (*env)->GetIntField(env, jraster, g_BCRtypeID); 220 rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BCRscanstrID); 221 rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BCRpixstrID); 222 joffs = (*env)->GetObjectField(env, jraster, g_BCRdataOffsetsID); 223 } 224 else if ((*env)->IsInstanceOf(env, jraster, 225 (*env)->FindClass(env, "sun/awt/image/ShortComponentRaster"))){ 226 rasterP->jdata = (*env)->GetObjectField(env, jraster, g_SCRdataID); 227 rasterP->dataType = SHORT_DATA_TYPE; 228 rasterP->dataSize = 2; 229 rasterP->dataIsShared = TRUE; 230 rasterP->rasterType = COMPONENT_RASTER_TYPE; 231 rasterP->type = (*env)->GetIntField(env, jraster, g_SCRtypeID); 232 rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_SCRscanstrID); 233 rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_SCRpixstrID); 234 joffs = (*env)->GetObjectField(env, jraster, g_SCRdataOffsetsID); 235 } 236 else if ((*env)->IsInstanceOf(env, jraster, 237 (*env)->FindClass(env, "sun/awt/image/BytePackedRaster"))){ 238 rasterP->rasterType = PACKED_RASTER_TYPE; 239 rasterP->dataType = BYTE_DATA_TYPE; 240 rasterP->dataSize = 1; 241 rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BPRscanstrID); 242 rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BPRpixstrID); 243 rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BPRdataID); 244 rasterP->type = (*env)->GetIntField(env, jraster, g_BPRtypeID); 245 rasterP->chanOffsets = NULL; 246 if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { 247 rasterP->chanOffsets = 248 (jint *)malloc(rasterP->numDataElements * sizeof(jint)); 249 } 250 if (rasterP->chanOffsets == NULL) { 251 /* Out of memory */ 252 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 253 return -1; 254 } 255 rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID); 256 rasterP->dataType = BYTE_DATA_TYPE; 257 isDiscrete = FALSE; 258 } 259 else { 260 rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM; 261 rasterP->dataType = UNKNOWN_DATA_TYPE; 262 rasterP->rasterType = UNKNOWN_RASTER_TYPE; 263 rasterP->chanOffsets = NULL; 264 /* Custom raster */ 265 return 0; 266 } 267 268 if (isDiscrete) { 269 rasterP->chanOffsets = NULL; 270 if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) { 271 rasterP->chanOffsets = 272 (jint *)malloc(rasterP->numDataElements * sizeof(jint)); 273 } 274 if (rasterP->chanOffsets == NULL) { 275 /* Out of memory */ 276 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 277 return -1; 278 } 279 (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements, 280 rasterP->chanOffsets); 281 } 282 283 /* additioanl check for sppsm fields validity: make sure that 284 * size of raster samples doesn't exceed the data type cpacity. 285 */ 286 if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */ 287 rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */ 288 rasterP->sppsm.maxBitSize > (rasterP->dataSize * 8)) 289 { 290 JNU_ThrowInternalError(env, "Raster samples are too big"); 291 return -1; 292 } 293 294 #if 0 295 fprintf(stderr,"---------------------\n"); 296 fprintf(stderr,"Width : %d\n",rasterP->width); 297 fprintf(stderr,"Height : %d\n",rasterP->height); 298 fprintf(stderr,"X : %d\n",rasterP->x); 299 fprintf(stderr,"Y : %d\n",rasterP->y); 300 fprintf(stderr,"numC : %d\n",rasterP->numDataElements); 301 fprintf(stderr,"SS : %d\n",rasterP->scanlineStride); 302 fprintf(stderr,"PS : %d\n",rasterP->pixelStride); 303 fprintf(stderr,"CO : %d\n",rasterP->chanOffsets); 304 fprintf(stderr,"shared?: %d\n",rasterP->dataIsShared); 305 fprintf(stderr,"RasterT: %d\n",rasterP->rasterType); 306 fprintf(stderr,"DataT : %d\n",rasterP->dataType); 307 fprintf(stderr,"---------------------\n"); 308 #endif 309 310 return 1; 311 } 312 313 int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, 314 ColorModelS_t *cmP) { 315 /*jmethodID jID; */ 316 jobject jnBits; 317 int i; 318 static jobject s_jdefCM = NULL; 319 320 if (JNU_IsNull(env, jcmodel)) { 321 JNU_ThrowNullPointerException(env, "null ColorModel object"); 322 return -1; 323 } 324 325 cmP->jcmodel = jcmodel; 326 327 cmP->jcspace = (*env)->GetObjectField(env, jcmodel, g_CMcspaceID); 328 329 cmP->numComponents = (*env)->GetIntField(env, jcmodel, 330 g_CMnumComponentsID); 331 cmP->supportsAlpha = (*env)->GetBooleanField(env, jcmodel, 332 g_CMsuppAlphaID); 333 cmP->isAlphaPre = (*env)->GetBooleanField(env,jcmodel, 334 g_CMisAlphaPreID); 335 cmP->transparency = (*env)->GetIntField(env, jcmodel, 336 g_CMtransparencyID); 337 338 if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB) { 339 cmP->isDefaultCM = TRUE; 340 cmP->isDefaultCompatCM = TRUE; 341 } else if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE || 342 imageType == java_awt_image_BufferedImage_TYPE_INT_RGB) { 343 cmP->isDefaultCompatCM = TRUE; 344 } else if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR || 345 imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR || 346 imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE){ 347 cmP->isDefaultCompatCM = TRUE; 348 } 349 else { 350 /* Figure out if this is the default CM */ 351 if (s_jdefCM == NULL) { 352 jobject defCM; 353 jclass jcm = (*env)->FindClass(env, "java/awt/image/ColorModel"); 354 defCM = (*env)->CallStaticObjectMethod(env, jcm, 355 g_CMgetRGBdefaultMID, NULL); 356 s_jdefCM = (*env)->NewGlobalRef(env, defCM); 357 if (defCM == NULL || s_jdefCM == NULL) { 358 JNU_ThrowNullPointerException(env, 359 "Unable to find default CM"); 360 return -1; 361 } 362 } 363 cmP->isDefaultCM = ((*env)->IsSameObject(env, s_jdefCM, jcmodel)); 364 cmP->isDefaultCompatCM = cmP->isDefaultCM; 365 } 366 367 if (cmP->isDefaultCompatCM) { 368 cmP->cmType = DIRECT_CM_TYPE; 369 cmP->nBits = (jint *) malloc(sizeof(jint)*4); 370 cmP->nBits[0] = cmP->nBits[1] = cmP->nBits[2] = cmP->nBits[3] = 8; 371 cmP->maxNbits = 8; 372 cmP->is_sRGB = TRUE; 373 cmP->csType = java_awt_color_ColorSpace_TYPE_RGB; 374 375 return 1; 376 } 377 378 jnBits = (*env)->GetObjectField(env, jcmodel, g_CMnBitsID); 379 if (jnBits == NULL) { 380 JNU_ThrowNullPointerException(env, "null nBits structure in CModel"); 381 return -1; 382 } 383 384 cmP->nBits = NULL; 385 if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) { 386 cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint)); 387 } 388 if (cmP->nBits == NULL){ 389 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 390 return -1; 391 } 392 (*env)->GetIntArrayRegion(env, jnBits, 0, cmP->numComponents, 393 cmP->nBits); 394 cmP->maxNbits = 0; 395 for (i=0; i < cmP->numComponents; i++) { 396 if (cmP->maxNbits < cmP->nBits[i]) { 397 cmP->maxNbits = cmP->nBits[i]; 398 } 399 } 400 401 cmP->is_sRGB = (*env)->GetBooleanField(env, cmP->jcmodel, g_CMis_sRGBID); 402 403 cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID); 404 405 /* Find out what type of colol model */ 406 if (imageType == java_awt_image_BufferedImage_TYPE_BYTE_INDEXED || 407 (*env)->IsInstanceOf(env, jcmodel, 408 (*env)->FindClass(env, "java/awt/image/IndexColorModel"))) 409 { 410 cmP->cmType = INDEX_CM_TYPE; 411 cmP->transIdx = (*env)->GetIntField(env, jcmodel, g_ICMtransIdxID); 412 cmP->mapSize = (*env)->GetIntField(env, jcmodel, g_ICMmapSizeID); 413 cmP->jrgb = (*env)->GetObjectField(env, jcmodel, g_ICMrgbID); 414 if (cmP->transIdx == -1) { 415 /* Need to find the transparent index */ 416 int *rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, 417 cmP->jrgb, 418 NULL); 419 if (rgb == NULL) { 420 return -1; 421 } 422 for (i=0; i < cmP->mapSize; i++) { 423 if ((rgb[i]&0xff000000) == 0) { 424 cmP->transIdx = i; 425 break; 426 } 427 } 428 (*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb, 429 JNI_ABORT); 430 if (cmP->transIdx == -1) { 431 /* Now what? No transparent pixel... */ 432 cmP->transIdx = 0; 433 } 434 } 435 } 436 else if ((*env)->IsInstanceOf(env, jcmodel, 437 (*env)->FindClass(env, "java/awt/image/PackedColorModel"))) 438 { 439 if ((*env)->IsInstanceOf(env, jcmodel, 440 (*env)->FindClass(env, "java/awt/image/DirectColorModel"))){ 441 cmP->cmType = DIRECT_CM_TYPE; 442 } 443 else { 444 cmP->cmType = PACKED_CM_TYPE; 445 } 446 } 447 else if ((*env)->IsInstanceOf(env, jcmodel, 448 (*env)->FindClass(env, "java/awt/image/ComponentColorModel"))) 449 { 450 cmP->cmType = COMPONENT_CM_TYPE; 451 } 452 else if ((*env)->IsInstanceOf(env, jcmodel, 453 (*env)->FindClass(env, "java/awt/image/PackedColorModel"))) 454 { 455 cmP->cmType = PACKED_CM_TYPE; 456 } 457 else { 458 cmP->cmType = UNKNOWN_CM_TYPE; 459 } 460 461 462 return 1; 463 } 464 465 void awt_freeParsedRaster(RasterS_t *rasterP, int freeRasterP) { 466 if (rasterP->chanOffsets) { 467 free((void *) rasterP->chanOffsets); 468 } 469 470 if (freeRasterP) { 471 free((void *) rasterP); 472 } 473 } 474 475 void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) { 476 if (imageP->hints.colorOrder) { 477 free ((void *) imageP->hints.colorOrder); 478 } 479 480 if (imageP->cmodel.nBits) { 481 free ((void *) imageP->cmodel.nBits); 482 } 483 484 /* Free the raster */ 485 awt_freeParsedRaster(&imageP->raster, FALSE); 486 487 if (freeImageP) { 488 free((void *) imageP); 489 } 490 } 491 492 static void 493 awt_getBIColorOrder(int type, int *colorOrder) { 494 switch(type) { 495 case java_awt_image_BufferedImage_TYPE_INT_ARGB: 496 case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE: 497 #ifdef _LITTLE_ENDIAN 498 colorOrder[0] = 2; 499 colorOrder[1] = 1; 500 colorOrder[2] = 0; 501 colorOrder[3] = 3; 502 #else 503 colorOrder[0] = 1; 504 colorOrder[1] = 2; 505 colorOrder[2] = 3; 506 colorOrder[3] = 0; 507 #endif 508 break; 509 case java_awt_image_BufferedImage_TYPE_INT_BGR: 510 #ifdef _LITTLE_ENDIAN 511 colorOrder[0] = 0; 512 colorOrder[1] = 1; 513 colorOrder[2] = 2; 514 #else 515 colorOrder[0] = 3; 516 colorOrder[1] = 2; 517 colorOrder[2] = 1; 518 #endif 519 break; 520 case java_awt_image_BufferedImage_TYPE_INT_RGB: 521 #ifdef _LITTLE_ENDIAN 522 colorOrder[0] = 2; 523 colorOrder[1] = 1; 524 colorOrder[2] = 0; 525 #else 526 colorOrder[0] = 1; 527 colorOrder[1] = 2; 528 colorOrder[2] = 3; 529 #endif 530 break; 531 case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR: 532 case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE: 533 colorOrder[0] = 3; 534 colorOrder[1] = 2; 535 colorOrder[2] = 1; 536 colorOrder[3] = 0; 537 break; 538 case java_awt_image_BufferedImage_TYPE_3BYTE_BGR: 539 colorOrder[0] = 2; 540 colorOrder[1] = 1; 541 colorOrder[2] = 0; 542 break; 543 case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB: 544 case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB: 545 colorOrder[0] = 0; 546 colorOrder[1] = 1; 547 colorOrder[2] = 2; 548 break; 549 case java_awt_image_BufferedImage_TYPE_BYTE_GRAY: 550 case java_awt_image_BufferedImage_TYPE_USHORT_GRAY: 551 case java_awt_image_BufferedImage_TYPE_BYTE_BINARY: 552 case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED: 553 colorOrder[0] = 0; 554 break; 555 } 556 } 557 558 static int 559 setHints(JNIEnv *env, BufImageS_t *imageP) { 560 HintS_t *hintP = &imageP->hints; 561 RasterS_t *rasterP = &imageP->raster; 562 ColorModelS_t *cmodelP = &imageP->cmodel; 563 int imageType = imageP->imageType; 564 565 hintP->numChans = imageP->cmodel.numComponents; 566 hintP->colorOrder = NULL; 567 if (SAFE_TO_ALLOC_2(hintP->numChans, sizeof(int))) { 568 hintP->colorOrder = (int *)malloc(hintP->numChans * sizeof(int)); 569 } 570 if (hintP->colorOrder == NULL) { 571 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 572 return -1; 573 } 574 if (imageType != java_awt_image_BufferedImage_TYPE_CUSTOM) { 575 awt_getBIColorOrder(imageType, hintP->colorOrder); 576 } 577 if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB || 578 imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE || 579 imageType == java_awt_image_BufferedImage_TYPE_INT_RGB) 580 { 581 hintP->channelOffset = rasterP->chanOffsets[0]; 582 /* These hints are #bytes */ 583 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 584 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 585 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 586 hintP->packing = BYTE_INTERLEAVED; 587 } else if (imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR || 588 imageType==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE|| 589 imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR || 590 imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) 591 { 592 if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) { 593 hintP->channelOffset = rasterP->chanOffsets[0]; 594 } 595 else { 596 hintP->channelOffset = rasterP->chanOffsets[hintP->numChans-1]; 597 } 598 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 599 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 600 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 601 hintP->packing = BYTE_INTERLEAVED; 602 } else if (imageType==java_awt_image_BufferedImage_TYPE_USHORT_565_RGB || 603 imageType==java_awt_image_BufferedImage_TYPE_USHORT_555_RGB) { 604 hintP->needToExpand = TRUE; 605 hintP->expandToNbits = 8; 606 hintP->packing = PACKED_SHORT_INTER; 607 } else if (cmodelP->cmType == INDEX_CM_TYPE) { 608 int i; 609 hintP->numChans = 1; 610 hintP->channelOffset = rasterP->chanOffsets[0]; 611 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 612 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 613 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 614 switch(rasterP->dataType ) { 615 case BYTE_DATA_TYPE: 616 if (rasterP->rasterType == PACKED_RASTER_TYPE) { 617 hintP->needToExpand = TRUE; 618 hintP->expandToNbits = 8; 619 hintP->packing = BYTE_PACKED_BAND; 620 } 621 else { 622 hintP->packing = BYTE_SINGLE_BAND; 623 } 624 break; 625 case SHORT_DATA_TYPE: 626 hintP->packing = SHORT_SINGLE_BAND; 627 break; 628 case INT_DATA_TYPE: 629 default: 630 hintP->packing = UNKNOWN_PACKING; 631 break; 632 } 633 for (i=0; i < hintP->numChans; i++) { 634 hintP->colorOrder[i] = i; 635 } 636 } 637 else if (cmodelP->cmType == COMPONENT_CM_TYPE) { 638 /* Figure out if it is interleaved */ 639 int bits=1; 640 int i; 641 int low = rasterP->chanOffsets[0]; 642 int diff; 643 int banded = 0; 644 for (i=1; i < hintP->numChans; i++) { 645 if (rasterP->chanOffsets[i] < low) { 646 low = rasterP->chanOffsets[i]; 647 } 648 } 649 for (i=1; i < hintP->numChans; i++) { 650 diff = rasterP->chanOffsets[i]-low; 651 if (diff < hintP->numChans) { 652 if (bits & (1<<diff)) { 653 /* Overlapping samples */ 654 /* Could just copy */ 655 return -1; 656 } 657 bits |= (1<<diff); 658 } 659 else if (diff >= rasterP->width) { 660 banded = 1; 661 } 662 /* Ignore the case if bands are overlapping */ 663 } 664 hintP->channelOffset = low; 665 hintP->dataOffset = low*rasterP->dataSize; 666 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 667 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 668 switch(rasterP->dataType) { 669 case BYTE_DATA_TYPE: 670 hintP->packing = BYTE_COMPONENTS; 671 break; 672 case SHORT_DATA_TYPE: 673 hintP->packing = SHORT_COMPONENTS; 674 break; 675 default: 676 /* Don't handle any other case */ 677 return -1; 678 } 679 if (bits == ((1<<hintP->numChans)-1)) { 680 hintP->packing |= INTERLEAVED; 681 for (i=0; i < hintP->numChans; i++) { 682 hintP->colorOrder[rasterP->chanOffsets[i]-low] = i; 683 } 684 } 685 else if (banded == 1) { 686 int bandSize = rasterP->width*rasterP->height; 687 hintP->packing |= BANDED; 688 for (i=0; i < hintP->numChans; i++) { 689 /* REMIND: Not necessarily correct */ 690 hintP->colorOrder[(rasterP->chanOffsets[i]-low)%bandSize] = i; 691 } 692 } 693 else { 694 return -1; 695 } 696 } 697 else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) { 698 int i; 699 if (cmodelP->maxNbits > 8) { 700 hintP->needToExpand = TRUE; 701 hintP->expandToNbits = cmodelP->maxNbits; 702 } 703 else if (rasterP->sppsm.offsets != NULL) { 704 for (i=0; i < rasterP->numBands; i++) { 705 if (!(rasterP->sppsm.offsets[i] % 8)) { 706 hintP->needToExpand = TRUE; 707 hintP->expandToNbits = 8; 708 break; 709 } 710 else { 711 hintP->colorOrder[i] = rasterP->sppsm.offsets[i]>>3; 712 } 713 } 714 } 715 716 hintP->channelOffset = rasterP->chanOffsets[0]; 717 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 718 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 719 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 720 if (hintP->needToExpand) { 721 switch(rasterP->dataType) { 722 case BYTE_DATA_TYPE: 723 hintP->packing = PACKED_BYTE_INTER; 724 break; 725 case SHORT_DATA_TYPE: 726 hintP->packing = PACKED_SHORT_INTER; 727 break; 728 case INT_DATA_TYPE: 729 hintP->packing = PACKED_INT_INTER; 730 break; 731 default: 732 /* Don't know what it is */ 733 return -1; 734 } 735 } 736 else { 737 hintP->packing = BYTE_INTERLEAVED; 738 739 } 740 } 741 else { 742 /* REMIND: Need to handle more cases */ 743 return -1; 744 } 745 746 return 1; 747 } 748 749 /* 750 * This routine will fill in a buffer of data for either 1 band or all 751 * bands (if band == -1). 752 */ 753 #define MAX_TO_GRAB (10240) 754 755 int awt_getPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, 756 unsigned char *bufferP) { 757 int w = rasterP->width; 758 int h = rasterP->height; 759 int numBands = rasterP->numBands; 760 int y; 761 int i; 762 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 763 jobject jsm; 764 int off; 765 jarray jdata = NULL; 766 jobject jdatabuffer; 767 int *dataP; 768 int maxBytes = w; 769 770 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 771 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 772 g_RasterDataBufferID); 773 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 774 if (JNU_IsNull(env, jdata)) { 775 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 776 return -1; 777 } 778 779 /* Here is the generic code */ 780 if (band >= 0) { 781 int dOff; 782 if (band >= numBands) { 783 (*env)->DeleteLocalRef(env, jdata); 784 JNU_ThrowInternalError(env, "Band out of range."); 785 return -1; 786 } 787 off = 0; 788 for (y=0; y < h; ) { 789 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 790 0, y, w, 791 maxLines, jdata, jdatabuffer); 792 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 793 NULL); 794 if (dataP == NULL) { 795 (*env)->DeleteLocalRef(env, jdata); 796 return -1; 797 } 798 dOff = band; 799 for (i=0; i < maxBytes; i++, dOff += numBands) { 800 bufferP[off++] = (unsigned char) dataP[dOff]; 801 } 802 803 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 804 JNI_ABORT); 805 806 if (y+maxLines < h) { 807 y += maxLines; 808 } 809 else { 810 y++; 811 maxBytes = w; 812 } 813 } 814 } 815 else { 816 off = 0; 817 maxBytes *= numBands; 818 for (y=0; y < h; ) { 819 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 820 0, y, w, 821 maxLines, jdata, jdatabuffer); 822 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 823 NULL); 824 if (dataP == NULL) { 825 (*env)->DeleteLocalRef(env, jdata); 826 return -1; 827 } 828 for (i=0; i < maxBytes; i++) { 829 bufferP[off++] = (unsigned char) dataP[i]; 830 } 831 832 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 833 JNI_ABORT); 834 835 if (y+maxLines < h) { 836 y += maxLines; 837 } 838 else { 839 y++; 840 maxBytes = w*numBands; 841 } 842 } 843 844 } 845 (*env)->DeleteLocalRef(env, jdata); 846 847 return 0; 848 } 849 int awt_setPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, 850 unsigned char *bufferP) { 851 int w = rasterP->width; 852 int h = rasterP->height; 853 int numBands = rasterP->numBands; 854 int y; 855 int i; 856 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 857 jobject jsm; 858 int off; 859 jarray jdata = NULL; 860 jobject jdatabuffer; 861 int *dataP; 862 int maxBytes = w; 863 864 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 865 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 866 g_RasterDataBufferID); 867 /* Here is the generic code */ 868 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 869 if (JNU_IsNull(env, jdata)) { 870 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 871 return -1; 872 } 873 if (band >= 0) { 874 int dOff; 875 if (band >= numBands) { 876 (*env)->DeleteLocalRef(env, jdata); 877 JNU_ThrowInternalError(env, "Band out of range."); 878 return -1; 879 } 880 off = 0; 881 for (y=0; y < h; y+=maxLines) { 882 if (y+maxLines > h) { 883 maxBytes = w*numBands; 884 maxLines = h - y; 885 } 886 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 887 NULL); 888 if (dataP == NULL) { 889 (*env)->DeleteLocalRef(env, jdata); 890 return -1; 891 } 892 dOff = band; 893 for (i=0; i < maxBytes; i++, dOff += numBands) { 894 dataP[dOff] = bufferP[off++]; 895 } 896 897 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 898 JNI_ABORT); 899 900 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 901 0, y, w, 902 maxLines, jdata, jdatabuffer); 903 } 904 } 905 else { 906 off = 0; 907 maxBytes *= numBands; 908 for (y=0; y < h; y+=maxLines) { 909 if (y+maxLines > h) { 910 maxBytes = w*numBands; 911 maxLines = h - y; 912 } 913 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 914 NULL); 915 if (dataP == NULL) { 916 (*env)->DeleteLocalRef(env, jdata); 917 return -1; 918 } 919 for (i=0; i < maxBytes; i++) { 920 dataP[i] = bufferP[off++]; 921 } 922 923 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 924 JNI_ABORT); 925 926 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 927 0, y, w, 928 maxLines, jdata, jdatabuffer); 929 } 930 931 } 932 933 (*env)->DeleteLocalRef(env, jdata); 934 935 return 0; 936 } 937 int awt_getPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, 938 unsigned short *bufferP) { 939 int w = rasterP->width; 940 int h = rasterP->height; 941 int numBands = rasterP->numBands; 942 int y; 943 int i; 944 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 945 jobject jsm; 946 int off; 947 jarray jdata = NULL; 948 jobject jdatabuffer; 949 int *dataP; 950 int maxBytes = w*maxLines; 951 952 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 953 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 954 g_RasterDataBufferID); 955 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 956 if (JNU_IsNull(env, jdata)) { 957 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 958 return -1; 959 } 960 /* Here is the generic code */ 961 if (band >= 0) { 962 int dOff; 963 if (band >= numBands) { 964 (*env)->DeleteLocalRef(env, jdata); 965 JNU_ThrowInternalError(env, "Band out of range."); 966 return -1; 967 } 968 off = 0; 969 for (y=0; y < h; y += maxLines) { 970 if (y+maxLines > h) { 971 maxBytes = w*numBands; 972 maxLines = h - y; 973 } 974 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 975 0, y, w, 976 maxLines, jdata, jdatabuffer); 977 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 978 NULL); 979 if (dataP == NULL) { 980 (*env)->DeleteLocalRef(env, jdata); 981 return -1; 982 } 983 984 dOff = band; 985 for (i=0; i < maxBytes; i++, dOff += numBands) { 986 bufferP[off++] = (unsigned short) dataP[dOff]; 987 } 988 989 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 990 JNI_ABORT); 991 } 992 } 993 else { 994 off = 0; 995 maxBytes *= numBands; 996 for (y=0; y < h; y+=maxLines) { 997 if (y+maxLines > h) { 998 maxBytes = w*numBands; 999 maxLines = h - y; 1000 } 1001 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 1002 0, y, w, 1003 maxLines, jdata, jdatabuffer); 1004 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 1005 NULL); 1006 if (dataP == NULL) { 1007 (*env)->DeleteLocalRef(env, jdata); 1008 return -1; 1009 } 1010 for (i=0; i < maxBytes; i++) { 1011 bufferP[off++] = (unsigned short) dataP[i]; 1012 } 1013 1014 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 1015 JNI_ABORT); 1016 } 1017 1018 } 1019 1020 (*env)->DeleteLocalRef(env, jdata); 1021 return 0; 1022 } 1023 int awt_setPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, 1024 unsigned short *bufferP) { 1025 int w = rasterP->width; 1026 int h = rasterP->height; 1027 int numBands = rasterP->numBands; 1028 int y; 1029 int i; 1030 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 1031 jobject jsm; 1032 int off; 1033 jarray jdata = NULL; 1034 jobject jdatabuffer; 1035 int *dataP; 1036 int maxBytes = w; 1037 1038 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 1039 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 1040 g_RasterDataBufferID); 1041 /* Here is the generic code */ 1042 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 1043 if (JNU_IsNull(env, jdata)) { 1044 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 1045 return -1; 1046 } 1047 if (band >= 0) { 1048 int dOff; 1049 if (band >= numBands) { 1050 (*env)->DeleteLocalRef(env, jdata); 1051 JNU_ThrowInternalError(env, "Band out of range."); 1052 return -1; 1053 } 1054 off = 0; 1055 for (y=0; y < h; y+=maxLines) { 1056 if (y+maxLines > h) { 1057 maxBytes = w*numBands; 1058 maxLines = h - y; 1059 } 1060 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 1061 NULL); 1062 if (dataP == NULL) { 1063 (*env)->DeleteLocalRef(env, jdata); 1064 return -1; 1065 } 1066 dOff = band; 1067 for (i=0; i < maxBytes; i++, dOff += numBands) { 1068 dataP[dOff] = bufferP[off++]; 1069 } 1070 1071 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 1072 JNI_ABORT); 1073 1074 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 1075 0, y, w, 1076 maxLines, jdata, jdatabuffer); 1077 } 1078 } 1079 else { 1080 off = 0; 1081 maxBytes *= numBands; 1082 for (y=0; y < h; y+=maxLines) { 1083 if (y+maxLines > h) { 1084 maxBytes = w*numBands; 1085 maxLines = h - y; 1086 } 1087 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 1088 NULL); 1089 if (dataP == NULL) { 1090 (*env)->DeleteLocalRef(env, jdata); 1091 return -1; 1092 } 1093 for (i=0; i < maxBytes; i++) { 1094 dataP[i] = bufferP[off++]; 1095 } 1096 1097 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 1098 JNI_ABORT); 1099 1100 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 1101 0, y, w, 1102 maxLines, jdata, jdatabuffer); 1103 } 1104 1105 } 1106 1107 (*env)->DeleteLocalRef(env, jdata); 1108 return 0; 1109 }