Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c
38918 views
/*1* Copyright (c) 1997, 2016, 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 <string.h>28#include "sun_awt_image_ImagingLib.h"29#include "java_awt_Transparency.h"30#include "java_awt_image_AffineTransformOp.h"31#include "java_awt_image_BufferedImage.h"32#include "java_awt_color_ColorSpace.h"33#include "java_awt_image_ConvolveOp.h"34#include "sun_awt_image_IntegerComponentRaster.h"35#include "awt_ImagingLib.h"36#include "awt_parseImage.h"37#include "imageInitIDs.h"38#include <jni.h>39#include <jni_util.h>40#include <assert.h>41#include "awt_Mlib.h"42#include "gdefs.h"43#include "safe_alloc.h"44#include "safe_math.h"4546/***************************************************************************47* Definitions *48***************************************************************************/49#define jio_fprintf fprintf5051#ifndef TRUE52#define TRUE 153#endif /* TRUE */5455#ifndef FALSE56#define FALSE 057#endif /* FALSE */5859#define TYPE_CUSTOM java_awt_image_BufferedImage_TYPE_CUSTOM60#define TYPE_INT_RGB java_awt_image_BufferedImage_TYPE_INT_RGB61#define TYPE_INT_ARGB java_awt_image_BufferedImage_TYPE_INT_ARGB62#define TYPE_INT_ARGB_PRE java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE63#define TYPE_INT_BGR java_awt_image_BufferedImage_TYPE_INT_BGR64#define TYPE_4BYTE_ABGR java_awt_image_BufferedImage_TYPE_4BYTE_ABGR65#define TYPE_4BYTE_ABGR_PRE java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE6667/* (alpha*color)>>nbits + alpha>>(nbits-1) */68#define BLEND(color, alpha, alphaNbits) \69((((alpha)*(color))>>(alphaNbits)) + ((alpha) >> ((alphaNbits)-1)))7071/* ((color - (alpha>>(nBits-1)))<<nBits)/alpha */72#define UNBLEND(color, alpha, alphaNbits) \73((((color)-((alpha)>>((alphaNbits)-1)))<<(alphaNbits))/(alpha))7475/* Enumeration of all of the mlib functions used */76typedef enum {77MLIB_CONVMxN,78MLIB_AFFINE,79MLIB_LOOKUP,80MLIB_CONVKERNCVT81} mlibTypeE_t;8283typedef struct {84int dataType; /* One of BYTE_DATA_TYPE, SHORT_DATA_TYPE, */85int needToCopy;86int cvtSrcToDefault; /* If TRUE, convert the src to def CM (pre?) */87int allocDefaultDst; /* If TRUE, alloc def CM dst buffer */88int cvtToDst; /* If TRUE, convert dst buffer to Dst CM */89int addAlpha;90} mlibHintS_t;9192/***************************************************************************93* Static Variables/Structures *94***************************************************************************/9596static mlibSysFnS_t sMlibSysFns = {97NULL, // placeholder for j2d_mlib_ImageCreate98NULL, // placeholder for j2d_mlib_ImageCreateStruct99NULL, // placeholder for j2d_mlib_ImageDelete100};101102static mlibFnS_t sMlibFns[] = {103{NULL, "j2d_mlib_ImageConvMxN"},104{NULL, "j2d_mlib_ImageAffine"},105{NULL, "j2d_mlib_ImageLookUp"},106{NULL, "j2d_mlib_ImageConvKernelConvert"},107{NULL, NULL},108};109110static int s_timeIt = 0;111static int s_printIt = 0;112static int s_startOff = 0;113static int s_nomlib = 0;114115/***************************************************************************116* Static Function Prototypes *117***************************************************************************/118119static int120allocateArray(JNIEnv *env, BufImageS_t *imageP,121mlib_image **mlibImagePP, void **dataPP, int isSrc,122int cvtToDefault, int addAlpha);123static int124allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,125mlib_image **mlibImagePP, void **dataPP, int isSrc);126127static void128freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,129void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,130void *dstdataP);131static void132freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,133void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,134void *dstdataP);135136static int137storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,138mlib_image *mlibImP);139140static int141storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,142mlib_image *mlibImP);143144static int145storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,146mlib_image *mlibImP);147148static int149colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors);150151static int152setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,153int expandICM, int useAlpha,154int premultiply, mlibHintS_t *hintP);155156157static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP);158static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,159unsigned char *outDataP);160static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,161unsigned char *outDataP);162static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,163unsigned char *outDataP);164static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,165int component, unsigned char *outDataP,166int forceAlpha);167static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,168int component, unsigned char *outDataP,169int forceAlpha);170static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,171int component, unsigned char *outDataP,172int forceAlpha);173static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,174unsigned char *outDataP);175static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,176unsigned char *outDataP);177static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,178unsigned char *outDataP);179static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,180int component, unsigned char *outDataP,181int supportsAlpha);182static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,183int component, unsigned char *outDataP,184int supportsAlpha);185static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,186int component, unsigned char *outDataP,187int supportsAlpha);188189mlib_start_timer start_timer = NULL;190mlib_stop_timer stop_timer = NULL;191192/***************************************************************************193* Debugging Definitions *194***************************************************************************/195#ifdef DEBUG196197static void198printMedialibError(int status) {199switch(status) {200case MLIB_FAILURE:201jio_fprintf(stderr, "failure\n");202break;203case MLIB_NULLPOINTER:204jio_fprintf(stderr, "null pointer\n");205break;206case MLIB_OUTOFRANGE:207jio_fprintf (stderr, "out of range\n");208break;209default:210jio_fprintf (stderr, "medialib error\n");211break;212}213}214#else /* ! DEBUG */215# define printMedialibError(x)216217#endif /* ! DEBUG */218219static int220getMlibEdgeHint(jint edgeHint) {221switch (edgeHint) {222case java_awt_image_ConvolveOp_EDGE_NO_OP:223return MLIB_EDGE_DST_COPY_SRC;224case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:225default:226return MLIB_EDGE_DST_FILL_ZERO;227}228}229230/*231* We have to make sure that awt_setPixels can be safely applied to the given pair of232* raster and mlib image.233*234* In particular, make sure that235* - dimension is the same236* - number of channels in mlib image corresponds to the number of bands in the raster237* - sample size in image and raster are the same.238*239* Returns:240* -1 to indicate failure,241* 1 to indicate success242*/243static int setPixelsFormMlibImage(JNIEnv *env, RasterS_t *rasterP, mlib_image* img) {244if (rasterP->width != img->width || rasterP->height != img->height) {245/* dimension does not match */246return -1;247}248249if (rasterP->numBands != img->channels) {250/* number of bands does not match */251return -1;252}253254switch (rasterP->dataType) {255case BYTE_DATA_TYPE:256if (img->type != MLIB_BYTE) {257return -1;258}259break;260case SHORT_DATA_TYPE:261if (img->type != MLIB_SHORT && img->type != MLIB_USHORT) {262return -1;263}264break;265default:266/* awt_setPixels does not support such rasters */267return -1;268}269270return awt_setPixels(env, rasterP, mlib_ImageGetData(img));271}272273/***************************************************************************274* External Functions *275***************************************************************************/276JNIEXPORT jint JNICALL277Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this,278jobject jsrc, jobject jdst,279jobject jkernel, jint edgeHint)280{281void *sdata, *ddata;282mlib_image *src;283mlib_image *dst;284int i, scale;285mlib_d64 *dkern;286mlib_s32 *kdata;287int klen;288float kmax;289mlib_s32 cmask;290mlib_status status;291int retStatus = 1;292float *kern;293BufImageS_t *srcImageP, *dstImageP;294jobject jdata;295int kwidth;296int kheight;297int w, h;298int x, y;299mlibHintS_t hint;300int nbands;301302/* This function requires a lot of local refs ??? Is 64 enough ??? */303if ((*env)->EnsureLocalCapacity(env, 64) < 0)304return 0;305306if (s_nomlib) return 0;307if (s_timeIt) (*start_timer)(3600);308309kwidth = (*env)->GetIntField(env, jkernel, g_KernelWidthID);310kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID);311jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID);312klen = (*env)->GetArrayLength(env, jdata);313kern = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);314if (kern == NULL) {315/* out of memory exception already thrown */316return 0;317}318319if ((kwidth&0x1) == 0) {320/* Kernel has even width */321w = kwidth+1;322}323else {324w = kwidth;325}326if ((kheight&0x1) == 0) {327/* Kernel has even height */328h = kheight+1;329}330else {331h = kheight;332}333334dkern = NULL;335if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) {336dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64));337}338if (dkern == NULL) {339(*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);340return 0;341}342343/* Need to flip and find max value of the kernel.344* Also, save the kernel values as mlib_d64 values.345* The flip is to operate correctly with medialib,346* which doesn't do the mathemetically correct thing,347* i.e. it doesn't rotate the kernel by 180 degrees.348* REMIND: This should perhaps be done at the Java349* level by ConvolveOp.350* REMIND: Should the max test be looking at absolute351* values?352* REMIND: What if klen != kheight * kwidth?353*/354kmax = kern[klen-1];355i = klen-1;356for (y=0; y < kheight; y++) {357for (x=0; x < kwidth; x++, i--) {358dkern[y*w+x] = (mlib_d64) kern[i];359if (kern[i] > kmax) {360kmax = kern[i];361}362}363}364365(*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);366367if (kmax > 1<<16) {368/* We can only handle 16 bit max */369free(dkern);370return 0;371}372373374/* Parse the source image */375if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {376/* Can't handle any custom images */377free(dkern);378return 0;379}380381/* Parse the destination image */382if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {383/* Can't handle any custom images */384awt_freeParsedImage(srcImageP, TRUE);385free(dkern);386return 0;387}388389nbands = setImageHints(env, srcImageP, dstImageP, TRUE, TRUE,390FALSE, &hint);391if (nbands < 1) {392/* Can't handle any custom images */393awt_freeParsedImage(srcImageP, TRUE);394awt_freeParsedImage(dstImageP, TRUE);395free(dkern);396return 0;397}398/* Allocate the arrays */399if (allocateArray(env, srcImageP, &src, &sdata, TRUE,400hint.cvtSrcToDefault, hint.addAlpha) < 0) {401/* Must be some problem */402awt_freeParsedImage(srcImageP, TRUE);403awt_freeParsedImage(dstImageP, TRUE);404free(dkern);405return 0;406}407if (allocateArray(env, dstImageP, &dst, &ddata, FALSE,408hint.cvtToDst, FALSE) < 0) {409/* Must be some problem */410freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);411awt_freeParsedImage(srcImageP, TRUE);412awt_freeParsedImage(dstImageP, TRUE);413free(dkern);414return 0;415}416417kdata = NULL;418if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) {419kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32));420}421if (kdata == NULL) {422freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);423awt_freeParsedImage(srcImageP, TRUE);424awt_freeParsedImage(dstImageP, TRUE);425free(dkern);426return 0;427}428429if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h,430mlib_ImageGetType(src)) != MLIB_SUCCESS) {431freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);432awt_freeParsedImage(srcImageP, TRUE);433awt_freeParsedImage(dstImageP, TRUE);434free(dkern);435free(kdata);436return 0;437}438439if (s_printIt) {440fprintf(stderr, "Orig Kernel(len=%d):\n",klen);441for (y=kheight-1; y >= 0; y--) {442for (x=kwidth-1; x >= 0; x--) {443fprintf(stderr, "%g ", dkern[y*w+x]);444}445fprintf(stderr, "\n");446}447fprintf(stderr, "New Kernel(scale=%d):\n", scale);448for (y=kheight-1; y >= 0; y--) {449for (x=kwidth-1; x >= 0; x--) {450fprintf(stderr, "%d ", kdata[y*w+x]);451}452fprintf(stderr, "\n");453}454}455456cmask = (1<<src->channels)-1;457status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,458(w-1)/2, (h-1)/2, scale, cmask,459getMlibEdgeHint(edgeHint));460461if (status != MLIB_SUCCESS) {462printMedialibError(status);463retStatus = 0;464}465466if (s_printIt) {467unsigned int *dP;468if (s_startOff != 0) {469printf("Starting at %d\n", s_startOff);470}471if (sdata == NULL) {472dP = (unsigned int *) mlib_ImageGetData(src);473}474else {475dP = (unsigned int *) sdata;476}477printf("src is\n");478for (i=0; i < 20; i++) {479printf("%x ",dP[s_startOff+i]);480}481printf("\n");482if (ddata == NULL) {483dP = (unsigned int *)mlib_ImageGetData(dst);484}485else {486dP = (unsigned int *) ddata;487}488printf("dst is \n");489for (i=0; i < 20; i++) {490printf("%x ",dP[s_startOff+i]);491}492printf("\n");493}494495/* Means that we couldn't write directly into the destination buffer */496if (ddata == NULL) {497498/* Need to store it back into the array */499if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {500/* Error */501retStatus = 0;502}503}504505/* Release the pinned memory */506freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);507awt_freeParsedImage(srcImageP, TRUE);508awt_freeParsedImage(dstImageP, TRUE);509free(dkern);510free(kdata);511512if (s_timeIt) (*stop_timer)(3600, 1);513514return retStatus;515}516517JNIEXPORT jint JNICALL518Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this,519jobject jsrc, jobject jdst,520jobject jkernel, jint edgeHint)521{522mlib_image *src;523mlib_image *dst;524int i, scale;525mlib_d64 *dkern;526mlib_s32 *kdata;527int klen;528float kmax;529int retStatus = 1;530mlib_status status;531mlib_s32 cmask;532void *sdata;533void *ddata;534RasterS_t *srcRasterP;535RasterS_t *dstRasterP;536int kwidth;537int kheight;538int w, h;539int x, y;540jobject jdata;541float *kern;542543/* This function requires a lot of local refs ??? Is 64 enough ??? */544if ((*env)->EnsureLocalCapacity(env, 64) < 0)545return 0;546547if (s_nomlib) return 0;548if (s_timeIt) (*start_timer)(3600);549550kwidth = (*env)->GetIntField(env, jkernel, g_KernelWidthID);551kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID);552jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID);553klen = (*env)->GetArrayLength(env, jdata);554kern = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);555if (kern == NULL) {556/* out of memory exception already thrown */557return 0;558}559560if ((kwidth&0x1) == 0) {561/* Kernel has even width */562w = kwidth+1;563}564else {565w = kwidth;566}567if ((kheight&0x1) == 0) {568/* Kernel has even height */569h = kheight+1;570}571else {572h = kheight;573}574575dkern = NULL;576if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) {577dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64));578}579if (dkern == NULL) {580(*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);581return 0;582}583584/* Need to flip and find max value of the kernel.585* Also, save the kernel values as mlib_d64 values.586* The flip is to operate correctly with medialib,587* which doesn't do the mathemetically correct thing,588* i.e. it doesn't rotate the kernel by 180 degrees.589* REMIND: This should perhaps be done at the Java590* level by ConvolveOp.591* REMIND: Should the max test be looking at absolute592* values?593* REMIND: What if klen != kheight * kwidth?594*/595kmax = kern[klen-1];596i = klen-1;597for (y=0; y < kheight; y++) {598for (x=0; x < kwidth; x++, i--) {599dkern[y*w+x] = (mlib_d64) kern[i];600if (kern[i] > kmax) {601kmax = kern[i];602}603}604}605606(*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);607608if (kmax > 1<<16) {609/* We can only handle 16 bit max */610free(dkern);611return 0;612}613614/* Parse the source image */615if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {616JNU_ThrowOutOfMemoryError(env, "Out of memory");617free(dkern);618return -1;619}620621if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {622JNU_ThrowOutOfMemoryError(env, "Out of memory");623free(srcRasterP);624free(dkern);625return -1;626}627628/* Parse the source raster */629if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {630/* Can't handle any custom rasters */631free(srcRasterP);632free(dstRasterP);633free(dkern);634return 0;635}636637/* Parse the destination raster */638if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {639/* Can't handle any custom images */640awt_freeParsedRaster(srcRasterP, TRUE);641free(dstRasterP);642free(dkern);643return 0;644}645646/* Allocate the arrays */647if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {648/* Must be some problem */649awt_freeParsedRaster(srcRasterP, TRUE);650awt_freeParsedRaster(dstRasterP, TRUE);651free(dkern);652return 0;653}654if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {655/* Must be some problem */656freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);657awt_freeParsedRaster(srcRasterP, TRUE);658awt_freeParsedRaster(dstRasterP, TRUE);659free(dkern);660return 0;661}662663kdata = NULL;664if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) {665kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32));666}667if (kdata == NULL) {668freeDataArray(env, srcRasterP->jdata, src, sdata,669dstRasterP->jdata, dst, ddata);670awt_freeParsedRaster(srcRasterP, TRUE);671awt_freeParsedRaster(dstRasterP, TRUE);672free(dkern);673return 0;674}675676if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h,677mlib_ImageGetType(src)) != MLIB_SUCCESS) {678freeDataArray(env, srcRasterP->jdata, src, sdata,679dstRasterP->jdata, dst, ddata);680awt_freeParsedRaster(srcRasterP, TRUE);681awt_freeParsedRaster(dstRasterP, TRUE);682free(dkern);683free(kdata);684return 0;685}686687if (s_printIt) {688fprintf(stderr, "Orig Kernel(len=%d):\n",klen);689for (y=kheight-1; y >= 0; y--) {690for (x=kwidth-1; x >= 0; x--) {691fprintf(stderr, "%g ", dkern[y*w+x]);692}693fprintf(stderr, "\n");694}695fprintf(stderr, "New Kernel(scale=%d):\n", scale);696for (y=kheight-1; y >= 0; y--) {697for (x=kwidth-1; x >= 0; x--) {698fprintf(stderr, "%d ", kdata[y*w+x]);699}700fprintf(stderr, "\n");701}702}703704cmask = (1<<src->channels)-1;705status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,706(w-1)/2, (h-1)/2, scale, cmask,707getMlibEdgeHint(edgeHint));708709if (status != MLIB_SUCCESS) {710printMedialibError(status);711retStatus = 0;712}713714if (s_printIt) {715unsigned int *dP;716if (s_startOff != 0) {717printf("Starting at %d\n", s_startOff);718}719if (sdata == NULL) {720dP = (unsigned int *) mlib_ImageGetData(src);721}722else {723dP = (unsigned int *) sdata;724}725printf("src is\n");726for (i=0; i < 20; i++) {727printf("%x ",dP[s_startOff+i]);728}729printf("\n");730if (ddata == NULL) {731dP = (unsigned int *)mlib_ImageGetData(dst);732}733else {734dP = (unsigned int *) ddata;735}736printf("dst is\n");737for (i=0; i < 20; i++) {738printf("%x ",dP[s_startOff+i]);739}740printf("\n");741}742743/* Means that we couldn't write directly into the destination buffer */744if (ddata == NULL) {745if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {746retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);747}748}749750/* Release the pinned memory */751freeDataArray(env, srcRasterP->jdata, src, sdata,752dstRasterP->jdata, dst, ddata);753awt_freeParsedRaster(srcRasterP, TRUE);754awt_freeParsedRaster(dstRasterP, TRUE);755free(dkern);756free(kdata);757758if (s_timeIt) (*stop_timer)(3600,1);759760return retStatus;761}762763764JNIEXPORT jint JNICALL765Java_sun_awt_image_ImagingLib_transformBI(JNIEnv *env, jobject this,766jobject jsrc,767jobject jdst,768jdoubleArray jmatrix,769jint interpType)770{771mlib_image *src;772mlib_image *dst;773int i;774int j = 0;775int retStatus = 1;776mlib_status status;777double *matrix;778mlib_d64 mtx[6];779void *sdata;780void *ddata;781BufImageS_t *srcImageP;782BufImageS_t *dstImageP;783mlib_filter filter;784mlibHintS_t hint;785unsigned int *dP;786int useIndexed;787int nbands;788789/* This function requires a lot of local refs ??? Is 64 enough ??? */790if ((*env)->EnsureLocalCapacity(env, 64) < 0)791return 0;792793if (s_nomlib) return 0;794if (s_timeIt) {795(*start_timer)(3600);796}797798switch(interpType) {799case java_awt_image_AffineTransformOp_TYPE_BILINEAR:800filter = MLIB_BILINEAR;801break;802case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR:803filter = MLIB_NEAREST;804break;805case java_awt_image_AffineTransformOp_TYPE_BICUBIC:806filter = MLIB_BICUBIC;807break;808default:809JNU_ThrowInternalError(env, "Unknown interpolation type");810return -1;811}812813if ((*env)->GetArrayLength(env, jmatrix) < 6) {814/*815* Very unlikely, however we should check for this:816* if given matrix array is too short, we can't handle it817*/818return 0;819}820821matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL);822if (matrix == NULL) {823/* out of memory error already thrown */824return 0;825}826827/* Check for invalid double value in transformation matrix */828for (j = 0; j < 6; j++) {829830if (!(IS_FINITE(matrix[j]))) {831(*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);832return 0;833}834}835836if (s_printIt) {837printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],838matrix[2], matrix[3], matrix[4], matrix[5]);839}840841mtx[0] = matrix[0];842mtx[1] = matrix[2];843mtx[2] = matrix[4];844mtx[3] = matrix[1];845mtx[4] = matrix[3];846mtx[5] = matrix[5];847848(*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);849850/* Parse the source image */851if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {852/* Can't handle any custom images */853return 0;854}855856/* Parse the destination image */857if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {858/* Can't handle any custom images */859awt_freeParsedImage(srcImageP, TRUE);860return 0;861}862863/* REMIND!! Can't assume that it is the same LUT!! */864/* Fix 4213160, 4184283 */865useIndexed = (srcImageP->cmodel.cmType == INDEX_CM_TYPE &&866dstImageP->cmodel.cmType == INDEX_CM_TYPE &&867srcImageP->raster.rasterType == dstImageP->raster.rasterType &&868srcImageP->raster.rasterType == COMPONENT_RASTER_TYPE);869870nbands = setImageHints(env, srcImageP, dstImageP, !useIndexed, TRUE,871FALSE, &hint);872if (nbands < 1) {873/* Can't handle any custom images */874awt_freeParsedImage(srcImageP, TRUE);875awt_freeParsedImage(dstImageP, TRUE);876return 0;877}878879/* Allocate the arrays */880if (allocateArray(env, srcImageP, &src, &sdata, TRUE,881hint.cvtSrcToDefault, hint.addAlpha) < 0) {882/* Must be some problem */883awt_freeParsedImage(srcImageP, TRUE);884awt_freeParsedImage(dstImageP, TRUE);885return 0;886}887if (allocateArray(env, dstImageP, &dst, &ddata, FALSE,888hint.cvtToDst, FALSE) < 0) {889/* Must be some problem */890freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);891awt_freeParsedImage(srcImageP, TRUE);892awt_freeParsedImage(dstImageP, TRUE);893return 0;894}895#if 0896fprintf(stderr,"Src----------------\n");897fprintf(stderr,"Type : %d\n",src->type);898fprintf(stderr,"Channels: %d\n",src->channels);899fprintf(stderr,"Width : %d\n",src->width);900fprintf(stderr,"Height : %d\n",src->height);901fprintf(stderr,"Stride : %d\n",src->stride);902fprintf(stderr,"Flags : %d\n",src->flags);903904fprintf(stderr,"Dst----------------\n");905fprintf(stderr,"Type : %d\n",dst->type);906fprintf(stderr,"Channels: %d\n",dst->channels);907fprintf(stderr,"Width : %d\n",dst->width);908fprintf(stderr,"Height : %d\n",dst->height);909fprintf(stderr,"Stride : %d\n",dst->stride);910fprintf(stderr,"Flags : %d\n",dst->flags);911#endif912913if (dstImageP->cmodel.cmType == INDEX_CM_TYPE) {914/* Need to clear the destination to the transparent pixel */915unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);916917memset(cP, dstImageP->cmodel.transIdx,918mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));919}920/* Perform the transformation */921if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,922MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))923{924printMedialibError(status);925freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);926awt_freeParsedImage(srcImageP, TRUE);927awt_freeParsedImage(dstImageP, TRUE);928929return 0;930}931932if (s_printIt) {933if (sdata == NULL) {934dP = (unsigned int *) mlib_ImageGetData(src);935}936else {937dP = (unsigned int *) sdata;938}939printf("src is\n");940for (i=0; i < 20; i++) {941printf("%x ",dP[i]);942}943printf("\n");944if (ddata == NULL) {945dP = (unsigned int *)mlib_ImageGetData(dst);946}947else {948dP = (unsigned int *) ddata;949}950printf("dst is\n");951for (i=0; i < 20; i++) {952printf("%x ",dP[i]);953}954printf("\n");955}956957/* Means that we couldn't write directly into the destination buffer */958if (ddata == NULL) {959freeDataArray(env, srcImageP->raster.jdata, src, sdata,960NULL, NULL, NULL);961/* Need to store it back into the array */962if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {963/* Error */964retStatus = 0;965}966freeDataArray(env, NULL, NULL, NULL, dstImageP->raster.jdata,967dst, ddata);968}969else {970/* Release the pinned memory */971freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);972}973974awt_freeParsedImage(srcImageP, TRUE);975awt_freeParsedImage(dstImageP, TRUE);976977if (s_timeIt) (*stop_timer)(3600,1);978979return retStatus;980}981982JNIEXPORT jint JNICALL983Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv *env, jobject this,984jobject jsrc,985jobject jdst,986jdoubleArray jmatrix,987jint interpType)988{989mlib_image *src;990mlib_image *dst;991int i;992int j = 0;993int retStatus = 1;994mlib_status status;995double *matrix;996mlib_d64 mtx[6];997void *sdata;998void *ddata;999RasterS_t *srcRasterP;1000RasterS_t *dstRasterP;1001mlib_filter filter;1002unsigned int *dP;10031004/* This function requires a lot of local refs ??? Is 64 enough ??? */1005if ((*env)->EnsureLocalCapacity(env, 64) < 0)1006return 0;10071008if (s_nomlib) return 0;1009if (s_timeIt) {1010(*start_timer)(3600);1011}10121013switch(interpType) {1014case java_awt_image_AffineTransformOp_TYPE_BILINEAR:1015filter = MLIB_BILINEAR;1016break;1017case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR:1018filter = MLIB_NEAREST;1019break;1020case java_awt_image_AffineTransformOp_TYPE_BICUBIC:1021filter = MLIB_BICUBIC;1022break;1023default:1024JNU_ThrowInternalError(env, "Unknown interpolation type");1025return -1;1026}10271028if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {1029JNU_ThrowOutOfMemoryError(env, "Out of memory");1030return -1;1031}10321033if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {1034JNU_ThrowOutOfMemoryError(env, "Out of memory");1035free(srcRasterP);1036return -1;1037}10381039if ((*env)->GetArrayLength(env, jmatrix) < 6) {1040/*1041* Very unlikely, however we should check for this:1042* if given matrix array is too short, we can't handle it.1043*/1044free(srcRasterP);1045free(dstRasterP);1046return 0;1047}10481049matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL);1050if (matrix == NULL) {1051/* out of memory error already thrown */1052free(srcRasterP);1053free(dstRasterP);1054return 0;1055}10561057/* Check for invalid double value in transformation matrix */1058for (j = 0; j < 6; j++) {10591060if (!(IS_FINITE(matrix[j]))) {1061(*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);1062free(srcRasterP);1063free(dstRasterP);1064return 0;1065}1066}10671068if (s_printIt) {1069printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],1070matrix[2], matrix[3], matrix[4], matrix[5]);1071}10721073mtx[0] = matrix[0];1074mtx[1] = matrix[2];1075mtx[2] = matrix[4];1076mtx[3] = matrix[1];1077mtx[4] = matrix[3];1078mtx[5] = matrix[5];10791080(*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);10811082/* Parse the source raster */1083if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {1084/* Can't handle any custom rasters */1085free(srcRasterP);1086free(dstRasterP);1087return 0;1088}10891090/* Parse the destination raster */1091if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {1092/* Can't handle any custom images */1093awt_freeParsedRaster(srcRasterP, TRUE);1094free(dstRasterP);1095return 0;1096}10971098/* Allocate the arrays */1099if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {1100/* Must be some problem */1101awt_freeParsedRaster(srcRasterP, TRUE);1102awt_freeParsedRaster(dstRasterP, TRUE);1103return 0;1104}1105if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {1106/* Must be some problem */1107freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);1108awt_freeParsedRaster(srcRasterP, TRUE);1109awt_freeParsedRaster(dstRasterP, TRUE);1110return 0;1111}11121113#if 01114fprintf(stderr,"Src----------------\n");1115fprintf(stderr,"Type : %d\n",src->type);1116fprintf(stderr,"Channels: %d\n",src->channels);1117fprintf(stderr,"Width : %d\n",src->width);1118fprintf(stderr,"Height : %d\n",src->height);1119fprintf(stderr,"Stride : %d\n",src->stride);1120fprintf(stderr,"Flags : %d\n",src->flags);11211122fprintf(stderr,"Dst----------------\n");1123fprintf(stderr,"Type : %d\n",dst->type);1124fprintf(stderr,"Channels: %d\n",dst->channels);1125fprintf(stderr,"Width : %d\n",dst->width);1126fprintf(stderr,"Height : %d\n",dst->height);1127fprintf(stderr,"Stride : %d\n",dst->stride);1128fprintf(stderr,"Flags : %d\n",dst->flags);1129#endif11301131{1132unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);11331134memset(cP, 0, mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));1135}11361137/* Perform the transformation */1138if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,1139MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))1140{1141printMedialibError(status);1142/* REMIND: Free the regions */1143return 0;1144}11451146if (s_printIt) {1147if (sdata == NULL) {1148dP = (unsigned int *) mlib_ImageGetData(src);1149}1150else {1151dP = (unsigned int *) sdata;1152}1153printf("src is\n");1154for (i=0; i < 20; i++) {1155printf("%x ",dP[i]);1156}1157printf("\n");1158if (ddata == NULL) {1159dP = (unsigned int *)mlib_ImageGetData(dst);1160}1161else {1162dP = (unsigned int *) ddata;1163}1164printf("dst is\n");1165for (i=0; i < 20; i++) {1166printf("%x ",dP[i]);1167}1168printf("\n");1169}11701171/* Means that we couldn't write directly into the destination buffer */1172if (ddata == NULL) {1173/* Need to store it back into the array */1174if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {1175(*env)->ExceptionClear(env); // Could not store the array, try another way1176retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);1177}1178}11791180/* Release the pinned memory */1181freeDataArray(env, srcRasterP->jdata, src, sdata,1182dstRasterP->jdata, dst, ddata);11831184awt_freeParsedRaster(srcRasterP, TRUE);1185awt_freeParsedRaster(dstRasterP, TRUE);11861187if (s_timeIt) (*stop_timer)(3600,1);11881189return retStatus;1190}11911192typedef struct {1193jobject jArray;1194jsize length;1195unsigned char *table;1196} LookupArrayInfo;11971198#define NLUT 811991200#ifdef _LITTLE_ENDIAN1201#define INDEXES { 3, 2, 1, 0, 7, 6, 5, 4 }1202#else1203#define INDEXES { 0, 1, 2, 3, 4, 5, 6, 7 }1204#endif12051206static int lookupShortData(mlib_image* src, mlib_image* dst,1207LookupArrayInfo* lookup)1208{1209int x, y;1210unsigned int mask = NLUT-1;12111212unsigned short* srcLine = (unsigned short*)src->data;1213unsigned char* dstLine = (unsigned char*)dst->data;12141215static int indexes[NLUT] = INDEXES;12161217if (src->width != dst->width || src->height != dst->height) {1218return 0;1219}12201221for (y=0; y < src->height; y++) {1222int nloop, nx;1223int npix = src->width;12241225unsigned short* srcPixel = srcLine;1226unsigned char* dstPixel = dstLine;12271228#ifdef SIMPLE_LOOKUP_LOOP1229for (x=0; status && x < width; x++) {1230unsigned short s = *srcPixel++;1231if (s >= lookup->length) {1232/* we can not handle source image using1233* byte lookup table. Fall back to processing1234* images in java1235*/1236return 0;1237}1238*dstPixel++ = lookup->table[s];1239}1240#else1241/* Get to 32 bit-aligned point */1242while(((uintptr_t)dstPixel & 0x3) != 0 && npix>0) {1243unsigned short s = *srcPixel++;1244if (s >= lookup->length) {1245return 0;1246}1247*dstPixel++ = lookup->table[s];1248npix--;1249}12501251/*1252* Do NLUT pixels per loop iteration.1253* Pack into ints and write out 2 at a time.1254*/1255nloop = npix/NLUT;1256nx = npix%NLUT;12571258for(x=nloop; x!=0; x--) {1259int i = 0;1260int* dstP = (int*)dstPixel;12611262for (i = 0; i < NLUT; i++) {1263if (srcPixel[i] >= lookup->length) {1264return 0;1265}1266}12671268dstP[0] = (int)1269((lookup->table[srcPixel[indexes[0]]] << 24) |1270(lookup->table[srcPixel[indexes[1]]] << 16) |1271(lookup->table[srcPixel[indexes[2]]] << 8) |1272lookup->table[srcPixel[indexes[3]]]);1273dstP[1] = (int)1274((lookup->table[srcPixel[indexes[4]]] << 24) |1275(lookup->table[srcPixel[indexes[5]]] << 16) |1276(lookup->table[srcPixel[indexes[6]]] << 8) |1277lookup->table[srcPixel[indexes[7]]]);127812791280dstPixel += NLUT;1281srcPixel += NLUT;1282}12831284/*1285* Complete any remaining pixels1286*/1287for(x=nx; x!=0; x--) {1288unsigned short s = *srcPixel++;1289if (s >= lookup->length) {1290return 0;1291}1292*dstPixel++ = lookup->table[s];1293}1294#endif12951296dstLine += dst->stride; // array of bytes, scan stride in bytes1297srcLine += src->stride / 2; // array of shorts, scan stride in bytes1298}1299return 1;1300}13011302JNIEXPORT jint JNICALL1303Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject thisLib,1304jobject jsrc, jobject jdst,1305jobjectArray jtableArrays)1306{1307mlib_image *src;1308mlib_image *dst;1309void *sdata, *ddata;1310unsigned char **tbl;1311unsigned char lut[256];1312int retStatus = 1;1313int i;1314mlib_status status;1315int lut_nbands;1316LookupArrayInfo *jtable;1317BufImageS_t *srcImageP, *dstImageP;1318int nbands;1319int ncomponents;1320mlibHintS_t hint;13211322/* This function requires a lot of local refs ??? Is 64 enough ??? */1323if ((*env)->EnsureLocalCapacity(env, 64) < 0)1324return 0;13251326if (s_nomlib) return 0;1327if (s_timeIt) (*start_timer)(3600);13281329/* Parse the source image */1330if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {1331/* Can't handle any custom images */1332return 0;1333}13341335/* Parse the destination image */1336if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {1337/* Can't handle any custom images */1338awt_freeParsedImage(srcImageP, TRUE);1339return 0;1340}13411342nbands = setImageHints(env, srcImageP, dstImageP, FALSE, TRUE,1343FALSE, &hint);13441345if (nbands < 1 || nbands > srcImageP->cmodel.numComponents) {1346/* Can't handle any custom images */1347awt_freeParsedImage(srcImageP, TRUE);1348awt_freeParsedImage(dstImageP, TRUE);1349return 0;1350}13511352ncomponents = srcImageP->cmodel.isDefaultCompatCM1353? 41354: srcImageP->cmodel.numComponents;13551356/* Make sure that color order can be used for1357* re-ordering of lookup arrays.1358*/1359for (i = 0; i < nbands; i++) {1360int idx = srcImageP->hints.colorOrder[i];13611362if (idx < 0 || idx >= ncomponents) {1363awt_freeParsedImage(srcImageP, TRUE);1364awt_freeParsedImage(dstImageP, TRUE);1365return 0;1366}1367}13681369lut_nbands = (*env)->GetArrayLength(env, jtableArrays);13701371if (lut_nbands > ncomponents) {1372lut_nbands = ncomponents;1373}13741375tbl = NULL;1376if (SAFE_TO_ALLOC_2(ncomponents, sizeof(unsigned char *))) {1377tbl = (unsigned char **)1378calloc(1, ncomponents * sizeof(unsigned char *));1379}13801381jtable = NULL;1382if (SAFE_TO_ALLOC_2(lut_nbands, sizeof(LookupArrayInfo))) {1383jtable = (LookupArrayInfo *)malloc(lut_nbands * sizeof (LookupArrayInfo));1384}13851386if (tbl == NULL || jtable == NULL) {1387if (tbl != NULL) free(tbl);1388if (jtable != NULL) free(jtable);1389awt_freeParsedImage(srcImageP, TRUE);1390awt_freeParsedImage(dstImageP, TRUE);1391JNU_ThrowNullPointerException(env, "NULL LUT");1392return 0;1393}1394/* Need to grab these pointers before we lock down arrays */1395for (i=0; i < lut_nbands; i++) {1396jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);13971398if (jtable[i].jArray != NULL) {1399jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);1400jtable[i].table = NULL;14011402if (jtable[i].length < 256) {1403/* we may read outside the table during lookup */1404jtable[i].jArray = NULL;1405jtable[i].length = 0;1406}1407}1408if (jtable[i].jArray == NULL) {1409free(tbl);1410free(jtable);1411awt_freeParsedImage(srcImageP, TRUE);1412awt_freeParsedImage(dstImageP, TRUE);1413return 0;1414}1415}14161417/* Allocate the arrays */1418if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) {1419/* Must be some problem */1420free(tbl);1421free(jtable);1422awt_freeParsedImage(srcImageP, TRUE);1423awt_freeParsedImage(dstImageP, TRUE);1424return 0;1425}1426if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) {1427/* Must be some problem */1428free(tbl);1429free(jtable);1430freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);1431awt_freeParsedImage(srcImageP, TRUE);1432awt_freeParsedImage(dstImageP, TRUE);1433return 0;1434}14351436/* Set up a straight lut so we don't mess around with alpha */1437/*1438* NB: medialib lookup routine expects lookup array for each1439* component of source image including alpha.1440* If lookup table we got form the java layer does not contain1441* sufficient number of lookup arrays we add references to identity1442* lookup array to make medialib happier.1443*/1444if (lut_nbands < ncomponents) {1445int j;1446/* REMIND: This should be the size of the input lut!! */1447for (j=0; j < 256; j++) {1448lut[j] = j;1449}1450for (j=0; j < ncomponents; j++) {1451tbl[j] = lut;1452}1453}14541455for (i=0; i < lut_nbands; i++) {1456jtable[i].table = (unsigned char *)1457(*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);1458if (jtable[i].table == NULL) {1459/* Free what we've got so far. */1460int j;1461for (j = 0; j < i; j++) {1462(*env)->ReleasePrimitiveArrayCritical(env,1463jtable[j].jArray,1464(jbyte *) jtable[j].table,1465JNI_ABORT);1466}1467free(tbl);1468free(jtable);1469freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);1470awt_freeParsedImage(srcImageP, TRUE);1471awt_freeParsedImage(dstImageP, TRUE);1472return 0;1473}1474tbl[srcImageP->hints.colorOrder[i]] = jtable[i].table;1475}14761477if (lut_nbands == 1) {1478for (i=1; i < nbands -1479srcImageP->cmodel.supportsAlpha; i++) {1480tbl[srcImageP->hints.colorOrder[i]] = jtable[0].table;1481}1482}14831484/* Mlib needs 16bit lookuptable and must be signed! */1485if (src->type == MLIB_SHORT) {1486if (dst->type == MLIB_BYTE) {1487if (nbands > 1) {1488retStatus = 0;1489}1490else {1491retStatus = lookupShortData(src, dst, &jtable[0]);1492}1493}1494/* How about ddata == null? */1495}1496else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,1497(void **)tbl) != MLIB_SUCCESS)) {1498printMedialibError(status);1499retStatus = 0;1500}15011502/* Release the LUT */1503for (i=0; i < lut_nbands; i++) {1504(*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,1505(jbyte *) jtable[i].table, JNI_ABORT);1506}1507free ((void *) jtable);1508free ((void *) tbl);15091510/*1511* Means that we couldn't write directly into1512* the destination buffer1513*/1514if (ddata == NULL) {15151516/* Need to store it back into the array */1517if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {1518/* Error */1519retStatus = 0;1520}1521}152215231524/* Release the pinned memory */1525freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);15261527awt_freeParsedImage(srcImageP, TRUE);1528awt_freeParsedImage(dstImageP, TRUE);15291530if (s_timeIt) (*stop_timer)(3600, 1);15311532return retStatus;1533}15341535JNIEXPORT jint JNICALL1536Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env,1537jobject this,1538jobject jsrc,1539jobject jdst,1540jobjectArray jtableArrays)1541{1542RasterS_t* srcRasterP;1543RasterS_t* dstRasterP;1544mlib_image* src;1545mlib_image* dst;1546void* sdata;1547void* ddata;1548LookupArrayInfo jtable[4];1549unsigned char* mlib_lookupTable[4];1550int i;1551int retStatus = 1;1552mlib_status status;1553int jlen;1554int lut_nbands;1555int src_nbands;1556int dst_nbands;1557unsigned char ilut[256];15581559/* This function requires a lot of local refs ??? Is 64 enough ??? */1560if ((*env)->EnsureLocalCapacity(env, 64) < 0)1561return 0;15621563if (s_nomlib) return 0;1564if (s_timeIt) (*start_timer)(3600);15651566if ((srcRasterP = (RasterS_t*) calloc(1, sizeof(RasterS_t))) == NULL) {1567JNU_ThrowOutOfMemoryError(env, "Out of memory");1568return -1;1569}15701571if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {1572JNU_ThrowOutOfMemoryError(env, "Out of memory");1573free(srcRasterP);1574return -1;1575}15761577/* Parse the source raster - reject custom images */1578if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {1579free(srcRasterP);1580free(dstRasterP);1581return 0;1582}15831584/* Parse the destination image - reject custom images */1585if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {1586awt_freeParsedRaster(srcRasterP, TRUE);1587free(dstRasterP);1588return 0;1589}15901591jlen = (*env)->GetArrayLength(env, jtableArrays);15921593lut_nbands = jlen;1594src_nbands = srcRasterP->numBands;1595dst_nbands = dstRasterP->numBands;15961597/* adjust number of lookup bands */1598if (lut_nbands > src_nbands) {1599lut_nbands = src_nbands;1600}16011602/* MediaLib can't do more than 4 bands */1603if (src_nbands <= 0 || src_nbands > 4 ||1604dst_nbands <= 0 || dst_nbands > 4 ||1605lut_nbands <= 0 || lut_nbands > 4 ||1606src_nbands != dst_nbands ||1607((lut_nbands != 1) && (lut_nbands != src_nbands)))1608{1609// we should free parsed rasters here1610awt_freeParsedRaster(srcRasterP, TRUE);1611awt_freeParsedRaster(dstRasterP, TRUE);1612return 0;1613}16141615/* Allocate the raster arrays */1616if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {1617/* Must be some problem */1618awt_freeParsedRaster(srcRasterP, TRUE);1619awt_freeParsedRaster(dstRasterP, TRUE);1620return 0;1621}1622if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {1623/* Must be some problem */1624freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);1625awt_freeParsedRaster(srcRasterP, TRUE);1626awt_freeParsedRaster(dstRasterP, TRUE);1627return 0;1628}16291630/*1631* Well, until now we have analyzed number of bands in1632* src and dst rasters.1633* However, it is not enough because medialib lookup routine uses1634* number of channels of medialib image. Note that in certain1635* case number of channels may differs form the number of bands.1636* Good example is raster that is used in TYPE_INT_RGB buffered1637* image: it has 3 bands, but their medialib representation has1638* 4 channels.1639*1640* In order to avoid the lookup routine failure, we need:1641*1642* 1. verify that src and dst have same number of channels.1643* 2. provide lookup array for every channel. If we have "extra"1644* channel (like the raster described above) then we need to1645* provide identical lookup array.1646*/1647if (src->channels != dst->channels) {1648freeDataArray(env, srcRasterP->jdata, src, sdata,1649dstRasterP->jdata, dst, ddata);16501651awt_freeParsedRaster(srcRasterP, TRUE);1652awt_freeParsedRaster(dstRasterP, TRUE);1653return 0;1654}16551656if (src_nbands < src->channels) {1657for (i = 0; i < 256; i++) {1658ilut[i] = i;1659}1660}166116621663/* Get references to the lookup table arrays */1664/* Need to grab these pointers before we lock down arrays */1665for (i=0; i < lut_nbands; i++) {1666jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);1667jtable[i].table = NULL;1668if (jtable[i].jArray != NULL) {1669jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);1670if (jtable[i].length < 256) {1671/* we may read outside the table during lookup */1672jtable[i].jArray = NULL;1673}1674}16751676if (jtable[i].jArray == NULL)1677{1678freeDataArray(env, srcRasterP->jdata, src, sdata,1679dstRasterP->jdata, dst, ddata);16801681awt_freeParsedRaster(srcRasterP, TRUE);1682awt_freeParsedRaster(dstRasterP, TRUE);1683return 0;1684}1685}16861687for (i=0; i < lut_nbands; i++) {1688jtable[i].table = (unsigned char *)1689(*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);1690if (jtable[i].table == NULL) {1691/* Free what we've got so far. */1692int j;1693for (j = 0; j < i; j++) {1694(*env)->ReleasePrimitiveArrayCritical(env,1695jtable[j].jArray,1696(jbyte *) jtable[j].table,1697JNI_ABORT);1698}1699freeDataArray(env, srcRasterP->jdata, src, sdata,1700dstRasterP->jdata, dst, ddata);1701awt_freeParsedRaster(srcRasterP, TRUE);1702awt_freeParsedRaster(dstRasterP, TRUE);1703return 0;1704}1705mlib_lookupTable[i] = jtable[i].table;1706}17071708/*1709* Medialib routine expects lookup array for each band of raster.1710* Setup the rest of lookup arrays if supplied lookup table1711* contains single lookup array.1712*/1713for (i = lut_nbands; i < src_nbands; i++) {1714mlib_lookupTable[i] = jtable[0].table;1715}17161717/*1718* Setup lookup array for "extra" channels1719*/1720for ( ; i < src->channels; i++) {1721mlib_lookupTable[i] = ilut;1722}17231724/* Mlib needs 16bit lookuptable and must be signed! */1725if (src->type == MLIB_SHORT) {1726if (dst->type == MLIB_BYTE) {1727if (lut_nbands > 1) {1728retStatus = 0;1729} else {1730retStatus = lookupShortData(src, dst, &jtable[0]);1731}1732}1733/* How about ddata == null? */1734} else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,1735(void **)mlib_lookupTable) != MLIB_SUCCESS)) {1736printMedialibError(status);1737retStatus = 0;1738}17391740/* Release the LUT */1741for (i=0; i < lut_nbands; i++) {1742(*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,1743(jbyte *) jtable[i].table, JNI_ABORT);1744}17451746/*1747* Means that we couldn't write directly into1748* the destination buffer1749*/1750if (ddata == NULL) {1751if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {1752retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);1753}1754}17551756/* Release the pinned memory */1757freeDataArray(env, srcRasterP->jdata, src, sdata,1758dstRasterP->jdata, dst, ddata);17591760awt_freeParsedRaster(srcRasterP, TRUE);1761awt_freeParsedRaster(dstRasterP, TRUE);17621763if (s_timeIt) (*stop_timer)(3600, 1);17641765return retStatus;1766}176717681769JNIEXPORT jboolean JNICALL1770Java_sun_awt_image_ImagingLib_init(JNIEnv *env, jclass thisClass) {1771char *start;1772if (getenv("IMLIB_DEBUG")) {1773start_timer = awt_setMlibStartTimer();1774stop_timer = awt_setMlibStopTimer();1775if (start_timer && stop_timer) {1776s_timeIt = 1;1777}1778}17791780if (getenv("IMLIB_PRINT")) {1781s_printIt = 1;1782}1783if ((start = getenv("IMLIB_START")) != NULL) {1784sscanf(start, "%d", &s_startOff);1785}17861787if (getenv ("IMLIB_NOMLIB")) {1788s_nomlib = 1;1789return JNI_FALSE;1790}17911792/* This function is platform-dependent and is in awt_mlib.c */1793if (awt_getImagingLib(env, (mlibFnS_t *)&sMlibFns, &sMlibSysFns) !=1794MLIB_SUCCESS)1795{1796s_nomlib = 1;1797return JNI_FALSE;1798}1799return JNI_TRUE;1800}18011802/* REMIND: How to specify border? */1803static void extendEdge(JNIEnv *env, BufImageS_t *imageP,1804int *widthP, int *heightP) {1805RasterS_t *rasterP = &imageP->raster;1806int width;1807int height;1808/* Useful for convolution? */18091810jobject jbaseraster = (*env)->GetObjectField(env, rasterP->jraster,1811g_RasterBaseRasterID);1812width = rasterP->width;1813height = rasterP->height;1814#ifdef WORKING1815if (! JNU_IsNull(env, jbaseraster) &&1816!(*env)->IsSameObject(env, rasterP->jraster, jbaseraster)) {1817int xOff;1818int yOff;1819int baseWidth;1820int baseHeight;1821int baseXoff;1822int baseYoff;1823/* Not the same object so get the width and height */1824xOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterXOffsetID);1825yOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterYOffsetID);1826baseWidth = (*env)->GetIntField(env, jbaseraster, g_RasterWidthID);1827baseHeight = (*env)->GetIntField(env, jbaseraster, g_RasterHeightID);1828baseXoff = (*env)->GetIntField(env, jbaseraster, g_RasterXOffsetID);1829baseYoff = (*env)->GetIntField(env, jbaseraster, g_RasterYOffsetID);18301831if (xOff + rasterP->width < baseXoff + baseWidth) {1832/* Can use edge */1833width++;1834}1835if (yOff + rasterP->height < baseYoff + baseHeight) {1836/* Can use edge */1837height++;1838}18391840}1841#endif18421843}18441845static int1846setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,1847int expandICM, int useAlpha,1848int premultiply, mlibHintS_t *hintP)1849{1850ColorModelS_t *srcCMP = &srcP->cmodel;1851ColorModelS_t *dstCMP = &dstP->cmodel;1852int nbands = 0;1853int ncomponents;18541855hintP->dataType = srcP->raster.dataType;1856hintP->addAlpha = FALSE;18571858/* Are the color spaces the same? */1859if (srcCMP->csType != dstCMP->csType) {1860/* If the src is GRAY and dst RGB, we can handle it */1861if (!(srcCMP->csType == java_awt_color_ColorSpace_TYPE_GRAY &&1862dstCMP->csType == java_awt_color_ColorSpace_TYPE_RGB)) {1863/* Nope, need to handle that in java for now */1864return -1;1865}1866else {1867hintP->cvtSrcToDefault = TRUE;1868}1869}1870else {1871if (srcP->hints.needToExpand) {1872hintP->cvtSrcToDefault = TRUE;1873}1874else {1875/* Need to initialize this */1876hintP->cvtSrcToDefault = FALSE;1877}1878}18791880ncomponents = srcCMP->numComponents;1881if ((useAlpha == 0) && srcCMP->supportsAlpha) {1882ncomponents--; /* ?? */1883/* Not really, more like shrink src to get rid of alpha */1884hintP->cvtSrcToDefault = TRUE;1885}18861887hintP->dataType = srcP->raster.dataType;1888if (hintP->cvtSrcToDefault == FALSE) {1889if (srcCMP->cmType == INDEX_CM_TYPE) {1890if (expandICM) {1891nbands = srcCMP->numComponents;1892hintP->cvtSrcToDefault = TRUE;18931894if (dstCMP->isDefaultCompatCM) {1895hintP->allocDefaultDst = FALSE;1896hintP->cvtToDst = FALSE;1897}1898else if (dstCMP->isDefaultCompatCM) {1899hintP->allocDefaultDst = FALSE;1900hintP->cvtToDst = FALSE;1901}1902}1903else {1904nbands = 1;1905hintP->cvtSrcToDefault = FALSE;1906}19071908}1909else {1910if (srcP->hints.packing & INTERLEAVED) {1911nbands = srcCMP->numComponents;1912}1913else {1914nbands = 1;1915}19161917/* Look at the packing */1918if ((srcP->hints.packing&BYTE_INTERLEAVED)==BYTE_INTERLEAVED ||1919(srcP->hints.packing&SHORT_INTERLEAVED)==SHORT_INTERLEAVED||1920(srcP->hints.packing&BYTE_SINGLE_BAND) == BYTE_SINGLE_BAND||1921(srcP->hints.packing&SHORT_SINGLE_BAND)==SHORT_SINGLE_BAND||1922(srcP->hints.packing&BYTE_BANDED) == BYTE_BANDED ||1923(srcP->hints.packing&SHORT_BANDED) == SHORT_BANDED) {1924/* Can use src directly */1925hintP->cvtSrcToDefault = FALSE;1926}1927else {1928/* Must be packed or custom */1929hintP->cvtSrcToDefault = TRUE;1930}1931}1932}1933if (hintP->cvtSrcToDefault) {1934/* By definition */1935nbands = 4; /* What about alpha? */1936hintP->dataType = BYTE_DATA_TYPE;1937hintP->needToCopy = TRUE;19381939if (srcP->imageType == dstP->imageType) {1940hintP->cvtToDst = TRUE;1941}1942else if (dstP->cmodel.isDefaultCM) {1943/* Not necessarily */1944hintP->cvtToDst = FALSE;1945}1946else {1947hintP->cvtToDst = TRUE;1948}1949}1950else {1951int srcImageType = srcP->imageType;1952int dstImageType = dstP->imageType;1953/* Special case where we need to fill in alpha values */1954if (srcCMP->isDefaultCompatCM && dstCMP->isDefaultCompatCM) {1955int i;1956if (!srcCMP->supportsAlpha &&dstCMP->supportsAlpha) {1957hintP->addAlpha = TRUE;1958}1959for (i=0; i < srcCMP->numComponents; i++) {1960if (srcP->hints.colorOrder[i] != dstP->hints.colorOrder[i]){1961if (!srcCMP->isDefaultCM) {1962hintP->cvtSrcToDefault = TRUE;1963srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;1964}1965if (!dstCMP->isDefaultCM) {1966hintP->cvtToDst = TRUE;1967dstImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;1968}19691970break;1971}1972}1973}1974else if (srcCMP->cmType != INDEX_CM_TYPE &&1975!srcCMP->supportsAlpha && dstCMP->supportsAlpha)1976{1977/* We've already handled the index case. This is for the rest of the cases */1978srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;1979hintP->cvtSrcToDefault = TRUE;1980}19811982hintP->allocDefaultDst = FALSE;1983if (srcImageType == dstImageType) {1984/* Same image type so use it */1985hintP->cvtToDst = FALSE;1986}1987else if (srcImageType == TYPE_INT_RGB &&1988(dstImageType == TYPE_INT_ARGB ||1989dstImageType == TYPE_INT_ARGB_PRE)) {1990hintP->cvtToDst = FALSE;1991}1992else if (srcImageType == TYPE_INT_BGR &&1993(dstImageType == TYPE_4BYTE_ABGR ||1994dstImageType == TYPE_4BYTE_ABGR_PRE)) {1995hintP->cvtToDst = FALSE;1996}1997else if (srcP->hints.packing == dstP->hints.packing) {1998/* Now what? */19992000/* Check color order */20012002/* Check if just need to scale the data */20032004hintP->cvtToDst = TRUE;2005}2006else {2007/* Don't know what it is so convert it */2008hintP->allocDefaultDst = TRUE;2009hintP->cvtToDst = TRUE;2010}2011hintP->needToCopy = (ncomponents > nbands);2012}20132014return nbands;2015}201620172018static int2019expandPacked(JNIEnv *env, BufImageS_t *img, ColorModelS_t *cmP,2020RasterS_t *rasterP, int component, unsigned char *bdataP) {20212022if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {2023switch (rasterP->dataType) {2024case BYTE_DATA_TYPE:2025if (expandPackedBCR(env, rasterP, component, bdataP) < 0) {2026/* Must have been an error */2027return -1;2028}2029break;20302031case SHORT_DATA_TYPE:2032if (expandPackedICR(env, rasterP, component, bdataP) < 0) {2033/* Must have been an error */2034return -1;2035}2036break;20372038case INT_DATA_TYPE:2039if (expandPackedICR(env, rasterP, component, bdataP) < 0) {2040/* Must have been an error */2041return -1;2042}2043break;20442045default:2046/* REMIND: Return some sort of error */2047return -1;2048}2049}2050else {2051/* REMIND: Return some sort of error */2052return -1;2053}20542055return 0;2056}20572058#define NUM_LINES 1020592060static int2061cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,2062unsigned char *dataP) {2063const RasterS_t *rasterP = &imageP->raster;2064const int w = rasterP->width;2065const int h = rasterP->height;20662067int y;2068jintArray jpixels = NULL;2069jint *pixels;2070unsigned char *dP = dataP;2071int numLines = h > NUM_LINES ? NUM_LINES : h;20722073/* it is safe to calculate the scan length, because width has been verified2074* on creation of the mlib image2075*/2076const int scanLength = w * 4;20772078int nbytes = 0;2079if (!SAFE_TO_MULT(numLines, scanLength)) {2080return -1;2081}20822083nbytes = numLines * scanLength;20842085jpixels = (*env)->NewIntArray(env, nbytes);2086if (JNU_IsNull(env, jpixels)) {2087(*env)->ExceptionClear(env);2088JNU_ThrowOutOfMemoryError(env, "Out of Memory");2089return -1;2090}20912092for (y = 0; y < h; y += numLines) {2093if (y + numLines > h) {2094numLines = h - y;2095nbytes = numLines * scanLength;2096}20972098(*env)->CallObjectMethod(env, imageP->jimage,2099g_BImgGetRGBMID, 0, y,2100w, numLines,2101jpixels, 0, w);2102if ((*env)->ExceptionOccurred(env)) {2103(*env)->DeleteLocalRef(env, jpixels);2104return -1;2105}21062107pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);2108if (pixels == NULL) {2109(*env)->DeleteLocalRef(env, jpixels);2110return -1;2111}21122113memcpy(dP, pixels, nbytes);2114dP += nbytes;21152116(*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels,2117JNI_ABORT);2118}21192120/* Need to release the array */2121(*env)->DeleteLocalRef(env, jpixels);21222123return 0;2124}21252126static int2127cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component,2128unsigned char *dataP) {2129const RasterS_t *rasterP = &imageP->raster;2130const int w = rasterP->width;2131const int h = rasterP->height;21322133int y;2134jintArray jpixels = NULL;2135jint *pixels;2136unsigned char *dP = dataP;2137int numLines = h > NUM_LINES ? NUM_LINES : h;21382139/* it is safe to calculate the scan length, because width has been verified2140* on creation of the mlib image2141*/2142const int scanLength = w * 4;21432144int nbytes = 0;2145if (!SAFE_TO_MULT(numLines, scanLength)) {2146return -1;2147}21482149nbytes = numLines * scanLength;21502151jpixels = (*env)->NewIntArray(env, nbytes);2152if (JNU_IsNull(env, jpixels)) {2153(*env)->ExceptionClear(env);2154JNU_ThrowOutOfMemoryError(env, "Out of Memory");2155return -1;2156}21572158for (y = 0; y < h; y += numLines) {2159if (y + numLines > h) {2160numLines = h - y;2161nbytes = numLines * scanLength;2162}21632164pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);2165if (pixels == NULL) {2166(*env)->DeleteLocalRef(env, jpixels);2167return -1;2168}21692170memcpy(pixels, dP, nbytes);2171dP += nbytes;21722173(*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, 0);21742175(*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y,2176w, numLines, jpixels,21770, w);2178if ((*env)->ExceptionOccurred(env)) {2179(*env)->DeleteLocalRef(env, jpixels);2180return -1;2181}2182}21832184/* Need to release the array */2185(*env)->DeleteLocalRef(env, jpixels);21862187return 0;2188}21892190static int2191allocateArray(JNIEnv *env, BufImageS_t *imageP,2192mlib_image **mlibImagePP, void **dataPP, int isSrc,2193int cvtToDefault, int addAlpha) {2194void *dataP;2195unsigned char *cDataP;2196RasterS_t *rasterP = &imageP->raster;2197ColorModelS_t *cmP = &imageP->cmodel;2198int dataType = BYTE_DATA_TYPE;2199int width;2200int height;2201HintS_t *hintP = &imageP->hints;2202*dataPP = NULL;22032204width = rasterP->width;2205height = rasterP->height;22062207/* Useful for convolution? */2208/* This code is zero'ed out so that it cannot be called */22092210/* To do this correctly, we need to expand src and dst in the */2211/* same direction up/down/left/right only if both can be expanded */2212/* in that direction. Expanding right and down is easy - */2213/* increment width. Expanding top and left requires bumping */2214/* around pointers and incrementing the width/height */22152216#if 02217if (0 && useEdges) {2218baseWidth = rasterP->baseRasterWidth;2219baseHeight = rasterP->baseRasterHeight;2220baseXoff = rasterP->baseOriginX;2221baseYoff = rasterP->baseOriginY;22222223if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {2224/* Can use edge */2225width++;2226}2227if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {2228/* Can use edge */2229height++;2230}22312232if (rasterP->minX > baseXoff ) {2233/* Can use edge */2234width++;2235/* NEED TO BUMP POINTER BACK A PIXELSTRIDE */2236}2237if (rasterP->minY > baseYoff) {2238/* Can use edge */2239height++;2240/* NEED TO BUMP POINTER BACK A SCANLINE */2241}224222432244}2245#endif2246if (cvtToDefault) {2247int status = 0;2248*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);2249if (*mlibImagePP == NULL) {2250return -1;2251}2252cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2253/* Make sure the image is cleared.2254* NB: the image dimension is already verified, so we can2255* safely calculate the length of the buffer.2256*/2257memset(cDataP, 0, width*height*4);22582259if (!isSrc) {2260return 0;2261}22622263switch(imageP->cmodel.cmType) {2264case INDEX_CM_TYPE:2265/* REMIND: Need to rearrange according to dst cm */2266/* Fix 4213160, 4184283 */2267if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {2268return expandICM(env, imageP, (unsigned int *)cDataP);2269}2270else {2271return cvtCustomToDefault(env, imageP, -1, cDataP);2272}22732274case DIRECT_CM_TYPE:2275switch(imageP->raster.dataType) {2276case BYTE_DATA_TYPE:2277return expandPackedBCRdefault(env, rasterP, -1, cDataP,2278!imageP->cmodel.supportsAlpha);2279case SHORT_DATA_TYPE:2280return expandPackedSCRdefault(env, rasterP, -1, cDataP,2281!imageP->cmodel.supportsAlpha);2282case INT_DATA_TYPE:2283return expandPackedICRdefault(env, rasterP, -1, cDataP,2284!imageP->cmodel.supportsAlpha);2285}2286} /* switch(imageP->cmodel.cmType) */22872288return cvtCustomToDefault(env, imageP, -1, cDataP);2289}22902291/* Interleaved with shared data */2292dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2293NULL);2294if (dataP == NULL) {2295return -1;2296}22972298/* Means we need to fill in alpha */2299if (!cvtToDefault && addAlpha) {2300*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);2301if (*mlibImagePP != NULL) {2302unsigned int *dstP = (unsigned int *)2303mlib_ImageGetData(*mlibImagePP);2304int dstride = (*mlibImagePP)->stride>>2;2305int sstride = hintP->sStride>>2;2306unsigned int *srcP = (unsigned int *)2307((unsigned char *)dataP + hintP->dataOffset);2308unsigned int *dP, *sP;2309int x, y;2310for (y=0; y < height; y++, srcP += sstride, dstP += dstride){2311sP = srcP;2312dP = dstP;2313for (x=0; x < width; x++) {2314dP[x] = sP[x] | 0xff000000;2315}2316}2317}2318(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2319JNI_ABORT);2320return 0;2321}2322else if ((hintP->packing & BYTE_INTERLEAVED) == BYTE_INTERLEAVED) {2323int nChans = (cmP->isDefaultCompatCM ? 4 : hintP->numChans);2324/* Easy case. It is or is similar to the default CM so use2325* the array. Must be byte data.2326*/2327/* Create the medialib image */2328*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE,2329nChans,2330width,2331height,2332hintP->sStride,2333(unsigned char *)dataP2334+ hintP->dataOffset);2335}2336else if ((hintP->packing & SHORT_INTERLEAVED) == SHORT_INTERLEAVED) {2337*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,2338hintP->numChans,2339width,2340height,2341imageP->raster.scanlineStride*2,2342(unsigned short *)dataP2343+ hintP->channelOffset);2344}2345else {2346/* Release the data array */2347(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2348JNI_ABORT);2349return -1;2350}23512352*dataPP = dataP;2353return 0;2354}23552356static int2357allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,2358mlib_image **mlibImagePP, void **dataPP, int isSrc) {2359void *dataP;2360unsigned char *cDataP;2361int dataType = BYTE_DATA_TYPE;2362int width;2363int height;2364int dataSize;2365int offset;23662367*dataPP = NULL;23682369width = rasterP->width;2370height = rasterP->height;23712372if (rasterP->numBands <= 0 || rasterP->numBands > 4) {2373/* REMIND: Fix this */2374return -1;2375}23762377/* Useful for convolution? */2378/* This code is zero'ed out so that it cannot be called */23792380/* To do this correctly, we need to expand src and dst in the */2381/* same direction up/down/left/right only if both can be expanded */2382/* in that direction. Expanding right and down is easy - */2383/* increment width. Expanding top and left requires bumping */2384/* around pointers and incrementing the width/height */23852386#if 02387if (0 && useEdges) {2388baseWidth = rasterP->baseRasterWidth;2389baseHeight = rasterP->baseRasterHeight;2390baseXoff = rasterP->baseOriginX;2391baseYoff = rasterP->baseOriginY;23922393if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {2394/* Can use edge */2395width++;2396}2397if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {2398/* Can use edge */2399height++;2400}24012402if (rasterP->minX > baseXoff ) {2403/* Can use edge */2404width++;2405/* NEED TO BUMP POINTER BACK A PIXELSTRIDE */2406}2407if (rasterP->minY > baseYoff) {2408/* Can use edge */2409height++;2410/* NEED TO BUMP POINTER BACK A SCANLINE */2411}241224132414}2415#endif2416switch (rasterP->type) {2417case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:2418if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&2419SAFE_TO_ALLOC_2(width, 4) &&2420SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4)))2421{2422return -1;2423}2424offset = 4 * rasterP->chanOffsets[0];2425dataSize = 4 * (*env)->GetArrayLength(env, rasterP->jdata);24262427if (offset < 0 || offset >= dataSize ||2428width > rasterP->scanlineStride ||2429((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset)2430{2431// raster data buffer is too short2432return -1;2433}2434dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2435NULL);2436if (dataP == NULL) {2437return -1;2438}2439*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, 4,2440width, height,2441rasterP->scanlineStride*4,2442(unsigned char *)dataP + offset);2443*dataPP = dataP;2444return 0;2445case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:2446if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&2447SAFE_TO_ALLOC_2(rasterP->scanlineStride, height)))2448{2449return -1;2450}2451offset = rasterP->chanOffsets[0];2452dataSize = (*env)->GetArrayLength(env, rasterP->jdata);24532454if (offset < 0 || offset >= dataSize ||2455width * rasterP->numBands > rasterP->scanlineStride ||2456((width * rasterP->numBands) +2457(height - 1) * rasterP->scanlineStride) > dataSize - offset)2458{2459// raster data buffer is too short2460return -1;2461}2462dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2463NULL);2464if (dataP == NULL) {2465return -1;2466}2467*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, rasterP->numBands,2468width, height,2469rasterP->scanlineStride,2470(unsigned char *)dataP + offset);2471*dataPP = dataP;2472return 0;2473case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:2474if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&2475SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&2476SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 2)))2477{2478return -1;2479}2480offset = rasterP->chanOffsets[0] * 2;2481dataSize = 2 * (*env)->GetArrayLength(env, rasterP->jdata);24822483if (offset < 0 || offset >= dataSize ||2484width * rasterP->numBands > rasterP->scanlineStride ||2485(((width * rasterP->numBands) +2486(height - 1) * rasterP->scanlineStride)) * 2 > dataSize - offset)2487{2488// raster data buffer is too short2489return -1;2490}2491dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2492NULL);2493if (dataP == NULL) {2494return -1;2495}2496*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,2497rasterP->numBands,2498width, height,2499rasterP->scanlineStride*2,2500(unsigned char *)dataP + offset);2501*dataPP = dataP;2502return 0;25032504case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:2505*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2506width, height);2507if (*mlibImagePP == NULL) {2508return -1;2509}2510if (!isSrc) return 0;2511cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2512return expandPackedBCR(env, rasterP, -1, cDataP);25132514case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:2515if (rasterP->sppsm.maxBitSize <= 8) {2516*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2517width, height);2518if (*mlibImagePP == NULL) {2519return -1;2520}2521if (!isSrc) return 0;2522cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2523return expandPackedSCR(env, rasterP, -1, cDataP);2524}2525break;2526case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:2527if (rasterP->sppsm.maxBitSize <= 8) {2528*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2529width, height);2530if (*mlibImagePP == NULL) {2531return -1;2532}2533if (!isSrc) return 0;2534cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2535return expandPackedICR(env, rasterP, -1, cDataP);2536}2537break;2538}25392540/* Just expand it right now */2541switch (rasterP->dataType) {2542case BYTE_DATA_TYPE:2543if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2544width, height)) == NULL) {2545return -1;2546}2547if (isSrc) {2548if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {2549(*sMlibSysFns.deleteImageFP)(*mlibImagePP);2550return -1;2551}2552}2553break;25542555case SHORT_DATA_TYPE:2556if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_SHORT,2557rasterP->numBands,2558width, height)) == NULL) {2559return -1;2560}2561if (isSrc) {2562if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {2563(*sMlibSysFns.deleteImageFP)(*mlibImagePP);2564return -1;2565}2566}2567break;25682569default:2570return -1;2571}2572return 0;2573}25742575static void2576freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,2577void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,2578void *dstdataP) {2579jobject srcJdata = (srcimageP != NULL ? srcimageP->raster.jdata : NULL);2580jobject dstJdata = (dstimageP != NULL ? dstimageP->raster.jdata : NULL);2581freeDataArray(env, srcJdata, srcmlibImP, srcdataP,2582dstJdata, dstmlibImP, dstdataP);2583}2584static void2585freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,2586void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,2587void *dstdataP)2588{2589/* Free the medialib image */2590if (srcmlibImP) {2591(*sMlibSysFns.deleteImageFP)(srcmlibImP);2592}25932594/* Release the array */2595if (srcdataP) {2596(*env)->ReleasePrimitiveArrayCritical(env, srcJdata,2597srcdataP, JNI_ABORT);2598}25992600/* Free the medialib image */2601if (dstmlibImP) {2602(*sMlibSysFns.deleteImageFP)(dstmlibImP);2603}26042605/* Release the array */2606if (dstdataP) {2607(*env)->ReleasePrimitiveArrayCritical(env, dstJdata,2608dstdataP, 0);2609}2610}26112612#define ERR_BAD_IMAGE_LAYOUT (-2)26132614#define CHECK_DST_ARRAY(start_offset, elements_per_scan, elements_per_pixel) \2615do { \2616int offset = (start_offset); \2617int lastScanOffset; \2618\2619if (!SAFE_TO_MULT((elements_per_scan), \2620(rasterP->height - 1))) \2621{ \2622return ERR_BAD_IMAGE_LAYOUT; \2623} \2624lastScanOffset = (elements_per_scan) * (rasterP->height - 1); \2625\2626if (!SAFE_TO_ADD(offset, lastScanOffset)) { \2627return ERR_BAD_IMAGE_LAYOUT; \2628} \2629lastScanOffset += offset; \2630\2631if (!SAFE_TO_MULT((elements_per_pixel), rasterP->width)) { \2632return ERR_BAD_IMAGE_LAYOUT; \2633} \2634offset = (elements_per_pixel) * rasterP->width; \2635\2636if (!SAFE_TO_ADD(offset, lastScanOffset)) { \2637return ERR_BAD_IMAGE_LAYOUT; \2638} \2639lastScanOffset += offset; \2640\2641if (dataArrayLength < lastScanOffset) { \2642return ERR_BAD_IMAGE_LAYOUT; \2643} \2644} while(0); \26452646static int2647storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,2648mlib_image *mlibImP) {2649int mStride;2650unsigned char *cmDataP, *dataP, *cDataP;2651HintS_t *hintP = &dstP->hints;2652RasterS_t *rasterP = &dstP->raster;2653jsize dataArrayLength = (*env)->GetArrayLength(env, rasterP->jdata);2654int y;26552656/* REMIND: Store mlib data type? */26572658/* Check if it is an IndexColorModel */2659if (dstP->cmodel.cmType == INDEX_CM_TYPE) {2660if (dstP->raster.rasterType == COMPONENT_RASTER_TYPE) {2661return storeICMarray(env, srcP, dstP, mlibImP);2662}2663else {2664/* Packed or some other custom raster */2665cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2666return cvtDefaultToCustom(env, dstP, -1, cmDataP);2667}2668}26692670if (hintP->packing == BYTE_INTERLEAVED) {2671/* Write it back to the destination */2672if (rasterP->dataType != BYTE_DATA_TYPE) {2673/* We are working with a raster which was marked2674as a byte interleaved due to performance reasons.2675So, we have to convert the length of the data2676array to bytes as well.2677*/2678if (!SAFE_TO_MULT(rasterP->dataSize, dataArrayLength)) {2679return ERR_BAD_IMAGE_LAYOUT;2680}2681dataArrayLength *= rasterP->dataSize;2682}26832684CHECK_DST_ARRAY(hintP->dataOffset, hintP->sStride, hintP->numChans);2685cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2686mStride = mlib_ImageGetStride(mlibImP);2687dataP = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env,2688rasterP->jdata, NULL);2689if (dataP == NULL) return 0;2690cDataP = dataP + hintP->dataOffset;2691for (y=0; y < rasterP->height;2692y++, cmDataP += mStride, cDataP += hintP->sStride)2693{2694memcpy(cDataP, cmDataP, rasterP->width*hintP->numChans);2695}2696(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2697JNI_ABORT);2698}2699else if (dstP->cmodel.cmType == DIRECT_CM_TYPE) {2700/* Just need to move bits */2701if (mlibImP->type == MLIB_BYTE) {2702if (dstP->hints.packing == PACKED_BYTE_INTER) {2703return setPackedBCRdefault(env, rasterP, -1,2704(unsigned char *) mlibImP->data,2705dstP->cmodel.supportsAlpha);2706} else if (dstP->hints.packing == PACKED_SHORT_INTER) {2707return setPackedSCRdefault(env, rasterP, -1,2708(unsigned char *) mlibImP->data,2709dstP->cmodel.supportsAlpha);2710} else if (dstP->hints.packing == PACKED_INT_INTER) {2711return setPackedICRdefault(env, rasterP, -1,2712(unsigned char *) mlibImP->data,2713dstP->cmodel.supportsAlpha);2714}2715}2716else if (mlibImP->type == MLIB_SHORT) {2717return setPixelsFormMlibImage(env, rasterP, mlibImP);2718}2719}2720else {2721return cvtDefaultToCustom(env, dstP, -1,2722(unsigned char *)mlibImP->data);2723}27242725return 0;2726}27272728static int2729storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,2730mlib_image *mlibImP) {2731unsigned char *cDataP;27322733switch(dstP->type) {2734case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:2735cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2736return setPackedBCR(env, dstP, -1, cDataP);27372738case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:2739if (dstP->sppsm.maxBitSize <= 8) {2740cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2741return setPackedSCR(env, dstP, -1, cDataP);2742}2743break;2744case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:2745if (dstP->sppsm.maxBitSize <= 8) {2746cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2747return setPackedICR(env, dstP, -1, cDataP);2748}2749}27502751return -1;2752}275327542755static int2756storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,2757mlib_image *mlibImP)2758{2759int *argb;2760int x, y;2761unsigned char *dataP, *cDataP, *cP;2762unsigned char *sP;2763int aIdx, rIdx, gIdx, bIdx;2764ColorModelS_t *cmodelP = &dstP->cmodel;2765RasterS_t *rasterP = &dstP->raster;27662767/* REMIND: Only works for RGB */2768if (cmodelP->csType != java_awt_color_ColorSpace_TYPE_RGB) {2769JNU_ThrowInternalError(env, "Writing to non-RGB images not implemented yet");2770return -1;2771}27722773if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||2774srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||2775srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)2776{2777aIdx = 0;2778rIdx = 1;2779gIdx = 2;2780bIdx = 3;2781}2782else if (srcP->imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR||2783srcP->imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)2784{2785aIdx = 0;2786rIdx = 3;2787gIdx = 2;2788bIdx = 1;2789}2790else if (srcP->imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR){2791rIdx = 2;2792gIdx = 1;2793bIdx = 0;2794aIdx = 0; /* Ignored */2795}2796else if (srcP->cmodel.cmType == INDEX_CM_TYPE) {2797rIdx = 0;2798gIdx = 1;2799bIdx = 2;2800aIdx = 3; /* Use supportsAlpha to see if it is really there */2801}2802else {2803return -1;2804}28052806/* Lock down the destination raster */2807dataP = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env,2808rasterP->jdata, NULL);2809if (dataP == NULL) {2810return -1;2811}2812argb = (*env)->GetPrimitiveArrayCritical(env, cmodelP->jrgb, NULL);2813if (argb == NULL) {2814(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2815JNI_ABORT);2816return -1;2817}28182819cDataP = dataP + dstP->hints.dataOffset;2820sP = (unsigned char *) mlib_ImageGetData(mlibImP);28212822for (y=0; y < rasterP->height; y++, cDataP += rasterP->scanlineStride) {2823cP = cDataP;2824for (x=0; x < rasterP->width; x++, cP += rasterP->pixelStride) {2825*cP = colorMatch(sP[rIdx], sP[gIdx], sP[bIdx], sP[aIdx],2826(unsigned char *)argb, cmodelP->mapSize);2827sP += cmodelP->numComponents;2828}2829}28302831(*env)->ReleasePrimitiveArrayCritical(env, cmodelP->jrgb, argb, JNI_ABORT);2832(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2833JNI_ABORT);2834return -1;2835}28362837static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP)2838{2839ColorModelS_t *cmP = &imageP->cmodel;2840RasterS_t *rasterP = &imageP->raster;2841HintS_t *hintP = &imageP->hints;2842int *rgb;2843int status = 0;2844unsigned char *dataP, *cP;2845unsigned int *mP;2846int width = rasterP->width;2847int height = rasterP->height;2848int x, y;28492850/* Need to grab the lookup tables. Right now only bytes */2851rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, cmP->jrgb, NULL);2852CHECK_NULL_RETURN(rgb, -1);28532854/* Interleaved with shared data */2855dataP = (void *) (*env)->GetPrimitiveArrayCritical(env,2856rasterP->jdata, NULL);2857if (dataP == NULL) {2858/* Release the lookup tables */2859(*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb, JNI_ABORT);2860return -1;2861}28622863if (rasterP->dataType == BYTE_DATA_TYPE) {2864unsigned char *cDataP = ((unsigned char *)dataP) + hintP->dataOffset;28652866for (y=0; y < height; y++) {2867mP = mDataP;2868cP = cDataP;2869for (x=0; x < width; x++, cP += rasterP->pixelStride) {2870*mP++ = rgb[*cP];2871}2872mDataP += width;2873cDataP += rasterP->scanlineStride;2874}2875}2876else if (rasterP->dataType == SHORT_DATA_TYPE) {2877unsigned short *sDataP, *sP;2878sDataP = ((unsigned short *)dataP) + hintP->channelOffset;28792880for (y=0; y < height; y++) {2881mP = mDataP;2882sP = sDataP;2883for (x=0; x < width; x++, sP+=rasterP->pixelStride) {2884*mP++ = rgb[*sP];2885}2886mDataP += width;2887sDataP += rasterP->scanlineStride;2888}2889}2890else {2891/* Unknown type */2892status = -1;2893}2894/* Release the lookup table data */2895(*env)->ReleasePrimitiveArrayCritical(env, imageP->cmodel.jrgb,2896rgb, JNI_ABORT);2897/* Release the data array */2898(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata,2899dataP, JNI_ABORT);2900return status;2901}2902/* This routine is expecting a ByteComponentRaster with a PackedColorModel */2903static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,2904unsigned char *outDataP)2905{2906int x, y, c;2907unsigned char *outP = outDataP;2908unsigned char *lineInP, *inP;2909jarray jInDataP;2910jint *inDataP;2911int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];29122913if (rasterP->numBands > MAX_NUMBANDS) {2914return -1;2915}29162917/* Grab data ptr, strides, offsets from raster */2918jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);2919inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);2920if (inDataP == NULL) {2921return -1;2922}2923lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0];29242925if (component < 0) {2926for (c=0; c < rasterP->numBands; c++) {2927roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);2928if (roff[c] < 0) {2929loff[c] = -roff[c];2930roff[c] = 0;2931}2932else loff[c] = 0;2933}2934/* Convert the all bands */2935if (rasterP->numBands < 4) {2936/* Need to put in alpha */2937for (y=0; y < rasterP->height; y++) {2938inP = lineInP;2939for (x=0; x < rasterP->width; x++) {2940for (c=0; c < rasterP->numBands; c++) {2941*outP++ = (unsigned char)2942(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])2943<<loff[c]);2944}2945inP++;2946}2947lineInP += rasterP->scanlineStride;2948}2949}2950else {2951for (y=0; y < rasterP->height; y++) {2952inP = lineInP;2953for (x=0; x < rasterP->width; x++) {2954for (c=0; c < rasterP->numBands; c++) {2955*outP++ = (unsigned char)2956(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])2957<<loff[c]);2958}2959inP++;2960}2961lineInP += rasterP->scanlineStride;2962}2963}2964}2965else {2966c = component;2967roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);2968if (roff[0] < 0) {2969loff[0] = -roff[0];2970roff[0] = 0;2971}2972else loff[c] = 0;2973for (y=0; y < rasterP->height; y++) {2974inP = lineInP;2975for (x=0; x < rasterP->width; x++) {2976*outP++ = (unsigned char)2977((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];2978inP++;2979}2980lineInP += rasterP->scanlineStride;2981}2982}29832984(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);29852986return 0;2987}29882989/* This routine is expecting a ByteComponentRaster with a PackedColorModel */2990static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,2991int component, unsigned char *outDataP,2992int forceAlpha)2993{2994int x, y, c;2995unsigned char *outP = outDataP;2996unsigned char *lineInP, *inP;2997jarray jInDataP;2998jint *inDataP;2999int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3000int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);3001int a = numBands;30023003if (rasterP->numBands > MAX_NUMBANDS) {3004return -1;3005}30063007/* Grab data ptr, strides, offsets from raster */3008jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);3009inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3010if (inDataP == NULL) {3011return -1;3012}3013lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0];30143015if (component < 0) {3016for (c=0; c < rasterP->numBands; c++) {3017roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3018if (roff[c] < 0) {3019loff[c] = -roff[c];3020roff[c] = 0;3021}3022else loff[c] = 0;3023}30243025/* Need to put in alpha */3026if (forceAlpha) {3027for (y=0; y < rasterP->height; y++) {3028inP = lineInP;3029for (x=0; x < rasterP->width; x++) {3030*outP++ = 0xff;3031for (c=0; c < numBands; c++) {3032*outP++ = (unsigned char)3033(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3034<<loff[c]);3035}3036inP++;3037}3038lineInP += rasterP->scanlineStride;3039}3040}3041else {3042for (y=0; y < rasterP->height; y++) {3043inP = lineInP;3044for (x=0; x < rasterP->width; x++) {3045*outP++ = (unsigned char)3046(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])3047<<loff[a]);3048for (c=0; c < numBands; c++) {3049*outP++ = (unsigned char)3050(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3051<<loff[c]);3052}3053inP++;3054}3055lineInP += rasterP->scanlineStride;3056}3057}3058}3059else {3060c = component;3061roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3062if (roff[0] < 0) {3063loff[0] = -roff[0];3064roff[0] = 0;3065}3066else loff[c] = 0;3067for (y=0; y < rasterP->height; y++) {3068inP = lineInP;3069for (x=0; x < rasterP->width; x++) {3070*outP++ = (unsigned char)3071((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];3072inP++;3073}3074lineInP += rasterP->scanlineStride;3075}3076}30773078(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);30793080return 0;3081}30823083/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3084static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,3085unsigned char *outDataP)3086{3087int x, y, c;3088unsigned char *outP = outDataP;3089unsigned short *lineInP, *inP;3090jarray jInDataP;3091jint *inDataP;3092int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];30933094if (rasterP->numBands > MAX_NUMBANDS) {3095return -1;3096}30973098/* Grab data ptr, strides, offsets from raster */3099jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3100inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3101if (inDataP == NULL) {3102return -1;3103}3104lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0];31053106if (component < 0) {3107for (c=0; c < rasterP->numBands; c++) {3108roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3109if (roff[c] < 0) {3110loff[c] = -roff[c];3111roff[c] = 0;3112}3113else loff[c] = 0;3114}3115/* Convert the all bands */3116if (rasterP->numBands < 4) {3117/* Need to put in alpha */3118for (y=0; y < rasterP->height; y++) {3119inP = lineInP;3120for (x=0; x < rasterP->width; x++) {3121for (c=0; c < rasterP->numBands; c++) {3122/*3123*Not correct. Might need to unpremult,3124* shift, etc3125*/3126*outP++ = (unsigned char)3127(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3128<<loff[c]);3129}3130inP++;3131}3132lineInP += rasterP->scanlineStride;3133}3134} else {3135for (y=0; y < rasterP->height; y++) {3136inP = lineInP;3137for (x=0; x < rasterP->width; x++) {3138for (c=0; c < rasterP->numBands; c++) {3139/*3140*Not correct. Might need to unpremult,3141* shift, etc3142*/3143*outP++ = (unsigned char)3144(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3145<<loff[c]);3146}3147inP++;3148}3149lineInP += rasterP->scanlineStride;3150}3151}3152}3153else {3154c = component;3155roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3156if (roff[0] < 0) {3157loff[0] = -roff[0];3158roff[0] = 0;3159}3160else loff[c] = 0;3161for (y=0; y < rasterP->height; y++) {3162inP = lineInP;3163for (x=0; x < rasterP->width; x++) {3164*outP++ = (unsigned char)3165((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];3166inP++;3167}3168lineInP += rasterP->scanlineStride;3169}3170}31713172(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);31733174return 0;3175}31763177/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3178static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,3179int component, unsigned char *outDataP,3180int forceAlpha)3181{3182int x, y, c;3183unsigned char *outP = outDataP;3184unsigned short *lineInP, *inP;3185jarray jInDataP;3186jint *inDataP;3187int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3188int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);3189int a = numBands;31903191if (rasterP->numBands > MAX_NUMBANDS) {3192return -1;3193}31943195/* Grab data ptr, strides, offsets from raster */3196jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3197inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3198if (inDataP == NULL) {3199return -1;3200}3201lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0];32023203if (component < 0) {3204for (c=0; c < rasterP->numBands; c++) {3205roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3206if (roff[c] < 0) {3207loff[c] = -roff[c];3208roff[c] = 0;3209}3210else loff[c] = 0;3211}32123213/* Need to put in alpha */3214if (forceAlpha) {3215for (y=0; y < rasterP->height; y++) {3216inP = lineInP;3217for (x=0; x < rasterP->width; x++) {3218*outP++ = 0xff;3219for (c=0; c < numBands; c++) {3220/*3221* Not correct. Might need to unpremult,3222* shift, etc3223*/3224*outP++ = (unsigned char)3225(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3226<<loff[c]);3227}3228inP++;3229}3230lineInP += rasterP->scanlineStride;3231}3232}3233else {3234for (y=0; y < rasterP->height; y++) {3235inP = lineInP;3236for (x=0; x < rasterP->width; x++) {3237*outP++ = (unsigned char)3238(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])3239<<loff[a]);3240for (c=0; c < numBands; c++) {3241/*3242* Not correct. Might need to3243* unpremult, shift, etc3244*/3245*outP++ = (unsigned char)3246(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3247<<loff[c]);3248}3249inP++;3250}3251lineInP += rasterP->scanlineStride;3252}3253}3254}3255else {3256c = component;3257roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3258if (roff[0] < 0) {3259loff[0] = -roff[0];3260roff[0] = 0;3261}3262else loff[c] = 0;3263for (y=0; y < rasterP->height; y++) {3264inP = lineInP;3265for (x=0; x < rasterP->width; x++) {3266*outP++ = (unsigned char)3267((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];3268inP++;3269}3270lineInP += rasterP->scanlineStride;3271}3272}32733274(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);32753276return 0;32773278}32793280/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3281static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,3282unsigned char *outDataP)3283{3284int x, y, c;3285unsigned char *outP = outDataP;3286unsigned int *lineInP, *inP;3287jarray jInDataP;3288jint *inDataP;3289int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];32903291if (rasterP->numBands > MAX_NUMBANDS) {3292return -1;3293}32943295/* Grab data ptr, strides, offsets from raster */3296jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3297inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3298if (inDataP == NULL) {3299return -1;3300}3301lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0];33023303if (component < 0) {3304for (c=0; c < rasterP->numBands; c++) {3305roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3306if (roff[c] < 0) {3307loff[c] = -roff[c];3308roff[c] = 0;3309}3310else loff[c] = 0;3311}3312/* Convert the all bands */3313if (rasterP->numBands < 4) {3314for (y=0; y < rasterP->height; y++) {3315inP = lineInP;3316for (x=0; x < rasterP->width; x++) {3317for (c=0; c < rasterP->numBands; c++) {3318/*3319* Not correct. Might need to unpremult,3320* shift, etc3321*/3322*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3323<<loff[c]);3324}3325inP++;3326}3327lineInP += rasterP->scanlineStride;3328}3329}3330else {3331for (y=0; y < rasterP->height; y++) {3332inP = lineInP;3333for (x=0; x < rasterP->width; x++) {3334for (c=0; c < rasterP->numBands; c++) {3335/*3336* Not correct. Might need to3337* unpremult, shift, etc3338*/3339*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3340<<loff[c]);3341}3342inP++;3343}3344lineInP += rasterP->scanlineStride;3345}3346}3347}3348else {3349c = component;3350roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3351if (roff[0] < 0) {3352loff[0] = -roff[0];3353roff[0] = 0;3354}3355else loff[c] = 0;3356for (y=0; y < rasterP->height; y++) {3357inP = lineInP;3358for (x=0; x < rasterP->width; x++) {3359*outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);3360inP++;3361}3362lineInP += rasterP->scanlineStride;3363}3364}33653366(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);33673368return 0;3369}33703371/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3372static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,3373int component, unsigned char *outDataP,3374int forceAlpha)3375{3376int x, y, c;3377unsigned char *outP = outDataP;3378unsigned int *lineInP, *inP;3379jarray jInDataP;3380jint *inDataP;3381int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3382int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);3383int a = numBands;33843385if (rasterP->numBands > MAX_NUMBANDS) {3386return -1;3387}33883389/* Grab data ptr, strides, offsets from raster */3390jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3391inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3392if (inDataP == NULL) {3393return -1;3394}3395lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0];33963397if (component < 0) {3398for (c=0; c < rasterP->numBands; c++) {3399roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3400if (roff[c] < 0) {3401loff[c] = -roff[c];3402roff[c] = 0;3403}3404else loff[c] = 0;3405}34063407/* Need to put in alpha */3408if (forceAlpha) {3409for (y=0; y < rasterP->height; y++) {3410inP = lineInP;3411for (x=0; x < rasterP->width; x++) {3412*outP++ = 0xff;3413for (c=0; c < numBands; c++) {3414/*3415* Not correct. Might need to unpremult,3416* shift, etc3417*/3418*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3419<<loff[c]);3420}3421inP++;3422}3423lineInP += rasterP->scanlineStride;3424}3425}3426else {3427for (y=0; y < rasterP->height; y++) {3428inP = lineInP;3429for (x=0; x < rasterP->width; x++) {3430*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])3431<<loff[a]);3432for (c=0; c < numBands; c++) {3433/*3434* Not correct. Might need to3435* unpremult, shift, etc3436*/3437*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3438<<loff[c]);3439}3440inP++;3441}3442lineInP += rasterP->scanlineStride;3443}3444}3445}3446else {3447c = component;3448roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3449if (roff[0] < 0) {3450loff[0] = -roff[0];3451roff[0] = 0;3452}3453else loff[c] = 0;3454for (y=0; y < rasterP->height; y++) {3455inP = lineInP;3456for (x=0; x < rasterP->width; x++) {3457*outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);3458inP++;3459}3460lineInP += rasterP->scanlineStride;3461}3462}34633464(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);34653466return 0;3467}34683469/* This routine is expecting a ByteComponentRaster with a PackedColorModel */3470static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,3471unsigned char *inDataP)3472{3473int x, y, c;3474unsigned char *inP = inDataP;3475unsigned char *lineOutP, *outP;3476jarray jOutDataP;3477jsize dataArrayLength;3478unsigned char *outDataP;3479int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];34803481if (rasterP->numBands > MAX_NUMBANDS) {3482return -1;3483}34843485/* Grab data ptr, strides, offsets from raster */3486jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);3487if (JNU_IsNull(env, jOutDataP)) {3488return -1;3489}34903491dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3492CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);34933494outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3495if (outDataP == NULL) {3496return -1;3497}3498lineOutP = outDataP + rasterP->chanOffsets[0];34993500if (component < 0) {3501for (c=0; c < rasterP->numBands; c++) {3502loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3503if (loff[c] < 0) {3504roff[c] = -loff[c];3505loff[c] = 0;3506}3507else roff[c] = 0;3508}3509/* Convert the all bands */3510for (y=0; y < rasterP->height; y++) {3511outP = lineOutP;3512*outP = 0;3513for (x=0; x < rasterP->width; x++) {3514for (c=0; c < rasterP->numBands; c++, inP++) {3515*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3516}3517outP++;3518}3519lineOutP += rasterP->scanlineStride;3520}3521}3522else {3523c = component;3524loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3525if (loff[0] < 0) {3526roff[0] = -loff[0];3527loff[0] = 0;3528}3529else roff[c] = 0;3530for (y=0; y < rasterP->height; y++) {3531outP = lineOutP;3532for (x=0; x < rasterP->width; x++, inP++) {3533*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3534outP++;3535}3536lineOutP += rasterP->scanlineStride;3537}3538}35393540(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);35413542return 0;3543}35443545/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3546static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,3547unsigned char *inDataP)3548{3549int x, y, c;3550unsigned char *inP = inDataP;3551unsigned short *lineOutP, *outP;3552jarray jOutDataP;3553jsize dataArrayLength;3554unsigned short *outDataP;3555int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];35563557if (rasterP->numBands > MAX_NUMBANDS) {3558return -1;3559}35603561/* Grab data ptr, strides, offsets from raster */3562jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3563if (JNU_IsNull(env, jOutDataP)) {3564return -1;3565}35663567dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3568CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);35693570outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3571if (outDataP == NULL) {3572return -1;3573}3574lineOutP = outDataP + rasterP->chanOffsets[0];35753576if (component < 0) {3577for (c=0; c < rasterP->numBands; c++) {3578loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3579if (loff[c] < 0) {3580roff[c] = -loff[c];3581loff[c] = 0;3582}3583else roff[c] = 0;3584}3585/* Convert the all bands */3586for (y=0; y < rasterP->height; y++) {3587outP = lineOutP;3588for (x=0; x < rasterP->width; x++) {3589for (c=0; c < rasterP->numBands; c++, inP++) {3590/* Not correct. Might need to unpremult, shift, etc */3591*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3592}3593outP++;3594}3595lineOutP += rasterP->scanlineStride;3596}3597}3598else {3599c = component;3600loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3601if (loff[0] < 0) {3602roff[0] = -loff[0];3603loff[0] = 0;3604}3605else roff[c] = 0;3606for (y=0; y < rasterP->height; y++) {3607outP = lineOutP;3608for (x=0; x < rasterP->width; x++, inP++) {3609*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3610outP++;3611}3612lineOutP += rasterP->scanlineStride;3613}3614}36153616(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);36173618return 0;3619}36203621/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3622static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,3623unsigned char *inDataP)3624{3625int x, y, c;3626unsigned char *inP = inDataP;3627unsigned int *lineOutP, *outP;3628jarray jOutDataP;3629jsize dataArrayLength;3630unsigned int *outDataP;3631int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];36323633if (rasterP->numBands > MAX_NUMBANDS) {3634return -1;3635}36363637/* Grab data ptr, strides, offsets from raster */3638jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3639if (JNU_IsNull(env, jOutDataP)) {3640return -1;3641}36423643dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3644CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);36453646outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3647if (outDataP == NULL) {3648return -1;3649}3650lineOutP = outDataP + rasterP->chanOffsets[0];36513652if (component < 0) {3653for (c=0; c < rasterP->numBands; c++) {3654loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3655if (loff[c] < 0) {3656roff[c] = -loff[c];3657loff[c] = 0;3658}3659else roff[c] = 0;3660}3661/* Convert the all bands */3662for (y=0; y < rasterP->height; y++) {3663outP = lineOutP;3664for (x=0; x < rasterP->width; x++) {3665for (c=0; c < rasterP->numBands; c++, inP++) {3666/* Not correct. Might need to unpremult, shift, etc */3667*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3668}3669outP++;3670}3671lineOutP += rasterP->scanlineStride;3672}3673}3674else {3675c = component;3676loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3677if (loff[0] < 0) {3678roff[0] = -loff[0];3679loff[0] = 0;3680}3681else roff[c] = 0;36823683for (y=0; y < rasterP->height; y++) {3684outP = lineOutP;3685for (x=0; x < rasterP->width; x++, inP++) {3686*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3687outP++;3688}3689lineOutP += rasterP->scanlineStride;3690}3691}36923693(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);36943695return 0;3696}36973698/* This routine is expecting a ByteComponentRaster with a PackedColorModel */3699static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,3700int component, unsigned char *inDataP,3701int supportsAlpha)3702{3703int x, y, c;3704unsigned char *inP = inDataP;3705unsigned char *lineOutP, *outP;3706jarray jOutDataP;3707jsize dataArrayLength;3708unsigned char *outDataP;3709int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3710int a = rasterP->numBands - 1;37113712if (rasterP->numBands > MAX_NUMBANDS) {3713return -1;3714}37153716/* Grab data ptr, strides, offsets from raster */3717jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);3718if (JNU_IsNull(env, jOutDataP)) {3719return -1;3720}37213722dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3723CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);37243725outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3726if (outDataP == NULL) {3727return -1;3728}3729lineOutP = outDataP + rasterP->chanOffsets[0];37303731if (component < 0) {3732for (c=0; c < rasterP->numBands; c++) {3733loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3734if (loff[c] < 0) {3735roff[c] = -loff[c];3736loff[c] = 0;3737}3738else roff[c] = 0;3739}3740/* Convert the all bands */3741if (supportsAlpha) {3742for (y=0; y < rasterP->height; y++) {3743outP = lineOutP;3744*outP = 0;3745for (x=0; x < rasterP->width; x++) {3746*outP |= (*inP<<loff[a]>>roff[a])&3747rasterP->sppsm.maskArray[a];3748inP++;3749for (c=0; c < rasterP->numBands-1; c++, inP++) {3750*outP |= (*inP<<loff[c]>>roff[c])&3751rasterP->sppsm.maskArray[c];3752}3753outP++;3754}3755lineOutP += rasterP->scanlineStride;3756}3757}3758else {3759for (y=0; y < rasterP->height; y++) {3760outP = lineOutP;3761*outP = 0;3762for (x=0; x < rasterP->width; x++) {3763inP++;3764for (c=0; c < rasterP->numBands; c++, inP++) {3765*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3766}3767outP++;3768}3769lineOutP += rasterP->scanlineStride;3770}3771}3772}3773else {3774c = component;3775loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3776if (loff[0] < 0) {3777roff[0] = -loff[0];3778loff[0] = 0;3779}3780else roff[c] = 0;3781for (y=0; y < rasterP->height; y++) {3782outP = lineOutP;3783for (x=0; x < rasterP->width; x++, inP++) {3784*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3785outP++;3786}3787lineOutP += rasterP->scanlineStride;3788}3789}37903791(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);37923793return 0;3794}37953796/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3797static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,3798int component, unsigned char *inDataP,3799int supportsAlpha)3800{3801int x, y, c;3802unsigned char *inP = inDataP;3803unsigned short *lineOutP, *outP;3804jarray jOutDataP;3805jsize dataArrayLength;3806unsigned short *outDataP;3807int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3808int a = rasterP->numBands - 1;38093810if (rasterP->numBands > MAX_NUMBANDS) {3811return -1;3812}38133814/* Grab data ptr, strides, offsets from raster */3815jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3816if (JNU_IsNull(env, jOutDataP)) {3817return -1;3818}3819dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3820CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);38213822outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3823if (outDataP == NULL) {3824return -1;3825}3826lineOutP = outDataP + rasterP->chanOffsets[0];38273828if (component < 0) {3829for (c=0; c < rasterP->numBands; c++) {3830loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3831if (loff[c] < 0) {3832roff[c] = -loff[c];3833loff[c] = 0;3834}3835else roff[c] = 0;3836}3837/* Convert the all bands */3838if (supportsAlpha) {3839for (y=0; y < rasterP->height; y++) {3840outP = lineOutP;3841for (x=0; x < rasterP->width; x++) {3842*outP |= (*inP<<loff[a]>>roff[a])&3843rasterP->sppsm.maskArray[a];3844inP++;3845for (c=0; c < rasterP->numBands-1; c++, inP++) {3846/* Not correct. Might need to unpremult, shift, etc */3847*outP |= (*inP<<loff[c]>>roff[c])&3848rasterP->sppsm.maskArray[c];3849}3850outP++;3851}3852lineOutP += rasterP->scanlineStride;3853}3854}3855else {3856for (y=0; y < rasterP->height; y++) {3857outP = lineOutP;3858for (x=0; x < rasterP->width; x++) {3859inP++;3860for (c=0; c < rasterP->numBands; c++, inP++) {3861/* Not correct. Might need to unpremult, shift, etc */3862*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3863}3864outP++;3865}3866lineOutP += rasterP->scanlineStride;3867}3868}3869}3870else {3871c = component;3872loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3873if (loff[0] < 0) {3874roff[0] = -loff[0];3875loff[0] = 0;3876}3877else roff[c] = 0;3878for (y=0; y < rasterP->height; y++) {3879outP = lineOutP;3880for (x=0; x < rasterP->width; x++, inP++) {3881*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3882outP++;3883}3884lineOutP += rasterP->scanlineStride;3885}3886}38873888(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);38893890return 0;3891}38923893/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3894static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,3895int component, unsigned char *inDataP,3896int supportsAlpha)3897{3898int x, y, c;3899unsigned char *inP = inDataP;3900unsigned int *lineOutP, *outP;3901jarray jOutDataP;3902jsize dataArrayLength;3903unsigned int *outDataP;3904int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3905int a = rasterP->numBands - 1;39063907if (rasterP->numBands > MAX_NUMBANDS) {3908return -1;3909}39103911/* Grab data ptr, strides, offsets from raster */3912jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3913if (JNU_IsNull(env, jOutDataP)) {3914return -1;3915}39163917dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3918CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);39193920outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3921if (outDataP == NULL) {3922return -1;3923}3924lineOutP = outDataP + rasterP->chanOffsets[0];39253926if (component < 0) {3927for (c=0; c < rasterP->numBands; c++) {3928loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3929if (loff[c] < 0) {3930roff[c] = -loff[c];3931loff[c] = 0;3932}3933else roff[c] = 0;3934}3935/* Convert the all bands */3936if (supportsAlpha) {3937for (y=0; y < rasterP->height; y++) {3938outP = lineOutP;3939for (x=0; x < rasterP->width; x++) {3940*outP |= (*inP<<loff[a]>>roff[a])&3941rasterP->sppsm.maskArray[a];3942inP++;3943for (c=0; c < rasterP->numBands-1; c++, inP++) {3944/* Not correct. Might need to unpremult, shift, etc */3945*outP |= (*inP<<loff[c]>>roff[c])&3946rasterP->sppsm.maskArray[c];3947}3948outP++;3949}3950lineOutP += rasterP->scanlineStride;3951}3952}3953else {3954for (y=0; y < rasterP->height; y++) {3955outP = lineOutP;3956for (x=0; x < rasterP->width; x++) {3957inP++;3958for (c=0; c < rasterP->numBands; c++, inP++) {3959/* Not correct. Might need to unpremult, shift, etc */3960*outP |= (*inP<<loff[c]>>roff[c])&3961rasterP->sppsm.maskArray[c];3962}3963outP++;3964}3965lineOutP += rasterP->scanlineStride;3966}3967}3968}3969else {3970c = component;3971loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3972if (loff[0] < 0) {3973roff[0] = -loff[0];3974loff[0] = 0;3975}3976else roff[c] = 0;39773978for (y=0; y < rasterP->height; y++) {3979outP = lineOutP;3980for (x=0; x < rasterP->width; x++, inP++) {3981*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3982outP++;3983}3984lineOutP += rasterP->scanlineStride;3985}3986}39873988(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);39893990return 0;3991}39923993/* This is temporary code. Should go away when there is better color3994* conversion code available.3995* REMIND: Ignoring alpha3996*/3997/* returns the absolute value x */3998#define ABS(x) ((x) < 0 ? -(x) : (x))3999#define CLIP(val,min,max) ((val < min) ? min : ((val > max) ? max : val))40004001static int4002colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors) {4003int besti = 0;4004int mindist, i, t, d;4005unsigned char red, green, blue;40064007r = CLIP(r, 0, 255);4008g = CLIP(g, 0, 255);4009b = CLIP(b, 0, 255);40104011/* look for pure gray match */4012if ((r == g) && (g == b)) {4013mindist = 256;4014for (i = 0 ; i < numColors ; i++, argb+=4) {4015red = argb[1];4016green = argb[2];4017blue = argb[3];4018if (! ((red == green) && (green == blue)) ) {4019continue;4020}4021d = ABS(red - r);4022if (d == 0)4023return i;4024if (d < mindist) {4025besti = i;4026mindist = d;4027}4028}4029return besti;4030}40314032/* look for non-pure gray match */4033mindist = 256 * 256 * 256;4034for (i = 0 ; i < numColors ; i++, argb+=4) {4035red = argb[1];4036green = argb[2];4037blue = argb[3];4038t = red - r;4039d = t * t;4040if (d >= mindist) {4041continue;4042}4043t = green - g;4044d += t * t;4045if (d >= mindist) {4046continue;4047}4048t = blue - b;4049d += t * t;4050if (d >= mindist) {4051continue;4052}4053if (d == 0)4054return i;4055if (d < mindist) {4056besti = i;4057mindist = d;4058}4059}40604061return besti;4062}406340644065