0N/A/*
3909N/A * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A#include <stdio.h>
0N/A#include <stdlib.h>
0N/A#include "awt_parseImage.h"
0N/A#include "imageInitIDs.h"
0N/A#include "java_awt_Transparency.h"
0N/A#include "java_awt_image_BufferedImage.h"
0N/A#include "sun_awt_image_IntegerComponentRaster.h"
0N/A#include "sun_awt_image_ImagingLib.h"
0N/A#include "java_awt_color_ColorSpace.h"
0N/A#include "awt_Mlib.h"
0N/A#include "safe_alloc.h"
5817N/A#include "safe_math.h"
0N/A
0N/Astatic int setHints(JNIEnv *env, BufImageS_t *imageP);
0N/A
0N/A
0N/A
0N/A/* Parse the buffered image. All of the raster information is returned in the
0N/A * imagePP structure.
0N/A *
0N/A * The handleCustom parameter specifies whether or not the caller
0N/A * can use custom channels. If it is false and a custom channel
0N/A * is encountered, the returned value will be 0 and all structures
0N/A * will be deallocated.
0N/A *
0N/A * Return value:
0N/A * -1: Exception
0N/A * 0: Can't do it.
0N/A * 1: Success
0N/A */
0N/Aint awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP,
0N/A int handleCustom) {
0N/A BufImageS_t *imageP;
0N/A int status;
0N/A jobject jraster;
0N/A jobject jcmodel;
0N/A
0N/A /* Make sure the image exists */
0N/A if (JNU_IsNull(env, jimage)) {
0N/A JNU_ThrowNullPointerException(env, "null BufferedImage object");
0N/A return -1;
0N/A }
0N/A
0N/A if ((imageP = (BufImageS_t *) calloc(1, sizeof(BufImageS_t))) == NULL) {
0N/A JNU_ThrowOutOfMemoryError(env, "Out of memory");
0N/A return -1;
0N/A }
0N/A imageP->jimage = jimage;
0N/A
0N/A /* Retrieve the raster */
0N/A if ((jraster = (*env)->GetObjectField(env, jimage,
0N/A g_BImgRasterID)) == NULL) {
0N/A free((void *) imageP);
0N/A JNU_ThrowNullPointerException(env, "null Raster object");
0N/A return 0;
0N/A }
0N/A
0N/A /* Retrieve the image type */
0N/A imageP->imageType = (*env)->GetIntField(env, jimage, g_BImgTypeID);
0N/A
0N/A /* Parse the raster */
0N/A if ((status = awt_parseRaster(env, jraster, &imageP->raster)) <= 0) {
0N/A free((void *)imageP);
0N/A return status;
0N/A }
0N/A
0N/A /* Retrieve the color model */
0N/A if ((jcmodel = (*env)->GetObjectField(env, jimage, g_BImgCMID)) == NULL) {
0N/A free((void *) imageP);
0N/A JNU_ThrowNullPointerException(env, "null Raster object");
0N/A return 0;
0N/A }
0N/A
0N/A /* Parse the color model */
0N/A if ((status = awt_parseColorModel(env, jcmodel, imageP->imageType,
0N/A &imageP->cmodel)) <= 0) {
0N/A awt_freeParsedRaster(&imageP->raster, FALSE);
0N/A free((void *)imageP);
0N/A return 0;
0N/A }
0N/A
0N/A /* Set hints */
0N/A if ((status = setHints(env, imageP)) <= 0) {
0N/A awt_freeParsedImage(imageP, TRUE);
0N/A return 0;
0N/A }
0N/A
0N/A *imagePP = imageP;
0N/A
0N/A return status;
0N/A}
0N/A
5708N/A/* Verifies whether the channel offsets are sane and correspond to the type of
5708N/A * the raster.
5708N/A *
5708N/A * Return value:
5708N/A * 0: Failure: channel offsets are invalid
5708N/A * 1: Success
5708N/A */
5708N/Astatic int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) {
5708N/A int i, lastPixelOffset, lastScanOffset;
5708N/A switch (rasterP->rasterType) {
5708N/A case COMPONENT_RASTER_TYPE:
5708N/A if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) {
5708N/A return 0;
5708N/A }
5708N/A if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) {
5708N/A return 0;
5708N/A }
5708N/A
5708N/A lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride;
5708N/A lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride;
5708N/A
5708N/A
5708N/A if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) {
5708N/A return 0;
5708N/A }
5708N/A
5708N/A lastPixelOffset += lastScanOffset;
5708N/A
5708N/A for (i = 0; i < rasterP->numDataElements; i++) {
5708N/A int off = rasterP->chanOffsets[i];
5708N/A int size = lastPixelOffset + off;
5708N/A
5708N/A if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) {
5708N/A return 0;
5708N/A }
5708N/A
5708N/A if (size < lastPixelOffset || size >= dataArrayLength) {
5708N/A // an overflow, or insufficient buffer capacity
5708N/A return 0;
5708N/A }
5708N/A }
5708N/A return 1;
5708N/A case BANDED_RASTER_TYPE:
5708N/A // NB:caller does not support the banded rasters yet,
5708N/A // so this branch of the code must be re-defined in
5708N/A // order to provide valid criteria for the data offsets
5708N/A // verification, when/if banded rasters will be supported.
5708N/A // At the moment, we prohibit banded rasters as well.
5708N/A return 0;
5708N/A default:
5708N/A // PACKED_RASTER_TYPE: does not support channel offsets
5708N/A // UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error
5708N/A return 0;
5708N/A }
5708N/A}
5708N/A
0N/A/* Parse the raster. All of the raster information is returned in the
0N/A * rasterP structure.
0N/A *
0N/A * Return value:
0N/A * -1: Exception
0N/A * 0: Can't do it (Custom channel)
0N/A * 1: Success
0N/A */
0N/Aint awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
0N/A jobject joffs = NULL;
0N/A /* int status;*/
0N/A
0N/A if (JNU_IsNull(env, jraster)) {
0N/A JNU_ThrowNullPointerException(env, "null Raster object");
0N/A return -1;
0N/A }
0N/A
0N/A rasterP->jraster = jraster;
0N/A rasterP->width = (*env)->GetIntField(env, jraster, g_RasterWidthID);
0N/A rasterP->height = (*env)->GetIntField(env, jraster, g_RasterHeightID);
0N/A rasterP->numDataElements = (*env)->GetIntField(env, jraster,
0N/A g_RasterNumDataElementsID);
0N/A rasterP->numBands = (*env)->GetIntField(env, jraster,
0N/A g_RasterNumBandsID);
0N/A
0N/A rasterP->baseOriginX = (*env)->GetIntField(env, jraster,
0N/A g_RasterBaseOriginXID);
0N/A rasterP->baseOriginY = (*env)->GetIntField(env, jraster,
0N/A g_RasterBaseOriginYID);
0N/A rasterP->minX = (*env)->GetIntField(env, jraster, g_RasterMinXID);
0N/A rasterP->minY = (*env)->GetIntField(env, jraster, g_RasterMinYID);
0N/A
0N/A rasterP->jsampleModel = (*env)->GetObjectField(env, jraster,
0N/A g_RasterSampleModelID);
0N/A
0N/A if (JNU_IsNull(env, rasterP->jsampleModel)) {
0N/A JNU_ThrowNullPointerException(env, "null Raster object");
0N/A return -1;
0N/A }
0N/A
5708N/A // make sure that the raster type is initialized
5708N/A rasterP->rasterType = UNKNOWN_RASTER_TYPE;
5708N/A
0N/A if (rasterP->numBands <= 0 ||
0N/A rasterP->numBands > MAX_NUMBANDS)
0N/A {
0N/A /*
0N/A * we can't handle such kind of rasters due to limitations
0N/A * of SPPSampleModelS_t structure and expand/set methods.
0N/A */
0N/A return 0;
0N/A }
0N/A
5710N/A rasterP->sppsm.isUsed = 0;
5710N/A
0N/A if ((*env)->IsInstanceOf(env, rasterP->jsampleModel,
0N/A (*env)->FindClass(env,"java/awt/image/SinglePixelPackedSampleModel"))) {
0N/A jobject jmask, joffs, jnbits;
5710N/A
5710N/A rasterP->sppsm.isUsed = 1;
5710N/A
0N/A rasterP->sppsm.maxBitSize = (*env)->GetIntField(env,
0N/A rasterP->jsampleModel,
0N/A g_SPPSMmaxBitID);
0N/A jmask = (*env)->GetObjectField(env, rasterP->jsampleModel,
0N/A g_SPPSMmaskArrID);
0N/A joffs = (*env)->GetObjectField(env, rasterP->jsampleModel,
0N/A g_SPPSMmaskOffID);
0N/A jnbits = (*env)->GetObjectField(env, rasterP->jsampleModel,
0N/A g_SPPSMnBitsID);
0N/A if (jmask == NULL || joffs == NULL || jnbits == NULL ||
3266N/A rasterP->sppsm.maxBitSize < 0)
0N/A {
0N/A JNU_ThrowInternalError(env, "Can't grab SPPSM fields");
0N/A return -1;
0N/A }
0N/A (*env)->GetIntArrayRegion(env, jmask, 0,
0N/A rasterP->numBands, rasterP->sppsm.maskArray);
0N/A (*env)->GetIntArrayRegion(env, joffs, 0,
0N/A rasterP->numBands, rasterP->sppsm.offsets);
0N/A (*env)->GetIntArrayRegion(env, jnbits, 0,
0N/A rasterP->numBands, rasterP->sppsm.nBits);
0N/A
0N/A }
0N/A rasterP->baseRasterWidth = (*env)->GetIntField(env, rasterP->jsampleModel,
0N/A g_SMWidthID);
0N/A rasterP->baseRasterHeight = (*env)->GetIntField(env,
0N/A rasterP->jsampleModel,
0N/A g_SMHeightID);
0N/A
0N/A if ((*env)->IsInstanceOf(env, jraster,
0N/A (*env)->FindClass(env, "sun/awt/image/IntegerComponentRaster"))){
0N/A rasterP->jdata = (*env)->GetObjectField(env, jraster, g_ICRdataID);
0N/A rasterP->dataType = INT_DATA_TYPE;
0N/A rasterP->dataSize = 4;
0N/A rasterP->dataIsShared = TRUE;
0N/A rasterP->rasterType = COMPONENT_RASTER_TYPE;
0N/A rasterP->type = (*env)->GetIntField(env, jraster, g_ICRtypeID);
0N/A rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_ICRscanstrID);
0N/A rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_ICRpixstrID);
0N/A joffs = (*env)->GetObjectField(env, jraster, g_ICRdataOffsetsID);
0N/A }
0N/A else if ((*env)->IsInstanceOf(env, jraster,
0N/A (*env)->FindClass(env, "sun/awt/image/ByteComponentRaster"))){
0N/A rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BCRdataID);
0N/A rasterP->dataType = BYTE_DATA_TYPE;
0N/A rasterP->dataSize = 1;
0N/A rasterP->dataIsShared = TRUE;
0N/A rasterP->rasterType = COMPONENT_RASTER_TYPE;
0N/A rasterP->type = (*env)->GetIntField(env, jraster, g_BCRtypeID);
0N/A rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BCRscanstrID);
0N/A rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BCRpixstrID);
0N/A joffs = (*env)->GetObjectField(env, jraster, g_BCRdataOffsetsID);
0N/A }
0N/A else if ((*env)->IsInstanceOf(env, jraster,
0N/A (*env)->FindClass(env, "sun/awt/image/ShortComponentRaster"))){
0N/A rasterP->jdata = (*env)->GetObjectField(env, jraster, g_SCRdataID);
0N/A rasterP->dataType = SHORT_DATA_TYPE;
0N/A rasterP->dataSize = 2;
0N/A rasterP->dataIsShared = TRUE;
0N/A rasterP->rasterType = COMPONENT_RASTER_TYPE;
0N/A rasterP->type = (*env)->GetIntField(env, jraster, g_SCRtypeID);
0N/A rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_SCRscanstrID);
0N/A rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_SCRpixstrID);
0N/A joffs = (*env)->GetObjectField(env, jraster, g_SCRdataOffsetsID);
0N/A }
0N/A else if ((*env)->IsInstanceOf(env, jraster,
0N/A (*env)->FindClass(env, "sun/awt/image/BytePackedRaster"))){
0N/A rasterP->rasterType = PACKED_RASTER_TYPE;
0N/A rasterP->dataType = BYTE_DATA_TYPE;
0N/A rasterP->dataSize = 1;
0N/A rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BPRscanstrID);
0N/A rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BPRpixstrID);
0N/A rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BPRdataID);
0N/A rasterP->type = (*env)->GetIntField(env, jraster, g_BPRtypeID);
0N/A rasterP->chanOffsets = NULL;
0N/A if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {
0N/A rasterP->chanOffsets =
0N/A (jint *)malloc(rasterP->numDataElements * sizeof(jint));
0N/A }
0N/A if (rasterP->chanOffsets == NULL) {
0N/A /* Out of memory */
0N/A JNU_ThrowOutOfMemoryError(env, "Out of memory");
0N/A return -1;
0N/A }
0N/A rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID);
0N/A rasterP->dataType = BYTE_DATA_TYPE;
0N/A }
0N/A else {
0N/A rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM;
0N/A rasterP->dataType = UNKNOWN_DATA_TYPE;
0N/A rasterP->rasterType = UNKNOWN_RASTER_TYPE;
0N/A rasterP->chanOffsets = NULL;
0N/A /* Custom raster */
0N/A return 0;
0N/A }
0N/A
5708N/A // do basic validation of the raster structure
5708N/A if (rasterP->width <= 0 || rasterP->height <= 0 ||
5708N/A rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0)
5708N/A {
5708N/A // invalid raster
5708N/A return -1;
5708N/A }
5708N/A
5708N/A // channel (data) offsets
5708N/A switch (rasterP->rasterType) {
5708N/A case COMPONENT_RASTER_TYPE:
5708N/A case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment
5708N/A // get channel (data) offsets
0N/A rasterP->chanOffsets = NULL;
0N/A if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {
0N/A rasterP->chanOffsets =
0N/A (jint *)malloc(rasterP->numDataElements * sizeof(jint));
0N/A }
0N/A if (rasterP->chanOffsets == NULL) {
0N/A /* Out of memory */
0N/A JNU_ThrowOutOfMemoryError(env, "Out of memory");
0N/A return -1;
0N/A }
0N/A (*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements,
0N/A rasterP->chanOffsets);
5708N/A if (rasterP->jdata == NULL) {
5708N/A // unable to verify the raster
5708N/A return -1;
5708N/A }
5708N/A // verify whether channel offsets look sane
5708N/A if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) {
5708N/A return -1;
5708N/A }
5708N/A break;
5708N/A default:
5708N/A ; // PACKED_RASTER_TYPE does not use the channel offsets.
0N/A }
0N/A
5708N/A /* additional check for sppsm fields validity: make sure that
5708N/A * size of raster samples doesn't exceed the data type capacity.
3266N/A */
3266N/A if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */
3266N/A rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */
3266N/A rasterP->sppsm.maxBitSize > (rasterP->dataSize * 8))
3266N/A {
3266N/A JNU_ThrowInternalError(env, "Raster samples are too big");
3266N/A return -1;
3266N/A }
3266N/A
0N/A#if 0
0N/A fprintf(stderr,"---------------------\n");
0N/A fprintf(stderr,"Width : %d\n",rasterP->width);
0N/A fprintf(stderr,"Height : %d\n",rasterP->height);
0N/A fprintf(stderr,"X : %d\n",rasterP->x);
0N/A fprintf(stderr,"Y : %d\n",rasterP->y);
0N/A fprintf(stderr,"numC : %d\n",rasterP->numDataElements);
0N/A fprintf(stderr,"SS : %d\n",rasterP->scanlineStride);
0N/A fprintf(stderr,"PS : %d\n",rasterP->pixelStride);
0N/A fprintf(stderr,"CO : %d\n",rasterP->chanOffsets);
0N/A fprintf(stderr,"shared?: %d\n",rasterP->dataIsShared);
0N/A fprintf(stderr,"RasterT: %d\n",rasterP->rasterType);
0N/A fprintf(stderr,"DataT : %d\n",rasterP->dataType);
0N/A fprintf(stderr,"---------------------\n");
0N/A#endif
0N/A
0N/A return 1;
0N/A}
0N/A
6378N/Astatic int getColorModelType(JNIEnv *env, jobject jcmodel) {
6378N/A int type = UNKNOWN_CM_TYPE;
6378N/A
6378N/A if ((*env)->IsInstanceOf(env, jcmodel,
6378N/A (*env)->FindClass(env, "java/awt/image/IndexColorModel")))
6378N/A {
6378N/A type = INDEX_CM_TYPE;
6378N/A } else if ((*env)->IsInstanceOf(env, jcmodel,
6378N/A (*env)->FindClass(env, "java/awt/image/PackedColorModel")))
6378N/A {
6378N/A if ((*env)->IsInstanceOf(env, jcmodel,
6378N/A (*env)->FindClass(env, "java/awt/image/DirectColorModel"))) {
6378N/A type = DIRECT_CM_TYPE;
6378N/A }
6378N/A else {
6378N/A type = PACKED_CM_TYPE;
6378N/A }
6378N/A }
6378N/A else if ((*env)->IsInstanceOf(env, jcmodel,
6378N/A (*env)->FindClass(env, "java/awt/image/ComponentColorModel")))
6378N/A {
6378N/A type = COMPONENT_CM_TYPE;
6378N/A }
6378N/A
6378N/A return type;
6378N/A}
6378N/A
0N/Aint awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType,
0N/A ColorModelS_t *cmP) {
0N/A /*jmethodID jID; */
0N/A jobject jnBits;
6378N/A jsize nBitsLength;
6378N/A
0N/A int i;
0N/A static jobject s_jdefCM = NULL;
0N/A
0N/A if (JNU_IsNull(env, jcmodel)) {
0N/A JNU_ThrowNullPointerException(env, "null ColorModel object");
0N/A return -1;
0N/A }
0N/A
0N/A cmP->jcmodel = jcmodel;
0N/A
0N/A cmP->jcspace = (*env)->GetObjectField(env, jcmodel, g_CMcspaceID);
0N/A
0N/A cmP->numComponents = (*env)->GetIntField(env, jcmodel,
0N/A g_CMnumComponentsID);
0N/A cmP->supportsAlpha = (*env)->GetBooleanField(env, jcmodel,
0N/A g_CMsuppAlphaID);
0N/A cmP->isAlphaPre = (*env)->GetBooleanField(env,jcmodel,
0N/A g_CMisAlphaPreID);
0N/A cmP->transparency = (*env)->GetIntField(env, jcmodel,
0N/A g_CMtransparencyID);
0N/A
6378N/A jnBits = (*env)->GetObjectField(env, jcmodel, g_CMnBitsID);
6378N/A if (jnBits == NULL) {
6378N/A JNU_ThrowNullPointerException(env, "null nBits structure in CModel");
6378N/A return -1;
6378N/A }
6378N/A
6378N/A nBitsLength = (*env)->GetArrayLength(env, jnBits);
6378N/A if (nBitsLength != cmP->numComponents) {
6378N/A // invalid number of components?
6378N/A return -1;
6378N/A }
6378N/A
6378N/A cmP->nBits = NULL;
6378N/A if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) {
6378N/A cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint));
6378N/A }
6378N/A
6378N/A if (cmP->nBits == NULL){
6378N/A JNU_ThrowOutOfMemoryError(env, "Out of memory");
6378N/A return -1;
6378N/A }
6378N/A (*env)->GetIntArrayRegion(env, jnBits, 0, cmP->numComponents,
6378N/A cmP->nBits);
6378N/A cmP->maxNbits = 0;
6378N/A for (i=0; i < cmP->numComponents; i++) {
6378N/A if (cmP->maxNbits < cmP->nBits[i]) {
6378N/A cmP->maxNbits = cmP->nBits[i];
6378N/A }
6378N/A }
6378N/A
6378N/A cmP->is_sRGB = (*env)->GetBooleanField(env, cmP->jcmodel, g_CMis_sRGBID);
6378N/A
6378N/A cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID);
6378N/A
6378N/A cmP->cmType = getColorModelType(env, jcmodel);
6378N/A
6378N/A cmP->isDefaultCM = FALSE;
6378N/A cmP->isDefaultCompatCM = FALSE;
6378N/A
6378N/A /* look for standard cases */
0N/A if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB) {
0N/A cmP->isDefaultCM = TRUE;
0N/A cmP->isDefaultCompatCM = TRUE;
0N/A } else if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
6378N/A imageType == java_awt_image_BufferedImage_TYPE_INT_RGB ||
6378N/A imageType == java_awt_image_BufferedImage_TYPE_INT_BGR ||
0N/A imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||
6378N/A imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)
6378N/A {
0N/A cmP->isDefaultCompatCM = TRUE;
0N/A }
0N/A else {
0N/A /* Figure out if this is the default CM */
0N/A if (s_jdefCM == NULL) {
0N/A jobject defCM;
0N/A jclass jcm = (*env)->FindClass(env, "java/awt/image/ColorModel");
0N/A defCM = (*env)->CallStaticObjectMethod(env, jcm,
0N/A g_CMgetRGBdefaultMID, NULL);
0N/A s_jdefCM = (*env)->NewGlobalRef(env, defCM);
0N/A if (defCM == NULL || s_jdefCM == NULL) {
0N/A JNU_ThrowNullPointerException(env,
0N/A "Unable to find default CM");
0N/A return -1;
0N/A }
0N/A }
0N/A cmP->isDefaultCM = ((*env)->IsSameObject(env, s_jdefCM, jcmodel));
0N/A cmP->isDefaultCompatCM = cmP->isDefaultCM;
0N/A }
0N/A
6378N/A /* check whether image attributes correspond to default cm */
0N/A if (cmP->isDefaultCompatCM) {
6378N/A if (cmP->csType != java_awt_color_ColorSpace_TYPE_RGB ||
6378N/A !cmP->is_sRGB)
6378N/A {
6378N/A return -1;
6378N/A }
0N/A
6378N/A for (i = 0; i < cmP->numComponents; i++) {
6378N/A if (cmP->nBits[i] != 8) {
6378N/A return -1;
6378N/A }
0N/A }
0N/A }
0N/A
6378N/A /* Get index color model attributes */
0N/A if (imageType == java_awt_image_BufferedImage_TYPE_BYTE_INDEXED ||
6378N/A cmP->cmType == INDEX_CM_TYPE)
0N/A {
0N/A cmP->transIdx = (*env)->GetIntField(env, jcmodel, g_ICMtransIdxID);
0N/A cmP->mapSize = (*env)->GetIntField(env, jcmodel, g_ICMmapSizeID);
0N/A cmP->jrgb = (*env)->GetObjectField(env, jcmodel, g_ICMrgbID);
0N/A if (cmP->transIdx == -1) {
0N/A /* Need to find the transparent index */
0N/A int *rgb = (int *) (*env)->GetPrimitiveArrayCritical(env,
0N/A cmP->jrgb,
0N/A NULL);
0N/A if (rgb == NULL) {
0N/A return -1;
0N/A }
0N/A for (i=0; i < cmP->mapSize; i++) {
0N/A if ((rgb[i]&0xff000000) == 0) {
0N/A cmP->transIdx = i;
0N/A break;
0N/A }
0N/A }
0N/A (*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb,
0N/A JNI_ABORT);
0N/A if (cmP->transIdx == -1) {
0N/A /* Now what? No transparent pixel... */
0N/A cmP->transIdx = 0;
0N/A }
0N/A }
0N/A }
0N/A
0N/A return 1;
0N/A}
0N/A
0N/Avoid awt_freeParsedRaster(RasterS_t *rasterP, int freeRasterP) {
0N/A if (rasterP->chanOffsets) {
0N/A free((void *) rasterP->chanOffsets);
0N/A }
0N/A
0N/A if (freeRasterP) {
0N/A free((void *) rasterP);
0N/A }
0N/A}
0N/A
0N/Avoid awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) {
0N/A if (imageP->hints.colorOrder) {
0N/A free ((void *) imageP->hints.colorOrder);
0N/A }
0N/A
0N/A if (imageP->cmodel.nBits) {
0N/A free ((void *) imageP->cmodel.nBits);
0N/A }
0N/A
0N/A /* Free the raster */
0N/A awt_freeParsedRaster(&imageP->raster, FALSE);
0N/A
0N/A if (freeImageP) {
0N/A free((void *) imageP);
0N/A }
0N/A}
0N/A
0N/A
0N/Astatic int
0N/AsetHints(JNIEnv *env, BufImageS_t *imageP) {
0N/A HintS_t *hintP = &imageP->hints;
0N/A RasterS_t *rasterP = &imageP->raster;
0N/A ColorModelS_t *cmodelP = &imageP->cmodel;
0N/A int imageType = imageP->imageType;
0N/A
6378N/A // check whether raster and color model are compatible
6378N/A if (cmodelP->numComponents != rasterP->numBands) {
6378N/A if (cmodelP->cmType != INDEX_CM_TYPE) {
6378N/A return -1;
6378N/A }
6378N/A }
6378N/A
0N/A hintP->numChans = imageP->cmodel.numComponents;
0N/A hintP->colorOrder = NULL;
0N/A if (SAFE_TO_ALLOC_2(hintP->numChans, sizeof(int))) {
0N/A hintP->colorOrder = (int *)malloc(hintP->numChans * sizeof(int));
0N/A }
0N/A if (hintP->colorOrder == NULL) {
0N/A JNU_ThrowOutOfMemoryError(env, "Out of memory");
0N/A return -1;
0N/A }
0N/A if (imageType != java_awt_image_BufferedImage_TYPE_CUSTOM) {
0N/A awt_getBIColorOrder(imageType, hintP->colorOrder);
0N/A }
0N/A if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||
0N/A imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
0N/A imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)
0N/A {
0N/A hintP->channelOffset = rasterP->chanOffsets[0];
0N/A /* These hints are #bytes */
0N/A hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
0N/A hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
0N/A hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
0N/A hintP->packing = BYTE_INTERLEAVED;
0N/A } else if (imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||
0N/A imageType==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE||
0N/A imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR ||
0N/A imageType == java_awt_image_BufferedImage_TYPE_INT_BGR)
0N/A {
0N/A if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) {
0N/A hintP->channelOffset = rasterP->chanOffsets[0];
0N/A }
0N/A else {
0N/A hintP->channelOffset = rasterP->chanOffsets[hintP->numChans-1];
0N/A }
0N/A hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
0N/A hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
0N/A hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
0N/A hintP->packing = BYTE_INTERLEAVED;
0N/A } else if (imageType==java_awt_image_BufferedImage_TYPE_USHORT_565_RGB ||
0N/A imageType==java_awt_image_BufferedImage_TYPE_USHORT_555_RGB) {
0N/A hintP->needToExpand = TRUE;
0N/A hintP->expandToNbits = 8;
0N/A hintP->packing = PACKED_SHORT_INTER;
0N/A } else if (cmodelP->cmType == INDEX_CM_TYPE) {
0N/A int i;
0N/A hintP->numChans = 1;
0N/A hintP->channelOffset = rasterP->chanOffsets[0];
0N/A hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
0N/A hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
0N/A hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
0N/A switch(rasterP->dataType ) {
0N/A case BYTE_DATA_TYPE:
0N/A if (rasterP->rasterType == PACKED_RASTER_TYPE) {
0N/A hintP->needToExpand = TRUE;
0N/A hintP->expandToNbits = 8;
0N/A hintP->packing = BYTE_PACKED_BAND;
0N/A }
0N/A else {
0N/A hintP->packing = BYTE_SINGLE_BAND;
0N/A }
0N/A break;
0N/A case SHORT_DATA_TYPE:
0N/A hintP->packing = SHORT_SINGLE_BAND;
0N/A break;
0N/A case INT_DATA_TYPE:
0N/A default:
0N/A hintP->packing = UNKNOWN_PACKING;
0N/A break;
0N/A }
0N/A for (i=0; i < hintP->numChans; i++) {
0N/A hintP->colorOrder[i] = i;
0N/A }
0N/A }
0N/A else if (cmodelP->cmType == COMPONENT_CM_TYPE) {
0N/A /* Figure out if it is interleaved */
0N/A int bits=1;
0N/A int i;
0N/A int low = rasterP->chanOffsets[0];
0N/A int diff;
0N/A int banded = 0;
0N/A for (i=1; i < hintP->numChans; i++) {
0N/A if (rasterP->chanOffsets[i] < low) {
0N/A low = rasterP->chanOffsets[i];
0N/A }
0N/A }
0N/A for (i=1; i < hintP->numChans; i++) {
0N/A diff = rasterP->chanOffsets[i]-low;
0N/A if (diff < hintP->numChans) {
0N/A if (bits & (1<<diff)) {
0N/A /* Overlapping samples */
0N/A /* Could just copy */
0N/A return -1;
0N/A }
0N/A bits |= (1<<diff);
0N/A }
0N/A else if (diff >= rasterP->width) {
0N/A banded = 1;
0N/A }
0N/A /* Ignore the case if bands are overlapping */
0N/A }
0N/A hintP->channelOffset = low;
0N/A hintP->dataOffset = low*rasterP->dataSize;
0N/A hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
0N/A hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
0N/A switch(rasterP->dataType) {
0N/A case BYTE_DATA_TYPE:
0N/A hintP->packing = BYTE_COMPONENTS;
0N/A break;
0N/A case SHORT_DATA_TYPE:
0N/A hintP->packing = SHORT_COMPONENTS;
0N/A break;
0N/A default:
0N/A /* Don't handle any other case */
0N/A return -1;
0N/A }
0N/A if (bits == ((1<<hintP->numChans)-1)) {
0N/A hintP->packing |= INTERLEAVED;
0N/A for (i=0; i < hintP->numChans; i++) {
0N/A hintP->colorOrder[rasterP->chanOffsets[i]-low] = i;
0N/A }
0N/A }
0N/A else if (banded == 1) {
0N/A int bandSize = rasterP->width*rasterP->height;
0N/A hintP->packing |= BANDED;
0N/A for (i=0; i < hintP->numChans; i++) {
0N/A /* REMIND: Not necessarily correct */
0N/A hintP->colorOrder[(rasterP->chanOffsets[i]-low)%bandSize] = i;
0N/A }
0N/A }
0N/A else {
0N/A return -1;
0N/A }
0N/A }
0N/A else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) {
0N/A int i;
5710N/A
5710N/A /* do some sanity check first: make sure that
5710N/A * - sample model is SinglePixelPackedSampleModel
5710N/A * - number of bands in the raster corresponds to the number
5710N/A * of color components in the color model
5710N/A */
5710N/A if (!rasterP->sppsm.isUsed ||
5710N/A rasterP->numBands != cmodelP->numComponents)
5710N/A {
5710N/A /* given raster is not compatible with the color model,
5710N/A * so the operation has to be aborted.
5710N/A */
5710N/A return -1;
5710N/A }
5710N/A
0N/A if (cmodelP->maxNbits > 8) {
0N/A hintP->needToExpand = TRUE;
0N/A hintP->expandToNbits = cmodelP->maxNbits;
0N/A }
0N/A else if (rasterP->sppsm.offsets != NULL) {
0N/A for (i=0; i < rasterP->numBands; i++) {
0N/A if (!(rasterP->sppsm.offsets[i] % 8)) {
0N/A hintP->needToExpand = TRUE;
0N/A hintP->expandToNbits = 8;
0N/A break;
0N/A }
0N/A else {
0N/A hintP->colorOrder[i] = rasterP->sppsm.offsets[i]>>3;
0N/A }
0N/A }
0N/A }
0N/A
0N/A hintP->channelOffset = rasterP->chanOffsets[0];
0N/A hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
0N/A hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
0N/A hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
0N/A if (hintP->needToExpand) {
0N/A switch(rasterP->dataType) {
0N/A case BYTE_DATA_TYPE:
0N/A hintP->packing = PACKED_BYTE_INTER;
0N/A break;
0N/A case SHORT_DATA_TYPE:
0N/A hintP->packing = PACKED_SHORT_INTER;
0N/A break;
0N/A case INT_DATA_TYPE:
0N/A hintP->packing = PACKED_INT_INTER;
0N/A break;
0N/A default:
0N/A /* Don't know what it is */
0N/A return -1;
0N/A }
0N/A }
0N/A else {
0N/A hintP->packing = BYTE_INTERLEAVED;
0N/A
0N/A }
0N/A }
0N/A else {
0N/A /* REMIND: Need to handle more cases */
0N/A return -1;
0N/A }
0N/A
0N/A return 1;
0N/A}
0N/A
0N/A/*
0N/A * This routine will fill in a buffer of data for either 1 band or all
0N/A * bands (if band == -1).
0N/A */
0N/A#define MAX_TO_GRAB (10240)
0N/A
0N/Aint awt_getPixelByte(JNIEnv *env, int band, RasterS_t *rasterP,
0N/A unsigned char *bufferP) {
0N/A int w = rasterP->width;
0N/A int h = rasterP->height;
0N/A int numBands = rasterP->numBands;
0N/A int y;
0N/A int i;
0N/A int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w);
0N/A jobject jsm;
0N/A int off;
0N/A jarray jdata = NULL;
0N/A jobject jdatabuffer;
0N/A int *dataP;
0N/A int maxBytes = w;
0N/A
0N/A jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
0N/A jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
0N/A g_RasterDataBufferID);
0N/A jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines);
0N/A if (JNU_IsNull(env, jdata)) {
0N/A JNU_ThrowOutOfMemoryError(env, "Out of Memory");
0N/A return -1;
0N/A }
0N/A
0N/A /* Here is the generic code */
0N/A if (band >= 0) {
0N/A int dOff;
0N/A if (band >= numBands) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A JNU_ThrowInternalError(env, "Band out of range.");
0N/A return -1;
0N/A }
0N/A off = 0;
0N/A for (y=0; y < h; ) {
0N/A (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A dOff = band;
0N/A for (i=0; i < maxBytes; i++, dOff += numBands) {
0N/A bufferP[off++] = (unsigned char) dataP[dOff];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A
0N/A if (y+maxLines < h) {
0N/A y += maxLines;
0N/A }
0N/A else {
0N/A y++;
0N/A maxBytes = w;
0N/A }
0N/A }
0N/A }
0N/A else {
0N/A off = 0;
0N/A maxBytes *= numBands;
0N/A for (y=0; y < h; ) {
0N/A (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A for (i=0; i < maxBytes; i++) {
0N/A bufferP[off++] = (unsigned char) dataP[i];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A
0N/A if (y+maxLines < h) {
0N/A y += maxLines;
0N/A }
0N/A else {
0N/A y++;
0N/A maxBytes = w*numBands;
0N/A }
0N/A }
0N/A
0N/A }
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A
0N/A return 0;
0N/A}
0N/Aint awt_setPixelByte(JNIEnv *env, int band, RasterS_t *rasterP,
0N/A unsigned char *bufferP) {
0N/A int w = rasterP->width;
0N/A int h = rasterP->height;
0N/A int numBands = rasterP->numBands;
0N/A int y;
0N/A int i;
0N/A int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w);
0N/A jobject jsm;
0N/A int off;
0N/A jarray jdata = NULL;
0N/A jobject jdatabuffer;
0N/A int *dataP;
0N/A int maxBytes = w;
0N/A
0N/A jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
0N/A jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
0N/A g_RasterDataBufferID);
0N/A /* Here is the generic code */
0N/A jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines);
0N/A if (JNU_IsNull(env, jdata)) {
0N/A JNU_ThrowOutOfMemoryError(env, "Out of Memory");
0N/A return -1;
0N/A }
0N/A if (band >= 0) {
0N/A int dOff;
0N/A if (band >= numBands) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A JNU_ThrowInternalError(env, "Band out of range.");
0N/A return -1;
0N/A }
0N/A off = 0;
0N/A for (y=0; y < h; y+=maxLines) {
0N/A if (y+maxLines > h) {
0N/A maxBytes = w*numBands;
0N/A maxLines = h - y;
0N/A }
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A dOff = band;
0N/A for (i=0; i < maxBytes; i++, dOff += numBands) {
0N/A dataP[dOff] = bufferP[off++];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A
0N/A (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A }
0N/A }
0N/A else {
0N/A off = 0;
0N/A maxBytes *= numBands;
0N/A for (y=0; y < h; y+=maxLines) {
0N/A if (y+maxLines > h) {
0N/A maxBytes = w*numBands;
0N/A maxLines = h - y;
0N/A }
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A for (i=0; i < maxBytes; i++) {
0N/A dataP[i] = bufferP[off++];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A
0N/A (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A }
0N/A
0N/A }
0N/A
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A
0N/A return 0;
0N/A}
0N/Aint awt_getPixelShort(JNIEnv *env, int band, RasterS_t *rasterP,
0N/A unsigned short *bufferP) {
0N/A int w = rasterP->width;
0N/A int h = rasterP->height;
0N/A int numBands = rasterP->numBands;
0N/A int y;
0N/A int i;
0N/A int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w);
0N/A jobject jsm;
0N/A int off;
0N/A jarray jdata = NULL;
0N/A jobject jdatabuffer;
0N/A int *dataP;
0N/A int maxBytes = w*maxLines;
0N/A
0N/A jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
0N/A jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
0N/A g_RasterDataBufferID);
0N/A jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines);
0N/A if (JNU_IsNull(env, jdata)) {
0N/A JNU_ThrowOutOfMemoryError(env, "Out of Memory");
0N/A return -1;
0N/A }
0N/A /* Here is the generic code */
0N/A if (band >= 0) {
0N/A int dOff;
0N/A if (band >= numBands) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A JNU_ThrowInternalError(env, "Band out of range.");
0N/A return -1;
0N/A }
0N/A off = 0;
0N/A for (y=0; y < h; y += maxLines) {
0N/A if (y+maxLines > h) {
0N/A maxBytes = w*numBands;
0N/A maxLines = h - y;
0N/A }
0N/A (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A
0N/A dOff = band;
0N/A for (i=0; i < maxBytes; i++, dOff += numBands) {
0N/A bufferP[off++] = (unsigned short) dataP[dOff];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A }
0N/A }
0N/A else {
0N/A off = 0;
0N/A maxBytes *= numBands;
0N/A for (y=0; y < h; y+=maxLines) {
0N/A if (y+maxLines > h) {
0N/A maxBytes = w*numBands;
0N/A maxLines = h - y;
0N/A }
0N/A (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A for (i=0; i < maxBytes; i++) {
0N/A bufferP[off++] = (unsigned short) dataP[i];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A }
0N/A
0N/A }
0N/A
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return 0;
0N/A}
0N/Aint awt_setPixelShort(JNIEnv *env, int band, RasterS_t *rasterP,
0N/A unsigned short *bufferP) {
0N/A int w = rasterP->width;
0N/A int h = rasterP->height;
0N/A int numBands = rasterP->numBands;
0N/A int y;
0N/A int i;
0N/A int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w);
0N/A jobject jsm;
0N/A int off;
0N/A jarray jdata = NULL;
0N/A jobject jdatabuffer;
0N/A int *dataP;
0N/A int maxBytes = w;
0N/A
0N/A jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
0N/A jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
0N/A g_RasterDataBufferID);
6378N/A if (band >= numBands) {
6378N/A JNU_ThrowInternalError(env, "Band out of range.");
6378N/A return -1;
6378N/A }
0N/A /* Here is the generic code */
0N/A jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines);
0N/A if (JNU_IsNull(env, jdata)) {
0N/A JNU_ThrowOutOfMemoryError(env, "Out of Memory");
0N/A return -1;
0N/A }
0N/A if (band >= 0) {
0N/A int dOff;
0N/A off = 0;
0N/A for (y=0; y < h; y+=maxLines) {
0N/A if (y+maxLines > h) {
0N/A maxBytes = w*numBands;
0N/A maxLines = h - y;
0N/A }
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A dOff = band;
0N/A for (i=0; i < maxBytes; i++, dOff += numBands) {
0N/A dataP[dOff] = bufferP[off++];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A
0N/A (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A }
0N/A }
0N/A else {
0N/A off = 0;
0N/A maxBytes *= numBands;
0N/A for (y=0; y < h; y+=maxLines) {
0N/A if (y+maxLines > h) {
0N/A maxBytes = w*numBands;
0N/A maxLines = h - y;
0N/A }
0N/A dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
0N/A NULL);
0N/A if (dataP == NULL) {
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return -1;
0N/A }
0N/A for (i=0; i < maxBytes; i++) {
0N/A dataP[i] = bufferP[off++];
0N/A }
0N/A
0N/A (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
0N/A JNI_ABORT);
0N/A
0N/A (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID,
0N/A 0, y, w,
0N/A maxLines, jdata, jdatabuffer);
0N/A }
0N/A
0N/A }
0N/A
0N/A (*env)->DeleteLocalRef(env, jdata);
0N/A return 0;
0N/A}