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 493 static int 494 setHints(JNIEnv *env, BufImageS_t *imageP) { 495 HintS_t *hintP = &imageP->hints; 496 RasterS_t *rasterP = &imageP->raster; 497 ColorModelS_t *cmodelP = &imageP->cmodel; 498 int imageType = imageP->imageType; 499 500 hintP->numChans = imageP->cmodel.numComponents; 501 hintP->colorOrder = NULL; 502 if (SAFE_TO_ALLOC_2(hintP->numChans, sizeof(int))) { 503 hintP->colorOrder = (int *)malloc(hintP->numChans * sizeof(int)); 504 } 505 if (hintP->colorOrder == NULL) { 506 JNU_ThrowOutOfMemoryError(env, "Out of memory"); 507 return -1; 508 } 509 if (imageType != java_awt_image_BufferedImage_TYPE_CUSTOM) { 510 awt_getBIColorOrder(imageType, hintP->colorOrder); 511 } 512 if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB || 513 imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE || 514 imageType == java_awt_image_BufferedImage_TYPE_INT_RGB) 515 { 516 hintP->channelOffset = rasterP->chanOffsets[0]; 517 /* These hints are #bytes */ 518 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 519 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 520 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 521 hintP->packing = BYTE_INTERLEAVED; 522 } else if (imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR || 523 imageType==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE|| 524 imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR || 525 imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) 526 { 527 if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) { 528 hintP->channelOffset = rasterP->chanOffsets[0]; 529 } 530 else { 531 hintP->channelOffset = rasterP->chanOffsets[hintP->numChans-1]; 532 } 533 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 534 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 535 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 536 hintP->packing = BYTE_INTERLEAVED; 537 } else if (imageType==java_awt_image_BufferedImage_TYPE_USHORT_565_RGB || 538 imageType==java_awt_image_BufferedImage_TYPE_USHORT_555_RGB) { 539 hintP->needToExpand = TRUE; 540 hintP->expandToNbits = 8; 541 hintP->packing = PACKED_SHORT_INTER; 542 } else if (cmodelP->cmType == INDEX_CM_TYPE) { 543 int i; 544 hintP->numChans = 1; 545 hintP->channelOffset = rasterP->chanOffsets[0]; 546 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 547 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 548 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 549 switch(rasterP->dataType ) { 550 case BYTE_DATA_TYPE: 551 if (rasterP->rasterType == PACKED_RASTER_TYPE) { 552 hintP->needToExpand = TRUE; 553 hintP->expandToNbits = 8; 554 hintP->packing = BYTE_PACKED_BAND; 555 } 556 else { 557 hintP->packing = BYTE_SINGLE_BAND; 558 } 559 break; 560 case SHORT_DATA_TYPE: 561 hintP->packing = SHORT_SINGLE_BAND; 562 break; 563 case INT_DATA_TYPE: 564 default: 565 hintP->packing = UNKNOWN_PACKING; 566 break; 567 } 568 for (i=0; i < hintP->numChans; i++) { 569 hintP->colorOrder[i] = i; 570 } 571 } 572 else if (cmodelP->cmType == COMPONENT_CM_TYPE) { 573 /* Figure out if it is interleaved */ 574 int bits=1; 575 int i; 576 int low = rasterP->chanOffsets[0]; 577 int diff; 578 int banded = 0; 579 for (i=1; i < hintP->numChans; i++) { 580 if (rasterP->chanOffsets[i] < low) { 581 low = rasterP->chanOffsets[i]; 582 } 583 } 584 for (i=1; i < hintP->numChans; i++) { 585 diff = rasterP->chanOffsets[i]-low; 586 if (diff < hintP->numChans) { 587 if (bits & (1<<diff)) { 588 /* Overlapping samples */ 589 /* Could just copy */ 590 return -1; 591 } 592 bits |= (1<<diff); 593 } 594 else if (diff >= rasterP->width) { 595 banded = 1; 596 } 597 /* Ignore the case if bands are overlapping */ 598 } 599 hintP->channelOffset = low; 600 hintP->dataOffset = low*rasterP->dataSize; 601 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 602 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 603 switch(rasterP->dataType) { 604 case BYTE_DATA_TYPE: 605 hintP->packing = BYTE_COMPONENTS; 606 break; 607 case SHORT_DATA_TYPE: 608 hintP->packing = SHORT_COMPONENTS; 609 break; 610 default: 611 /* Don't handle any other case */ 612 return -1; 613 } 614 if (bits == ((1<<hintP->numChans)-1)) { 615 hintP->packing |= INTERLEAVED; 616 for (i=0; i < hintP->numChans; i++) { 617 hintP->colorOrder[rasterP->chanOffsets[i]-low] = i; 618 } 619 } 620 else if (banded == 1) { 621 int bandSize = rasterP->width*rasterP->height; 622 hintP->packing |= BANDED; 623 for (i=0; i < hintP->numChans; i++) { 624 /* REMIND: Not necessarily correct */ 625 hintP->colorOrder[(rasterP->chanOffsets[i]-low)%bandSize] = i; 626 } 627 } 628 else { 629 return -1; 630 } 631 } 632 else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) { 633 int i; 634 if (cmodelP->maxNbits > 8) { 635 hintP->needToExpand = TRUE; 636 hintP->expandToNbits = cmodelP->maxNbits; 637 } 638 else if (rasterP->sppsm.offsets != NULL) { 639 for (i=0; i < rasterP->numBands; i++) { 640 if (!(rasterP->sppsm.offsets[i] % 8)) { 641 hintP->needToExpand = TRUE; 642 hintP->expandToNbits = 8; 643 break; 644 } 645 else { 646 hintP->colorOrder[i] = rasterP->sppsm.offsets[i]>>3; 647 } 648 } 649 } 650 651 hintP->channelOffset = rasterP->chanOffsets[0]; 652 hintP->dataOffset = hintP->channelOffset*rasterP->dataSize; 653 hintP->sStride = rasterP->scanlineStride*rasterP->dataSize; 654 hintP->pStride = rasterP->pixelStride*rasterP->dataSize; 655 if (hintP->needToExpand) { 656 switch(rasterP->dataType) { 657 case BYTE_DATA_TYPE: 658 hintP->packing = PACKED_BYTE_INTER; 659 break; 660 case SHORT_DATA_TYPE: 661 hintP->packing = PACKED_SHORT_INTER; 662 break; 663 case INT_DATA_TYPE: 664 hintP->packing = PACKED_INT_INTER; 665 break; 666 default: 667 /* Don't know what it is */ 668 return -1; 669 } 670 } 671 else { 672 hintP->packing = BYTE_INTERLEAVED; 673 674 } 675 } 676 else { 677 /* REMIND: Need to handle more cases */ 678 return -1; 679 } 680 681 return 1; 682 } 683 684 /* 685 * This routine will fill in a buffer of data for either 1 band or all 686 * bands (if band == -1). 687 */ 688 #define MAX_TO_GRAB (10240) 689 690 int awt_getPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, 691 unsigned char *bufferP) { 692 int w = rasterP->width; 693 int h = rasterP->height; 694 int numBands = rasterP->numBands; 695 int y; 696 int i; 697 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 698 jobject jsm; 699 int off; 700 jarray jdata = NULL; 701 jobject jdatabuffer; 702 int *dataP; 703 int maxBytes = w; 704 705 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 706 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 707 g_RasterDataBufferID); 708 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 709 if (JNU_IsNull(env, jdata)) { 710 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 711 return -1; 712 } 713 714 /* Here is the generic code */ 715 if (band >= 0) { 716 int dOff; 717 if (band >= numBands) { 718 (*env)->DeleteLocalRef(env, jdata); 719 JNU_ThrowInternalError(env, "Band out of range."); 720 return -1; 721 } 722 off = 0; 723 for (y=0; y < h; ) { 724 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 725 0, y, w, 726 maxLines, jdata, jdatabuffer); 727 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 728 NULL); 729 if (dataP == NULL) { 730 (*env)->DeleteLocalRef(env, jdata); 731 return -1; 732 } 733 dOff = band; 734 for (i=0; i < maxBytes; i++, dOff += numBands) { 735 bufferP[off++] = (unsigned char) dataP[dOff]; 736 } 737 738 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 739 JNI_ABORT); 740 741 if (y+maxLines < h) { 742 y += maxLines; 743 } 744 else { 745 y++; 746 maxBytes = w; 747 } 748 } 749 } 750 else { 751 off = 0; 752 maxBytes *= numBands; 753 for (y=0; y < h; ) { 754 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 755 0, y, w, 756 maxLines, jdata, jdatabuffer); 757 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 758 NULL); 759 if (dataP == NULL) { 760 (*env)->DeleteLocalRef(env, jdata); 761 return -1; 762 } 763 for (i=0; i < maxBytes; i++) { 764 bufferP[off++] = (unsigned char) dataP[i]; 765 } 766 767 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 768 JNI_ABORT); 769 770 if (y+maxLines < h) { 771 y += maxLines; 772 } 773 else { 774 y++; 775 maxBytes = w*numBands; 776 } 777 } 778 779 } 780 (*env)->DeleteLocalRef(env, jdata); 781 782 return 0; 783 } 784 int awt_setPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, 785 unsigned char *bufferP) { 786 int w = rasterP->width; 787 int h = rasterP->height; 788 int numBands = rasterP->numBands; 789 int y; 790 int i; 791 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 792 jobject jsm; 793 int off; 794 jarray jdata = NULL; 795 jobject jdatabuffer; 796 int *dataP; 797 int maxBytes = w; 798 799 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 800 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 801 g_RasterDataBufferID); 802 /* Here is the generic code */ 803 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 804 if (JNU_IsNull(env, jdata)) { 805 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 806 return -1; 807 } 808 if (band >= 0) { 809 int dOff; 810 if (band >= numBands) { 811 (*env)->DeleteLocalRef(env, jdata); 812 JNU_ThrowInternalError(env, "Band out of range."); 813 return -1; 814 } 815 off = 0; 816 for (y=0; y < h; y+=maxLines) { 817 if (y+maxLines > h) { 818 maxBytes = w*numBands; 819 maxLines = h - y; 820 } 821 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 822 NULL); 823 if (dataP == NULL) { 824 (*env)->DeleteLocalRef(env, jdata); 825 return -1; 826 } 827 dOff = band; 828 for (i=0; i < maxBytes; i++, dOff += numBands) { 829 dataP[dOff] = bufferP[off++]; 830 } 831 832 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 833 JNI_ABORT); 834 835 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 836 0, y, w, 837 maxLines, jdata, jdatabuffer); 838 } 839 } 840 else { 841 off = 0; 842 maxBytes *= numBands; 843 for (y=0; y < h; y+=maxLines) { 844 if (y+maxLines > h) { 845 maxBytes = w*numBands; 846 maxLines = h - y; 847 } 848 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 849 NULL); 850 if (dataP == NULL) { 851 (*env)->DeleteLocalRef(env, jdata); 852 return -1; 853 } 854 for (i=0; i < maxBytes; i++) { 855 dataP[i] = bufferP[off++]; 856 } 857 858 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 859 JNI_ABORT); 860 861 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 862 0, y, w, 863 maxLines, jdata, jdatabuffer); 864 } 865 866 } 867 868 (*env)->DeleteLocalRef(env, jdata); 869 870 return 0; 871 } 872 int awt_getPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, 873 unsigned short *bufferP) { 874 int w = rasterP->width; 875 int h = rasterP->height; 876 int numBands = rasterP->numBands; 877 int y; 878 int i; 879 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 880 jobject jsm; 881 int off; 882 jarray jdata = NULL; 883 jobject jdatabuffer; 884 int *dataP; 885 int maxBytes = w*maxLines; 886 887 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 888 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 889 g_RasterDataBufferID); 890 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 891 if (JNU_IsNull(env, jdata)) { 892 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 893 return -1; 894 } 895 /* Here is the generic code */ 896 if (band >= 0) { 897 int dOff; 898 if (band >= numBands) { 899 (*env)->DeleteLocalRef(env, jdata); 900 JNU_ThrowInternalError(env, "Band out of range."); 901 return -1; 902 } 903 off = 0; 904 for (y=0; y < h; y += maxLines) { 905 if (y+maxLines > h) { 906 maxBytes = w*numBands; 907 maxLines = h - y; 908 } 909 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 910 0, y, w, 911 maxLines, jdata, jdatabuffer); 912 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 913 NULL); 914 if (dataP == NULL) { 915 (*env)->DeleteLocalRef(env, jdata); 916 return -1; 917 } 918 919 dOff = band; 920 for (i=0; i < maxBytes; i++, dOff += numBands) { 921 bufferP[off++] = (unsigned short) dataP[dOff]; 922 } 923 924 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 925 JNI_ABORT); 926 } 927 } 928 else { 929 off = 0; 930 maxBytes *= numBands; 931 for (y=0; y < h; y+=maxLines) { 932 if (y+maxLines > h) { 933 maxBytes = w*numBands; 934 maxLines = h - y; 935 } 936 (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, 937 0, y, w, 938 maxLines, jdata, jdatabuffer); 939 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 940 NULL); 941 if (dataP == NULL) { 942 (*env)->DeleteLocalRef(env, jdata); 943 return -1; 944 } 945 for (i=0; i < maxBytes; i++) { 946 bufferP[off++] = (unsigned short) dataP[i]; 947 } 948 949 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 950 JNI_ABORT); 951 } 952 953 } 954 955 (*env)->DeleteLocalRef(env, jdata); 956 return 0; 957 } 958 int awt_setPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, 959 unsigned short *bufferP) { 960 int w = rasterP->width; 961 int h = rasterP->height; 962 int numBands = rasterP->numBands; 963 int y; 964 int i; 965 int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); 966 jobject jsm; 967 int off; 968 jarray jdata = NULL; 969 jobject jdatabuffer; 970 int *dataP; 971 int maxBytes = w; 972 973 jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); 974 jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, 975 g_RasterDataBufferID); 976 /* Here is the generic code */ 977 jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); 978 if (JNU_IsNull(env, jdata)) { 979 JNU_ThrowOutOfMemoryError(env, "Out of Memory"); 980 return -1; 981 } 982 if (band >= 0) { 983 int dOff; 984 if (band >= numBands) { 985 (*env)->DeleteLocalRef(env, jdata); 986 JNU_ThrowInternalError(env, "Band out of range."); 987 return -1; 988 } 989 off = 0; 990 for (y=0; y < h; y+=maxLines) { 991 if (y+maxLines > h) { 992 maxBytes = w*numBands; 993 maxLines = h - y; 994 } 995 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 996 NULL); 997 if (dataP == NULL) { 998 (*env)->DeleteLocalRef(env, jdata); 999 return -1; 1000 } 1001 dOff = band; 1002 for (i=0; i < maxBytes; i++, dOff += numBands) { 1003 dataP[dOff] = bufferP[off++]; 1004 } 1005 1006 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 1007 JNI_ABORT); 1008 1009 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 1010 0, y, w, 1011 maxLines, jdata, jdatabuffer); 1012 } 1013 } 1014 else { 1015 off = 0; 1016 maxBytes *= numBands; 1017 for (y=0; y < h; y+=maxLines) { 1018 if (y+maxLines > h) { 1019 maxBytes = w*numBands; 1020 maxLines = h - y; 1021 } 1022 dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, 1023 NULL); 1024 if (dataP == NULL) { 1025 (*env)->DeleteLocalRef(env, jdata); 1026 return -1; 1027 } 1028 for (i=0; i < maxBytes; i++) { 1029 dataP[i] = bufferP[off++]; 1030 } 1031 1032 (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, 1033 JNI_ABORT); 1034 1035 (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, 1036 0, y, w, 1037 maxLines, jdata, jdatabuffer); 1038 } 1039 1040 } 1041 1042 (*env)->DeleteLocalRef(env, jdata); 1043 return 0; 1044 }