Path: blob/master/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c
41159 views
/*1* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdio.h>26#include <stdlib.h>27#include "awt_parseImage.h"28#include "imageInitIDs.h"29#include "java_awt_Transparency.h"30#include "java_awt_image_BufferedImage.h"31#include "sun_awt_image_IntegerComponentRaster.h"32#include "sun_awt_image_ImagingLib.h"33#include "java_awt_color_ColorSpace.h"34#include "awt_Mlib.h"35#include "safe_alloc.h"36#include "safe_math.h"3738static int setHints(JNIEnv *env, BufImageS_t *imageP);39404142/* Parse the buffered image. All of the raster information is returned in the43* imagePP structure.44*45* The handleCustom parameter specifies whether or not the caller46* can use custom channels. If it is false and a custom channel47* is encountered, the returned value will be 0 and all structures48* will be deallocated.49*50* Return value:51* -1: Exception52* 0: Can't do it.53* 1: Success54*/55int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP,56int handleCustom) {57BufImageS_t *imageP;58int status;59jobject jraster;60jobject jcmodel;6162/* Make sure the image exists */63if (JNU_IsNull(env, jimage)) {64JNU_ThrowNullPointerException(env, "null BufferedImage object");65return -1;66}6768if ((imageP = (BufImageS_t *) calloc(1, sizeof(BufImageS_t))) == NULL) {69JNU_ThrowOutOfMemoryError(env, "Out of memory");70return -1;71}72imageP->jimage = jimage;7374/* Retrieve the raster */75if ((jraster = (*env)->GetObjectField(env, jimage,76g_BImgRasterID)) == NULL) {77free((void *) imageP);78JNU_ThrowNullPointerException(env, "null Raster object");79return 0;80}8182/* Retrieve the image type */83imageP->imageType = (*env)->GetIntField(env, jimage, g_BImgTypeID);8485/* Parse the raster */86if ((status = awt_parseRaster(env, jraster, &imageP->raster)) <= 0) {87free((void *)imageP);88return status;89}9091/* Retrieve the color model */92if ((jcmodel = (*env)->GetObjectField(env, jimage, g_BImgCMID)) == NULL) {93free((void *) imageP);94JNU_ThrowNullPointerException(env, "null Raster object");95return 0;96}9798/* Parse the color model */99if ((status = awt_parseColorModel(env, jcmodel, imageP->imageType,100&imageP->cmodel)) <= 0) {101awt_freeParsedRaster(&imageP->raster, FALSE);102free((void *)imageP);103return 0;104}105106/* Set hints */107if ((status = setHints(env, imageP)) <= 0) {108awt_freeParsedImage(imageP, TRUE);109return 0;110}111112*imagePP = imageP;113114return status;115}116117/* Verifies whether the channel offsets are sane and correspond to the type of118* the raster.119*120* Return value:121* 0: Failure: channel offsets are invalid122* 1: Success123*/124static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) {125int i, lastPixelOffset, lastScanOffset;126switch (rasterP->rasterType) {127case COMPONENT_RASTER_TYPE:128if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) {129return 0;130}131if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) {132return 0;133}134135lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride;136lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride;137138139if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) {140return 0;141}142143lastPixelOffset += lastScanOffset;144145for (i = 0; i < rasterP->numDataElements; i++) {146int off = rasterP->chanOffsets[i];147int size = lastPixelOffset + off;148149if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) {150return 0;151}152153if (size < lastPixelOffset || size >= dataArrayLength) {154// an overflow, or insufficient buffer capacity155return 0;156}157}158return 1;159case BANDED_RASTER_TYPE:160// NB:caller does not support the banded rasters yet,161// so this branch of the code must be re-defined in162// order to provide valid criteria for the data offsets163// verification, when/if banded rasters will be supported.164// At the moment, we prohibit banded rasters as well.165return 0;166default:167// PACKED_RASTER_TYPE: does not support channel offsets168// UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error169return 0;170}171}172173/* Parse the raster. All of the raster information is returned in the174* rasterP structure.175*176* Return value:177* -1: Exception178* 0: Can't do it (Custom channel)179* 1: Success180*/181int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {182jobject joffs = NULL;183/* int status;*/184jclass singlePixelPackedSampleModelClass = NULL;185jclass integerComponentRasterClass = NULL;186jclass byteComponentRasterClass = NULL;187jclass shortComponentRasterClass = NULL;188jclass bytePackedRasterClass = NULL;189190if (JNU_IsNull(env, jraster)) {191JNU_ThrowNullPointerException(env, "null Raster object");192return -1;193}194195rasterP->jraster = jraster;196rasterP->width = (*env)->GetIntField(env, jraster, g_RasterWidthID);197rasterP->height = (*env)->GetIntField(env, jraster, g_RasterHeightID);198rasterP->numDataElements = (*env)->GetIntField(env, jraster,199g_RasterNumDataElementsID);200rasterP->numBands = (*env)->GetIntField(env, jraster,201g_RasterNumBandsID);202203rasterP->baseOriginX = (*env)->GetIntField(env, jraster,204g_RasterBaseOriginXID);205rasterP->baseOriginY = (*env)->GetIntField(env, jraster,206g_RasterBaseOriginYID);207rasterP->minX = (*env)->GetIntField(env, jraster, g_RasterMinXID);208rasterP->minY = (*env)->GetIntField(env, jraster, g_RasterMinYID);209210rasterP->jsampleModel = (*env)->GetObjectField(env, jraster,211g_RasterSampleModelID);212213if (JNU_IsNull(env, rasterP->jsampleModel)) {214JNU_ThrowNullPointerException(env, "null Raster object");215return -1;216}217218// make sure that the raster type is initialized219rasterP->rasterType = UNKNOWN_RASTER_TYPE;220221if (rasterP->numBands <= 0 ||222rasterP->numBands > MAX_NUMBANDS)223{224/*225* we can't handle such kind of rasters due to limitations226* of SPPSampleModelS_t structure and expand/set methods.227*/228return 0;229}230231rasterP->sppsm.isUsed = 0;232233singlePixelPackedSampleModelClass = (*env)->FindClass(env,234"java/awt/image/SinglePixelPackedSampleModel");235CHECK_NULL_RETURN(singlePixelPackedSampleModelClass, -1);236if ((*env)->IsInstanceOf(env, rasterP->jsampleModel,237singlePixelPackedSampleModelClass)) {238jobject jmask, joffs, jnbits;239240rasterP->sppsm.isUsed = 1;241242rasterP->sppsm.maxBitSize = (*env)->GetIntField(env,243rasterP->jsampleModel,244g_SPPSMmaxBitID);245jmask = (*env)->GetObjectField(env, rasterP->jsampleModel,246g_SPPSMmaskArrID);247joffs = (*env)->GetObjectField(env, rasterP->jsampleModel,248g_SPPSMmaskOffID);249jnbits = (*env)->GetObjectField(env, rasterP->jsampleModel,250g_SPPSMnBitsID);251if (jmask == NULL || joffs == NULL || jnbits == NULL ||252rasterP->sppsm.maxBitSize < 0)253{254JNU_ThrowInternalError(env, "Can't grab SPPSM fields");255return -1;256}257(*env)->GetIntArrayRegion(env, jmask, 0,258rasterP->numBands, rasterP->sppsm.maskArray);259(*env)->GetIntArrayRegion(env, joffs, 0,260rasterP->numBands, rasterP->sppsm.offsets);261(*env)->GetIntArrayRegion(env, jnbits, 0,262rasterP->numBands, rasterP->sppsm.nBits);263264}265rasterP->baseRasterWidth = (*env)->GetIntField(env, rasterP->jsampleModel,266g_SMWidthID);267rasterP->baseRasterHeight = (*env)->GetIntField(env,268rasterP->jsampleModel,269g_SMHeightID);270271integerComponentRasterClass = (*env)->FindClass(env, "sun/awt/image/IntegerComponentRaster");272CHECK_NULL_RETURN(integerComponentRasterClass, -1);273byteComponentRasterClass = (*env)->FindClass(env, "sun/awt/image/ByteComponentRaster");274CHECK_NULL_RETURN(byteComponentRasterClass, -1);275shortComponentRasterClass = (*env)->FindClass(env,"sun/awt/image/ShortComponentRaster");276CHECK_NULL_RETURN(shortComponentRasterClass, -1);277bytePackedRasterClass = (*env)->FindClass(env, "sun/awt/image/BytePackedRaster");278CHECK_NULL_RETURN(bytePackedRasterClass, -1);279if ((*env)->IsInstanceOf(env, jraster, integerComponentRasterClass)){280rasterP->jdata = (*env)->GetObjectField(env, jraster, g_ICRdataID);281rasterP->dataType = INT_DATA_TYPE;282rasterP->dataSize = 4;283rasterP->dataIsShared = TRUE;284rasterP->rasterType = COMPONENT_RASTER_TYPE;285rasterP->type = (*env)->GetIntField(env, jraster, g_ICRtypeID);286rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_ICRscanstrID);287rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_ICRpixstrID);288joffs = (*env)->GetObjectField(env, jraster, g_ICRdataOffsetsID);289}290else if ((*env)->IsInstanceOf(env, jraster, byteComponentRasterClass)){291rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BCRdataID);292rasterP->dataType = BYTE_DATA_TYPE;293rasterP->dataSize = 1;294rasterP->dataIsShared = TRUE;295rasterP->rasterType = COMPONENT_RASTER_TYPE;296rasterP->type = (*env)->GetIntField(env, jraster, g_BCRtypeID);297rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BCRscanstrID);298rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BCRpixstrID);299joffs = (*env)->GetObjectField(env, jraster, g_BCRdataOffsetsID);300}301else if ((*env)->IsInstanceOf(env, jraster, shortComponentRasterClass)){302rasterP->jdata = (*env)->GetObjectField(env, jraster, g_SCRdataID);303rasterP->dataType = SHORT_DATA_TYPE;304rasterP->dataSize = 2;305rasterP->dataIsShared = TRUE;306rasterP->rasterType = COMPONENT_RASTER_TYPE;307rasterP->type = (*env)->GetIntField(env, jraster, g_SCRtypeID);308rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_SCRscanstrID);309rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_SCRpixstrID);310joffs = (*env)->GetObjectField(env, jraster, g_SCRdataOffsetsID);311}312else if ((*env)->IsInstanceOf(env, jraster, bytePackedRasterClass)){313rasterP->rasterType = PACKED_RASTER_TYPE;314rasterP->dataType = BYTE_DATA_TYPE;315rasterP->dataSize = 1;316rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BPRscanstrID);317rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BPRpixstrID);318rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BPRdataID);319rasterP->type = (*env)->GetIntField(env, jraster, g_BPRtypeID);320rasterP->chanOffsets = NULL;321if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {322rasterP->chanOffsets =323(jint *)malloc(rasterP->numDataElements * sizeof(jint));324}325if (rasterP->chanOffsets == NULL) {326/* Out of memory */327JNU_ThrowOutOfMemoryError(env, "Out of memory");328return -1;329}330rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID);331rasterP->dataType = BYTE_DATA_TYPE;332}333else {334rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM;335rasterP->dataType = UNKNOWN_DATA_TYPE;336rasterP->rasterType = UNKNOWN_RASTER_TYPE;337rasterP->chanOffsets = NULL;338/* Custom raster */339return 0;340}341342// do basic validation of the raster structure343if (rasterP->width <= 0 || rasterP->height <= 0 ||344rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0)345{346// invalid raster347return -1;348}349350// channel (data) offsets351switch (rasterP->rasterType) {352case COMPONENT_RASTER_TYPE:353case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment354// get channel (data) offsets355rasterP->chanOffsets = NULL;356if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {357rasterP->chanOffsets =358(jint *)malloc(rasterP->numDataElements * sizeof(jint));359}360if (rasterP->chanOffsets == NULL) {361/* Out of memory */362JNU_ThrowOutOfMemoryError(env, "Out of memory");363return -1;364}365(*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements,366rasterP->chanOffsets);367if (rasterP->jdata == NULL) {368// unable to verify the raster369return -1;370}371// verify whether channel offsets look sane372if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) {373return -1;374}375break;376default:377; // PACKED_RASTER_TYPE does not use the channel offsets.378}379380/* additional check for sppsm fields validity: make sure that381* size of raster samples doesn't exceed the data type capacity.382*/383if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */384rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */385rasterP->sppsm.maxBitSize > (rasterP->dataSize * 8))386{387JNU_ThrowInternalError(env, "Raster samples are too big");388return -1;389}390391#if 0392fprintf(stderr,"---------------------\n");393fprintf(stderr,"Width : %d\n",rasterP->width);394fprintf(stderr,"Height : %d\n",rasterP->height);395fprintf(stderr,"X : %d\n",rasterP->x);396fprintf(stderr,"Y : %d\n",rasterP->y);397fprintf(stderr,"numC : %d\n",rasterP->numDataElements);398fprintf(stderr,"SS : %d\n",rasterP->scanlineStride);399fprintf(stderr,"PS : %d\n",rasterP->pixelStride);400fprintf(stderr,"CO : %d\n",rasterP->chanOffsets);401fprintf(stderr,"shared?: %d\n",rasterP->dataIsShared);402fprintf(stderr,"RasterT: %d\n",rasterP->rasterType);403fprintf(stderr,"DataT : %d\n",rasterP->dataType);404fprintf(stderr,"---------------------\n");405#endif406407return 1;408}409410static int getColorModelType(JNIEnv *env, jobject jcmodel) {411jclass colorModelClass;412413colorModelClass = (*env)->FindClass(env,414"java/awt/image/IndexColorModel");415CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);416417if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass))418{419return INDEX_CM_TYPE;420}421422colorModelClass = (*env)->FindClass(env,423"java/awt/image/PackedColorModel");424CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);425if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass))426{427colorModelClass = (*env)->FindClass(env,428"java/awt/image/DirectColorModel");429CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);430if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass)) {431return DIRECT_CM_TYPE;432}433else {434return PACKED_CM_TYPE;435}436}437colorModelClass = (*env)->FindClass(env,438"java/awt/image/ComponentColorModel");439CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);440if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass))441{442return COMPONENT_CM_TYPE;443}444445return UNKNOWN_CM_TYPE;446}447448int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType,449ColorModelS_t *cmP) {450/*jmethodID jID; */451jobject jnBits;452jsize nBitsLength;453454int i;455static jobject s_jdefCM = NULL;456457if (JNU_IsNull(env, jcmodel)) {458JNU_ThrowNullPointerException(env, "null ColorModel object");459return -1;460}461462cmP->jcmodel = jcmodel;463464cmP->jcspace = (*env)->GetObjectField(env, jcmodel, g_CMcspaceID);465466cmP->numComponents = (*env)->GetIntField(env, jcmodel,467g_CMnumComponentsID);468cmP->supportsAlpha = (*env)->GetBooleanField(env, jcmodel,469g_CMsuppAlphaID);470cmP->isAlphaPre = (*env)->GetBooleanField(env,jcmodel,471g_CMisAlphaPreID);472cmP->transparency = (*env)->GetIntField(env, jcmodel,473g_CMtransparencyID);474475jnBits = (*env)->GetObjectField(env, jcmodel, g_CMnBitsID);476if (jnBits == NULL) {477JNU_ThrowNullPointerException(env, "null nBits structure in CModel");478return -1;479}480481nBitsLength = (*env)->GetArrayLength(env, jnBits);482if (nBitsLength != cmP->numComponents) {483// invalid number of components?484return -1;485}486487cmP->nBits = NULL;488if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) {489cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint));490}491492if (cmP->nBits == NULL){493JNU_ThrowOutOfMemoryError(env, "Out of memory");494return -1;495}496(*env)->GetIntArrayRegion(env, jnBits, 0, cmP->numComponents,497cmP->nBits);498cmP->maxNbits = 0;499for (i=0; i < cmP->numComponents; i++) {500if (cmP->maxNbits < cmP->nBits[i]) {501cmP->maxNbits = cmP->nBits[i];502}503}504505cmP->is_sRGB = (*env)->GetBooleanField(env, cmP->jcmodel, g_CMis_sRGBID);506507cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID);508509cmP->cmType = getColorModelType(env, jcmodel);510JNU_CHECK_EXCEPTION_RETURN(env, -1);511512cmP->isDefaultCM = FALSE;513cmP->isDefaultCompatCM = FALSE;514515/* look for standard cases */516if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB) {517cmP->isDefaultCM = TRUE;518cmP->isDefaultCompatCM = TRUE;519} else if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||520imageType == java_awt_image_BufferedImage_TYPE_INT_RGB ||521imageType == java_awt_image_BufferedImage_TYPE_INT_BGR ||522imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||523imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)524{525cmP->isDefaultCompatCM = TRUE;526}527else {528/* Figure out if this is the default CM */529if (s_jdefCM == NULL) {530jobject defCM;531jclass jcm = (*env)->FindClass(env, "java/awt/image/ColorModel");532CHECK_NULL_RETURN(jcm, -1);533defCM = (*env)->CallStaticObjectMethod(env, jcm,534g_CMgetRGBdefaultMID, NULL);535s_jdefCM = (*env)->NewGlobalRef(env, defCM);536if (defCM == NULL || s_jdefCM == NULL) {537(*env)->ExceptionClear(env);538JNU_ThrowNullPointerException(env, "Unable to find default CM");539return -1;540}541}542cmP->isDefaultCM = ((*env)->IsSameObject(env, s_jdefCM, jcmodel));543cmP->isDefaultCompatCM = cmP->isDefaultCM;544}545546/* check whether image attributes correspond to default cm */547if (cmP->isDefaultCompatCM) {548if (cmP->csType != java_awt_color_ColorSpace_TYPE_RGB ||549!cmP->is_sRGB)550{551return -1;552}553554for (i = 0; i < cmP->numComponents; i++) {555if (cmP->nBits[i] != 8) {556return -1;557}558}559}560561/* Get index color model attributes */562if (imageType == java_awt_image_BufferedImage_TYPE_BYTE_INDEXED ||563cmP->cmType == INDEX_CM_TYPE)564{565cmP->transIdx = (*env)->GetIntField(env, jcmodel, g_ICMtransIdxID);566cmP->mapSize = (*env)->GetIntField(env, jcmodel, g_ICMmapSizeID);567cmP->jrgb = (*env)->GetObjectField(env, jcmodel, g_ICMrgbID);568if (cmP->transIdx == -1) {569/* Need to find the transparent index */570int *rgb = (int *) (*env)->GetPrimitiveArrayCritical(env,571cmP->jrgb,572NULL);573if (rgb == NULL) {574return -1;575}576for (i=0; i < cmP->mapSize; i++) {577if ((rgb[i]&0xff000000) == 0) {578cmP->transIdx = i;579break;580}581}582(*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb,583JNI_ABORT);584if (cmP->transIdx == -1) {585/* Now what? No transparent pixel... */586cmP->transIdx = 0;587}588}589}590591return 1;592}593594void awt_freeParsedRaster(RasterS_t *rasterP, int freeRasterP) {595if (rasterP->chanOffsets) {596free((void *) rasterP->chanOffsets);597}598599if (freeRasterP) {600free((void *) rasterP);601}602}603604void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) {605if (imageP->hints.colorOrder) {606free ((void *) imageP->hints.colorOrder);607}608609if (imageP->cmodel.nBits) {610free ((void *) imageP->cmodel.nBits);611}612613/* Free the raster */614awt_freeParsedRaster(&imageP->raster, FALSE);615616if (freeImageP) {617free((void *) imageP);618}619}620621static void622awt_getBIColorOrder(int type, int *colorOrder) {623switch(type) {624case java_awt_image_BufferedImage_TYPE_INT_ARGB:625case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE:626#ifdef _LITTLE_ENDIAN627colorOrder[0] = 2;628colorOrder[1] = 1;629colorOrder[2] = 0;630colorOrder[3] = 3;631#else632colorOrder[0] = 1;633colorOrder[1] = 2;634colorOrder[2] = 3;635colorOrder[3] = 0;636#endif637break;638case java_awt_image_BufferedImage_TYPE_INT_BGR:639#ifdef _LITTLE_ENDIAN640colorOrder[0] = 0;641colorOrder[1] = 1;642colorOrder[2] = 2;643#else644colorOrder[0] = 3;645colorOrder[1] = 2;646colorOrder[2] = 1;647#endif648break;649case java_awt_image_BufferedImage_TYPE_INT_RGB:650#ifdef _LITTLE_ENDIAN651colorOrder[0] = 2;652colorOrder[1] = 1;653colorOrder[2] = 0;654#else655colorOrder[0] = 1;656colorOrder[1] = 2;657colorOrder[2] = 3;658#endif659break;660case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR:661case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE:662colorOrder[0] = 3;663colorOrder[1] = 2;664colorOrder[2] = 1;665colorOrder[3] = 0;666break;667case java_awt_image_BufferedImage_TYPE_3BYTE_BGR:668colorOrder[0] = 2;669colorOrder[1] = 1;670colorOrder[2] = 0;671break;672case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB:673case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB:674colorOrder[0] = 0;675colorOrder[1] = 1;676colorOrder[2] = 2;677break;678case java_awt_image_BufferedImage_TYPE_BYTE_GRAY:679case java_awt_image_BufferedImage_TYPE_USHORT_GRAY:680case java_awt_image_BufferedImage_TYPE_BYTE_BINARY:681case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED:682colorOrder[0] = 0;683break;684}685}686687static int688setHints(JNIEnv *env, BufImageS_t *imageP) {689HintS_t *hintP = &imageP->hints;690RasterS_t *rasterP = &imageP->raster;691ColorModelS_t *cmodelP = &imageP->cmodel;692int imageType = imageP->imageType;693694// check whether raster and color model are compatible695if (cmodelP->numComponents != rasterP->numBands) {696if (cmodelP->cmType != INDEX_CM_TYPE) {697return -1;698}699}700701hintP->numChans = imageP->cmodel.numComponents;702hintP->colorOrder = NULL;703if (SAFE_TO_ALLOC_2(hintP->numChans, sizeof(int))) {704hintP->colorOrder = (int *)malloc(hintP->numChans * sizeof(int));705}706if (hintP->colorOrder == NULL) {707JNU_ThrowOutOfMemoryError(env, "Out of memory");708return -1;709}710if (imageType != java_awt_image_BufferedImage_TYPE_CUSTOM) {711awt_getBIColorOrder(imageType, hintP->colorOrder);712}713if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||714imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||715imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)716{717hintP->channelOffset = rasterP->chanOffsets[0];718/* These hints are #bytes */719hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;720hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;721hintP->pStride = rasterP->pixelStride*rasterP->dataSize;722hintP->packing = BYTE_INTERLEAVED;723} else if (imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||724imageType==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE||725imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR ||726imageType == java_awt_image_BufferedImage_TYPE_INT_BGR)727{728if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) {729hintP->channelOffset = rasterP->chanOffsets[0];730}731else {732hintP->channelOffset = rasterP->chanOffsets[hintP->numChans-1];733}734hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;735hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;736hintP->pStride = rasterP->pixelStride*rasterP->dataSize;737hintP->packing = BYTE_INTERLEAVED;738} else if (imageType==java_awt_image_BufferedImage_TYPE_USHORT_565_RGB ||739imageType==java_awt_image_BufferedImage_TYPE_USHORT_555_RGB) {740hintP->needToExpand = TRUE;741hintP->expandToNbits = 8;742hintP->packing = PACKED_SHORT_INTER;743} else if (cmodelP->cmType == INDEX_CM_TYPE) {744int i;745hintP->numChans = 1;746hintP->channelOffset = rasterP->chanOffsets[0];747hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;748hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;749hintP->pStride = rasterP->pixelStride*rasterP->dataSize;750switch(rasterP->dataType ) {751case BYTE_DATA_TYPE:752if (rasterP->rasterType == PACKED_RASTER_TYPE) {753hintP->needToExpand = TRUE;754hintP->expandToNbits = 8;755hintP->packing = BYTE_PACKED_BAND;756}757else {758hintP->packing = BYTE_SINGLE_BAND;759}760break;761case SHORT_DATA_TYPE:762hintP->packing = SHORT_SINGLE_BAND;763break;764case INT_DATA_TYPE:765default:766hintP->packing = UNKNOWN_PACKING;767break;768}769for (i=0; i < hintP->numChans; i++) {770hintP->colorOrder[i] = i;771}772}773else if (cmodelP->cmType == COMPONENT_CM_TYPE) {774/* Figure out if it is interleaved */775int bits=1;776int i;777int low = rasterP->chanOffsets[0];778int diff;779int banded = 0;780for (i=1; i < hintP->numChans; i++) {781if (rasterP->chanOffsets[i] < low) {782low = rasterP->chanOffsets[i];783}784}785for (i=1; i < hintP->numChans; i++) {786diff = rasterP->chanOffsets[i]-low;787if (diff < hintP->numChans) {788if (bits & (1<<diff)) {789/* Overlapping samples */790/* Could just copy */791return -1;792}793bits |= (1<<diff);794}795else if (diff >= rasterP->width) {796banded = 1;797}798/* Ignore the case if bands are overlapping */799}800hintP->channelOffset = low;801hintP->dataOffset = low*rasterP->dataSize;802hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;803hintP->pStride = rasterP->pixelStride*rasterP->dataSize;804switch(rasterP->dataType) {805case BYTE_DATA_TYPE:806hintP->packing = BYTE_COMPONENTS;807break;808case SHORT_DATA_TYPE:809hintP->packing = SHORT_COMPONENTS;810break;811default:812/* Don't handle any other case */813return -1;814}815if (bits == ((1<<hintP->numChans)-1)) {816hintP->packing |= INTERLEAVED;817for (i=0; i < hintP->numChans; i++) {818hintP->colorOrder[rasterP->chanOffsets[i]-low] = i;819}820}821else if (banded == 1) {822int bandSize = rasterP->width*rasterP->height;823hintP->packing |= BANDED;824for (i=0; i < hintP->numChans; i++) {825/* REMIND: Not necessarily correct */826hintP->colorOrder[(rasterP->chanOffsets[i]-low)%bandSize] = i;827}828}829else {830return -1;831}832}833else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) {834int i;835836/* do some sanity check first: make sure that837* - sample model is SinglePixelPackedSampleModel838* - number of bands in the raster corresponds to the number839* of color components in the color model840*/841if (!rasterP->sppsm.isUsed ||842rasterP->numBands != cmodelP->numComponents)843{844/* given raster is not compatible with the color model,845* so the operation has to be aborted.846*/847return -1;848}849850if (cmodelP->maxNbits > 8) {851hintP->needToExpand = TRUE;852hintP->expandToNbits = cmodelP->maxNbits;853}854else {855for (i=0; i < rasterP->numBands; i++) {856if (!(rasterP->sppsm.offsets[i] % 8)) {857hintP->needToExpand = TRUE;858hintP->expandToNbits = 8;859break;860}861else {862hintP->colorOrder[i] = rasterP->sppsm.offsets[i]>>3;863}864}865}866867hintP->channelOffset = rasterP->chanOffsets[0];868hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;869hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;870hintP->pStride = rasterP->pixelStride*rasterP->dataSize;871if (hintP->needToExpand) {872switch(rasterP->dataType) {873case BYTE_DATA_TYPE:874hintP->packing = PACKED_BYTE_INTER;875break;876case SHORT_DATA_TYPE:877hintP->packing = PACKED_SHORT_INTER;878break;879case INT_DATA_TYPE:880hintP->packing = PACKED_INT_INTER;881break;882default:883/* Don't know what it is */884return -1;885}886}887else {888hintP->packing = BYTE_INTERLEAVED;889890}891}892else {893/* REMIND: Need to handle more cases */894return -1;895}896897return 1;898}899900#define MAX_TO_GRAB (10240)901902typedef union {903void *pv;904unsigned char *pb;905unsigned short *ps;906} PixelData_t;907908909int awt_getPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) {910const int w = rasterP->width;911const int h = rasterP->height;912const int numBands = rasterP->numBands;913int y;914int i;915int maxLines;916jobject jsm;917int off = 0;918jarray jdata = NULL;919jobject jdatabuffer;920int *dataP;921int maxSamples;922PixelData_t p;923924if (bufferP == NULL) {925return -1;926}927928if (rasterP->dataType != BYTE_DATA_TYPE &&929rasterP->dataType != SHORT_DATA_TYPE)930{931return -1;932}933934p.pv = bufferP;935936if (!SAFE_TO_MULT(w, numBands)) {937return -1;938}939maxSamples = w * numBands;940941maxLines = maxSamples > MAX_TO_GRAB ? 1 : (MAX_TO_GRAB / maxSamples);942if (maxLines > h) {943maxLines = h;944}945946if (!SAFE_TO_MULT(maxSamples, maxLines)) {947return -1;948}949950maxSamples *= maxLines;951952jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);953jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,954g_RasterDataBufferID);955956jdata = (*env)->NewIntArray(env, maxSamples);957if (JNU_IsNull(env, jdata)) {958(*env)->ExceptionClear(env);959JNU_ThrowOutOfMemoryError(env, "Out of Memory");960return -1;961}962963for (y = 0; y < h; y += maxLines) {964if (y + maxLines > h) {965maxLines = h - y;966maxSamples = w * numBands * maxLines;967}968969(*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID,9700, y, w,971maxLines, jdata, jdatabuffer);972973if ((*env)->ExceptionOccurred(env)) {974(*env)->DeleteLocalRef(env, jdata);975return -1;976}977978dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,979NULL);980if (dataP == NULL) {981(*env)->DeleteLocalRef(env, jdata);982return -1;983}984985switch (rasterP->dataType) {986case BYTE_DATA_TYPE:987for (i = 0; i < maxSamples; i ++) {988p.pb[off++] = (unsigned char) dataP[i];989}990break;991case SHORT_DATA_TYPE:992for (i = 0; i < maxSamples; i ++) {993p.ps[off++] = (unsigned short) dataP[i];994}995break;996}997998(*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,999JNI_ABORT);1000}1001(*env)->DeleteLocalRef(env, jdata);10021003return 1;1004}10051006int awt_setPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) {1007const int w = rasterP->width;1008const int h = rasterP->height;1009const int numBands = rasterP->numBands;10101011int y;1012int i;1013int maxLines;1014jobject jsm;1015int off = 0;1016jarray jdata = NULL;1017jobject jdatabuffer;1018int *dataP;1019int maxSamples;1020PixelData_t p;10211022if (bufferP == NULL) {1023return -1;1024}10251026if (rasterP->dataType != BYTE_DATA_TYPE &&1027rasterP->dataType != SHORT_DATA_TYPE)1028{1029return -1;1030}10311032p.pv = bufferP;10331034if (!SAFE_TO_MULT(w, numBands)) {1035return -1;1036}1037maxSamples = w * numBands;10381039maxLines = maxSamples > MAX_TO_GRAB ? 1 : (MAX_TO_GRAB / maxSamples);1040if (maxLines > h) {1041maxLines = h;1042}10431044if (!SAFE_TO_MULT(maxSamples, maxLines)) {1045return -1;1046}10471048maxSamples *= maxLines;10491050jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);1051jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,1052g_RasterDataBufferID);10531054jdata = (*env)->NewIntArray(env, maxSamples);1055if (JNU_IsNull(env, jdata)) {1056(*env)->ExceptionClear(env);1057JNU_ThrowOutOfMemoryError(env, "Out of Memory");1058return -1;1059}10601061for (y = 0; y < h; y += maxLines) {1062if (y + maxLines > h) {1063maxLines = h - y;1064maxSamples = w * numBands * maxLines;1065}1066dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,1067NULL);1068if (dataP == NULL) {1069(*env)->DeleteLocalRef(env, jdata);1070return -1;1071}10721073switch (rasterP->dataType) {1074case BYTE_DATA_TYPE:1075for (i = 0; i < maxSamples; i ++) {1076dataP[i] = p.pb[off++];1077}1078break;1079case SHORT_DATA_TYPE:1080for (i = 0; i < maxSamples; i ++) {1081dataP[i] = p.ps[off++];1082}1083break;1084}10851086(*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,1087JNI_ABORT);10881089(*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID,10900, y, w,1091maxLines, jdata, jdatabuffer);10921093if ((*env)->ExceptionOccurred(env)) {1094(*env)->DeleteLocalRef(env, jdata);1095return -1;1096}1097}10981099(*env)->DeleteLocalRef(env, jdata);11001101return 1;1102}110311041105