Path: blob/master/src/java.desktop/share/native/libawt/awt/medialib/awt_ImagingLib.c
41159 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);10641065return 0;1066}1067}10681069if (s_printIt) {1070printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],1071matrix[2], matrix[3], matrix[4], matrix[5]);1072}10731074mtx[0] = matrix[0];1075mtx[1] = matrix[2];1076mtx[2] = matrix[4];1077mtx[3] = matrix[1];1078mtx[4] = matrix[3];1079mtx[5] = matrix[5];10801081(*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);10821083/* Parse the source raster */1084if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {1085/* Can't handle any custom rasters */1086free(srcRasterP);1087free(dstRasterP);1088return 0;1089}10901091/* Parse the destination raster */1092if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {1093/* Can't handle any custom images */1094awt_freeParsedRaster(srcRasterP, TRUE);1095free(dstRasterP);1096return 0;1097}10981099/* Allocate the arrays */1100if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {1101/* Must be some problem */1102awt_freeParsedRaster(srcRasterP, TRUE);1103awt_freeParsedRaster(dstRasterP, TRUE);1104return 0;1105}1106if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {1107/* Must be some problem */1108freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);1109awt_freeParsedRaster(srcRasterP, TRUE);1110awt_freeParsedRaster(dstRasterP, TRUE);1111return 0;1112}11131114#if 01115fprintf(stderr,"Src----------------\n");1116fprintf(stderr,"Type : %d\n",src->type);1117fprintf(stderr,"Channels: %d\n",src->channels);1118fprintf(stderr,"Width : %d\n",src->width);1119fprintf(stderr,"Height : %d\n",src->height);1120fprintf(stderr,"Stride : %d\n",src->stride);1121fprintf(stderr,"Flags : %d\n",src->flags);11221123fprintf(stderr,"Dst----------------\n");1124fprintf(stderr,"Type : %d\n",dst->type);1125fprintf(stderr,"Channels: %d\n",dst->channels);1126fprintf(stderr,"Width : %d\n",dst->width);1127fprintf(stderr,"Height : %d\n",dst->height);1128fprintf(stderr,"Stride : %d\n",dst->stride);1129fprintf(stderr,"Flags : %d\n",dst->flags);1130#endif11311132{1133unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);11341135memset(cP, 0, mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));1136}11371138/* Perform the transformation */1139if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,1140MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))1141{1142printMedialibError(status);1143/* REMIND: Free the regions */1144return 0;1145}11461147if (s_printIt) {1148if (sdata == NULL) {1149dP = (unsigned int *) mlib_ImageGetData(src);1150}1151else {1152dP = (unsigned int *) sdata;1153}1154printf("src is\n");1155for (i=0; i < 20; i++) {1156printf("%x ",dP[i]);1157}1158printf("\n");1159if (ddata == NULL) {1160dP = (unsigned int *)mlib_ImageGetData(dst);1161}1162else {1163dP = (unsigned int *) ddata;1164}1165printf("dst is\n");1166for (i=0; i < 20; i++) {1167printf("%x ",dP[i]);1168}1169printf("\n");1170}11711172/* Means that we couldn't write directly into the destination buffer */1173if (ddata == NULL) {1174/* Need to store it back into the array */1175if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {1176(*env)->ExceptionClear(env); // Could not store the array, try another way1177retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);1178}1179}11801181/* Release the pinned memory */1182freeDataArray(env, srcRasterP->jdata, src, sdata,1183dstRasterP->jdata, dst, ddata);11841185awt_freeParsedRaster(srcRasterP, TRUE);1186awt_freeParsedRaster(dstRasterP, TRUE);11871188if (s_timeIt) (*stop_timer)(3600,1);11891190return retStatus;1191}11921193typedef struct {1194jobject jArray;1195jsize length;1196unsigned char *table;1197} LookupArrayInfo;11981199#define NLUT 812001201#ifdef _LITTLE_ENDIAN1202#define INDEXES { 3, 2, 1, 0, 7, 6, 5, 4 }1203#else1204#define INDEXES { 0, 1, 2, 3, 4, 5, 6, 7 }1205#endif12061207static int lookupShortData(mlib_image* src, mlib_image* dst,1208LookupArrayInfo* lookup)1209{1210int x, y;1211unsigned int mask = NLUT-1;12121213unsigned short* srcLine = (unsigned short*)src->data;1214unsigned char* dstLine = (unsigned char*)dst->data;12151216static int indexes[NLUT] = INDEXES;12171218if (src->width != dst->width || src->height != dst->height) {1219return 0;1220}12211222for (y=0; y < src->height; y++) {1223int nloop, nx;1224int npix = src->width;12251226unsigned short* srcPixel = srcLine;1227unsigned char* dstPixel = dstLine;12281229#ifdef SIMPLE_LOOKUP_LOOP1230for (x=0; status && x < width; x++) {1231unsigned short s = *srcPixel++;1232if (s >= lookup->length) {1233/* we can not handle source image using1234* byte lookup table. Fall back to processing1235* images in java1236*/1237return 0;1238}1239*dstPixel++ = lookup->table[s];1240}1241#else1242/* Get to 32 bit-aligned point */1243while(((uintptr_t)dstPixel & 0x3) != 0 && npix>0) {1244unsigned short s = *srcPixel++;1245if (s >= lookup->length) {1246return 0;1247}1248*dstPixel++ = lookup->table[s];1249npix--;1250}12511252/*1253* Do NLUT pixels per loop iteration.1254* Pack into ints and write out 2 at a time.1255*/1256nloop = npix/NLUT;1257nx = npix%NLUT;12581259for(x=nloop; x!=0; x--) {1260int i = 0;1261int* dstP = (int*)dstPixel;12621263for (i = 0; i < NLUT; i++) {1264if (srcPixel[i] >= lookup->length) {1265return 0;1266}1267}12681269dstP[0] = (int)1270((lookup->table[srcPixel[indexes[0]]] << 24) |1271(lookup->table[srcPixel[indexes[1]]] << 16) |1272(lookup->table[srcPixel[indexes[2]]] << 8) |1273lookup->table[srcPixel[indexes[3]]]);1274dstP[1] = (int)1275((lookup->table[srcPixel[indexes[4]]] << 24) |1276(lookup->table[srcPixel[indexes[5]]] << 16) |1277(lookup->table[srcPixel[indexes[6]]] << 8) |1278lookup->table[srcPixel[indexes[7]]]);127912801281dstPixel += NLUT;1282srcPixel += NLUT;1283}12841285/*1286* Complete any remaining pixels1287*/1288for(x=nx; x!=0; x--) {1289unsigned short s = *srcPixel++;1290if (s >= lookup->length) {1291return 0;1292}1293*dstPixel++ = lookup->table[s];1294}1295#endif12961297dstLine += dst->stride; // array of bytes, scan stride in bytes1298srcLine += src->stride / 2; // array of shorts, scan stride in bytes1299}1300return 1;1301}13021303JNIEXPORT jint JNICALL1304Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject thisLib,1305jobject jsrc, jobject jdst,1306jobjectArray jtableArrays)1307{1308mlib_image *src;1309mlib_image *dst;1310void *sdata, *ddata;1311unsigned char **tbl;1312unsigned char lut[256];1313int retStatus = 1;1314int i;1315mlib_status status;1316int lut_nbands;1317LookupArrayInfo *jtable;1318BufImageS_t *srcImageP, *dstImageP;1319int nbands;1320int ncomponents;1321mlibHintS_t hint;13221323/* This function requires a lot of local refs ??? Is 64 enough ??? */1324if ((*env)->EnsureLocalCapacity(env, 64) < 0)1325return 0;13261327if (s_nomlib) return 0;1328if (s_timeIt) (*start_timer)(3600);13291330/* Parse the source image */1331if (awt_parseImage(env, jsrc, &srcImageP, FALSE) <= 0) {1332/* Can't handle any custom images */1333return 0;1334}13351336/* Parse the destination image */1337if (awt_parseImage(env, jdst, &dstImageP, FALSE) <= 0) {1338/* Can't handle any custom images */1339awt_freeParsedImage(srcImageP, TRUE);1340return 0;1341}13421343nbands = setImageHints(env, srcImageP, dstImageP, FALSE, TRUE,1344FALSE, &hint);13451346if (nbands < 1 || nbands > srcImageP->cmodel.numComponents) {1347/* Can't handle any custom images */1348awt_freeParsedImage(srcImageP, TRUE);1349awt_freeParsedImage(dstImageP, TRUE);1350return 0;1351}13521353ncomponents = srcImageP->cmodel.isDefaultCompatCM1354? 41355: srcImageP->cmodel.numComponents;13561357/* Make sure that color order can be used for1358* re-ordering of lookup arrays.1359*/1360for (i = 0; i < nbands; i++) {1361int idx = srcImageP->hints.colorOrder[i];13621363if (idx < 0 || idx >= ncomponents) {1364awt_freeParsedImage(srcImageP, TRUE);1365awt_freeParsedImage(dstImageP, TRUE);1366return 0;1367}1368}13691370lut_nbands = (*env)->GetArrayLength(env, jtableArrays);13711372if (lut_nbands > ncomponents) {1373lut_nbands = ncomponents;1374}13751376tbl = NULL;1377if (SAFE_TO_ALLOC_2(ncomponents, sizeof(unsigned char *))) {1378tbl = (unsigned char **)1379calloc(1, ncomponents * sizeof(unsigned char *));1380}13811382jtable = NULL;1383if (SAFE_TO_ALLOC_2(lut_nbands, sizeof(LookupArrayInfo))) {1384jtable = (LookupArrayInfo *)malloc(lut_nbands * sizeof (LookupArrayInfo));1385}13861387if (tbl == NULL || jtable == NULL) {1388if (tbl != NULL) free(tbl);1389if (jtable != NULL) free(jtable);1390awt_freeParsedImage(srcImageP, TRUE);1391awt_freeParsedImage(dstImageP, TRUE);1392JNU_ThrowNullPointerException(env, "NULL LUT");1393return 0;1394}1395/* Need to grab these pointers before we lock down arrays */1396for (i=0; i < lut_nbands; i++) {1397jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);13981399if (jtable[i].jArray != NULL) {1400jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);1401jtable[i].table = NULL;14021403if (jtable[i].length < 256) {1404/* we may read outside the table during lookup */1405jtable[i].jArray = NULL;1406jtable[i].length = 0;1407}1408}1409if (jtable[i].jArray == NULL) {1410free(tbl);1411free(jtable);1412awt_freeParsedImage(srcImageP, TRUE);1413awt_freeParsedImage(dstImageP, TRUE);1414return 0;1415}1416}14171418/* Allocate the arrays */1419if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) {1420/* Must be some problem */1421free(tbl);1422free(jtable);1423awt_freeParsedImage(srcImageP, TRUE);1424awt_freeParsedImage(dstImageP, TRUE);1425return 0;1426}1427if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) {1428/* Must be some problem */1429free(tbl);1430free(jtable);1431freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);1432awt_freeParsedImage(srcImageP, TRUE);1433awt_freeParsedImage(dstImageP, TRUE);1434return 0;1435}14361437/* Set up a straight lut so we don't mess around with alpha */1438/*1439* NB: medialib lookup routine expects lookup array for each1440* component of source image including alpha.1441* If lookup table we got form the java layer does not contain1442* sufficient number of lookup arrays we add references to identity1443* lookup array to make medialib happier.1444*/1445if (lut_nbands < ncomponents) {1446int j;1447/* REMIND: This should be the size of the input lut!! */1448for (j=0; j < 256; j++) {1449lut[j] = j;1450}1451for (j=0; j < ncomponents; j++) {1452tbl[j] = lut;1453}1454}14551456for (i=0; i < lut_nbands; i++) {1457jtable[i].table = (unsigned char *)1458(*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);1459if (jtable[i].table == NULL) {1460/* Free what we've got so far. */1461int j;1462for (j = 0; j < i; j++) {1463(*env)->ReleasePrimitiveArrayCritical(env,1464jtable[j].jArray,1465(jbyte *) jtable[j].table,1466JNI_ABORT);1467}1468free(tbl);1469free(jtable);1470freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);1471awt_freeParsedImage(srcImageP, TRUE);1472awt_freeParsedImage(dstImageP, TRUE);1473return 0;1474}1475tbl[srcImageP->hints.colorOrder[i]] = jtable[i].table;1476}14771478if (lut_nbands == 1) {1479for (i=1; i < nbands -1480srcImageP->cmodel.supportsAlpha; i++) {1481tbl[srcImageP->hints.colorOrder[i]] = jtable[0].table;1482}1483}14841485/* Mlib needs 16bit lookuptable and must be signed! */1486if (src->type == MLIB_SHORT) {1487if (dst->type == MLIB_BYTE) {1488if (nbands > 1) {1489retStatus = 0;1490}1491else {1492retStatus = lookupShortData(src, dst, &jtable[0]);1493}1494}1495/* How about ddata == null? */1496}1497else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,1498(void **)tbl) != MLIB_SUCCESS)) {1499printMedialibError(status);1500retStatus = 0;1501}15021503/* Release the LUT */1504for (i=0; i < lut_nbands; i++) {1505(*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,1506(jbyte *) jtable[i].table, JNI_ABORT);1507}1508free ((void *) jtable);1509free ((void *) tbl);15101511/*1512* Means that we couldn't write directly into1513* the destination buffer1514*/1515if (ddata == NULL) {15161517/* Need to store it back into the array */1518if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {1519/* Error */1520retStatus = 0;1521}1522}152315241525/* Release the pinned memory */1526freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);15271528awt_freeParsedImage(srcImageP, TRUE);1529awt_freeParsedImage(dstImageP, TRUE);15301531if (s_timeIt) (*stop_timer)(3600, 1);15321533return retStatus;1534}15351536JNIEXPORT jint JNICALL1537Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env,1538jobject this,1539jobject jsrc,1540jobject jdst,1541jobjectArray jtableArrays)1542{1543RasterS_t* srcRasterP;1544RasterS_t* dstRasterP;1545mlib_image* src;1546mlib_image* dst;1547void* sdata;1548void* ddata;1549LookupArrayInfo jtable[4];1550unsigned char* mlib_lookupTable[4];1551int i;1552int retStatus = 1;1553mlib_status status;1554int jlen;1555int lut_nbands;1556int src_nbands;1557int dst_nbands;1558unsigned char ilut[256];15591560/* This function requires a lot of local refs ??? Is 64 enough ??? */1561if ((*env)->EnsureLocalCapacity(env, 64) < 0)1562return 0;15631564if (s_nomlib) return 0;1565if (s_timeIt) (*start_timer)(3600);15661567if ((srcRasterP = (RasterS_t*) calloc(1, sizeof(RasterS_t))) == NULL) {1568JNU_ThrowOutOfMemoryError(env, "Out of memory");1569return -1;1570}15711572if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {1573JNU_ThrowOutOfMemoryError(env, "Out of memory");1574free(srcRasterP);1575return -1;1576}15771578/* Parse the source raster - reject custom images */1579if (awt_parseRaster(env, jsrc, srcRasterP) <= 0) {1580free(srcRasterP);1581free(dstRasterP);1582return 0;1583}15841585/* Parse the destination image - reject custom images */1586if (awt_parseRaster(env, jdst, dstRasterP) <= 0) {1587awt_freeParsedRaster(srcRasterP, TRUE);1588free(dstRasterP);1589return 0;1590}15911592jlen = (*env)->GetArrayLength(env, jtableArrays);15931594lut_nbands = jlen;1595src_nbands = srcRasterP->numBands;1596dst_nbands = dstRasterP->numBands;15971598/* adjust number of lookup bands */1599if (lut_nbands > src_nbands) {1600lut_nbands = src_nbands;1601}16021603/* MediaLib can't do more than 4 bands */1604if (src_nbands <= 0 || src_nbands > 4 ||1605dst_nbands <= 0 || dst_nbands > 4 ||1606lut_nbands <= 0 || lut_nbands > 4 ||1607src_nbands != dst_nbands ||1608((lut_nbands != 1) && (lut_nbands != src_nbands)))1609{1610// we should free parsed rasters here1611awt_freeParsedRaster(srcRasterP, TRUE);1612awt_freeParsedRaster(dstRasterP, TRUE);1613return 0;1614}16151616/* Allocate the raster arrays */1617if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {1618/* Must be some problem */1619awt_freeParsedRaster(srcRasterP, TRUE);1620awt_freeParsedRaster(dstRasterP, TRUE);1621return 0;1622}1623if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {1624/* Must be some problem */1625freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);1626awt_freeParsedRaster(srcRasterP, TRUE);1627awt_freeParsedRaster(dstRasterP, TRUE);1628return 0;1629}16301631/*1632* Well, until now we have analyzed number of bands in1633* src and dst rasters.1634* However, it is not enough because medialib lookup routine uses1635* number of channels of medialib image. Note that in certain1636* case number of channels may differs form the number of bands.1637* Good example is raster that is used in TYPE_INT_RGB buffered1638* image: it has 3 bands, but their medialib representation has1639* 4 channels.1640*1641* In order to avoid the lookup routine failure, we need:1642*1643* 1. verify that src and dst have same number of channels.1644* 2. provide lookup array for every channel. If we have "extra"1645* channel (like the raster described above) then we need to1646* provide identical lookup array.1647*/1648if (src->channels != dst->channels) {1649freeDataArray(env, srcRasterP->jdata, src, sdata,1650dstRasterP->jdata, dst, ddata);16511652awt_freeParsedRaster(srcRasterP, TRUE);1653awt_freeParsedRaster(dstRasterP, TRUE);1654return 0;1655}16561657if (src_nbands < src->channels) {1658for (i = 0; i < 256; i++) {1659ilut[i] = i;1660}1661}166216631664/* Get references to the lookup table arrays */1665/* Need to grab these pointers before we lock down arrays */1666for (i=0; i < lut_nbands; i++) {1667jtable[i].jArray = (*env)->GetObjectArrayElement(env, jtableArrays, i);1668jtable[i].table = NULL;1669if (jtable[i].jArray != NULL) {1670jtable[i].length = (*env)->GetArrayLength(env, jtable[i].jArray);1671if (jtable[i].length < 256) {1672/* we may read outside the table during lookup */1673jtable[i].jArray = NULL;1674}1675}16761677if (jtable[i].jArray == NULL)1678{1679freeDataArray(env, srcRasterP->jdata, src, sdata,1680dstRasterP->jdata, dst, ddata);16811682awt_freeParsedRaster(srcRasterP, TRUE);1683awt_freeParsedRaster(dstRasterP, TRUE);1684return 0;1685}1686}16871688for (i=0; i < lut_nbands; i++) {1689jtable[i].table = (unsigned char *)1690(*env)->GetPrimitiveArrayCritical(env, jtable[i].jArray, NULL);1691if (jtable[i].table == NULL) {1692/* Free what we've got so far. */1693int j;1694for (j = 0; j < i; j++) {1695(*env)->ReleasePrimitiveArrayCritical(env,1696jtable[j].jArray,1697(jbyte *) jtable[j].table,1698JNI_ABORT);1699}1700freeDataArray(env, srcRasterP->jdata, src, sdata,1701dstRasterP->jdata, dst, ddata);1702awt_freeParsedRaster(srcRasterP, TRUE);1703awt_freeParsedRaster(dstRasterP, TRUE);1704return 0;1705}1706mlib_lookupTable[i] = jtable[i].table;1707}17081709/*1710* Medialib routine expects lookup array for each band of raster.1711* Setup the rest of lookup arrays if supplied lookup table1712* contains single lookup array.1713*/1714for (i = lut_nbands; i < src_nbands; i++) {1715mlib_lookupTable[i] = jtable[0].table;1716}17171718/*1719* Setup lookup array for "extra" channels1720*/1721for ( ; i < src->channels; i++) {1722mlib_lookupTable[i] = ilut;1723}17241725/* Mlib needs 16bit lookuptable and must be signed! */1726if (src->type == MLIB_SHORT) {1727if (dst->type == MLIB_BYTE) {1728if (lut_nbands > 1) {1729retStatus = 0;1730} else {1731retStatus = lookupShortData(src, dst, &jtable[0]);1732}1733}1734/* How about ddata == null? */1735} else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,1736(void **)mlib_lookupTable) != MLIB_SUCCESS)) {1737printMedialibError(status);1738retStatus = 0;1739}17401741/* Release the LUT */1742for (i=0; i < lut_nbands; i++) {1743(*env)->ReleasePrimitiveArrayCritical(env, jtable[i].jArray,1744(jbyte *) jtable[i].table, JNI_ABORT);1745}17461747/*1748* Means that we couldn't write directly into1749* the destination buffer1750*/1751if (ddata == NULL) {1752if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {1753retStatus = setPixelsFormMlibImage(env, dstRasterP, dst);1754}1755}17561757/* Release the pinned memory */1758freeDataArray(env, srcRasterP->jdata, src, sdata,1759dstRasterP->jdata, dst, ddata);17601761awt_freeParsedRaster(srcRasterP, TRUE);1762awt_freeParsedRaster(dstRasterP, TRUE);17631764if (s_timeIt) (*stop_timer)(3600, 1);17651766return retStatus;1767}176817691770JNIEXPORT jboolean JNICALL1771Java_sun_awt_image_ImagingLib_init(JNIEnv *env, jclass thisClass) {1772char *start;1773if (getenv("IMLIB_DEBUG")) {1774start_timer = awt_setMlibStartTimer();1775stop_timer = awt_setMlibStopTimer();1776if (start_timer && stop_timer) {1777s_timeIt = 1;1778}1779}17801781if (getenv("IMLIB_PRINT")) {1782s_printIt = 1;1783}1784if ((start = getenv("IMLIB_START")) != NULL) {1785sscanf(start, "%d", &s_startOff);1786}17871788if (getenv ("IMLIB_NOMLIB")) {1789s_nomlib = 1;1790return JNI_FALSE;1791}17921793/* This function is platform-dependent and is in awt_mlib.c */1794if (awt_getImagingLib(env, (mlibFnS_t *)&sMlibFns, &sMlibSysFns) !=1795MLIB_SUCCESS)1796{1797s_nomlib = 1;1798return JNI_FALSE;1799}1800return JNI_TRUE;1801}18021803/* REMIND: How to specify border? */1804static void extendEdge(JNIEnv *env, BufImageS_t *imageP,1805int *widthP, int *heightP) {1806RasterS_t *rasterP = &imageP->raster;1807int width;1808int height;1809/* Useful for convolution? */18101811jobject jbaseraster = (*env)->GetObjectField(env, rasterP->jraster,1812g_RasterBaseRasterID);1813width = rasterP->width;1814height = rasterP->height;1815#ifdef WORKING1816if (! JNU_IsNull(env, jbaseraster) &&1817!(*env)->IsSameObject(env, rasterP->jraster, jbaseraster)) {1818int xOff;1819int yOff;1820int baseWidth;1821int baseHeight;1822int baseXoff;1823int baseYoff;1824/* Not the same object so get the width and height */1825xOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterXOffsetID);1826yOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterYOffsetID);1827baseWidth = (*env)->GetIntField(env, jbaseraster, g_RasterWidthID);1828baseHeight = (*env)->GetIntField(env, jbaseraster, g_RasterHeightID);1829baseXoff = (*env)->GetIntField(env, jbaseraster, g_RasterXOffsetID);1830baseYoff = (*env)->GetIntField(env, jbaseraster, g_RasterYOffsetID);18311832if (xOff + rasterP->width < baseXoff + baseWidth) {1833/* Can use edge */1834width++;1835}1836if (yOff + rasterP->height < baseYoff + baseHeight) {1837/* Can use edge */1838height++;1839}18401841}1842#endif18431844}18451846static int1847setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,1848int expandICM, int useAlpha,1849int premultiply, mlibHintS_t *hintP)1850{1851ColorModelS_t *srcCMP = &srcP->cmodel;1852ColorModelS_t *dstCMP = &dstP->cmodel;1853int nbands = 0;1854int ncomponents;18551856hintP->dataType = srcP->raster.dataType;1857hintP->addAlpha = FALSE;18581859/* Are the color spaces the same? */1860if (srcCMP->csType != dstCMP->csType) {1861/* If the src is GRAY and dst RGB, we can handle it */1862if (!(srcCMP->csType == java_awt_color_ColorSpace_TYPE_GRAY &&1863dstCMP->csType == java_awt_color_ColorSpace_TYPE_RGB)) {1864/* Nope, need to handle that in java for now */1865return -1;1866}1867else {1868hintP->cvtSrcToDefault = TRUE;1869}1870}1871else {1872if (srcP->hints.needToExpand) {1873hintP->cvtSrcToDefault = TRUE;1874}1875else {1876/* Need to initialize this */1877hintP->cvtSrcToDefault = FALSE;1878}1879}18801881ncomponents = srcCMP->numComponents;1882if ((useAlpha == 0) && srcCMP->supportsAlpha) {1883ncomponents--; /* ?? */1884/* Not really, more like shrink src to get rid of alpha */1885hintP->cvtSrcToDefault = TRUE;1886}18871888hintP->dataType = srcP->raster.dataType;1889if (hintP->cvtSrcToDefault == FALSE) {1890if (srcCMP->cmType == INDEX_CM_TYPE) {1891if (expandICM) {1892nbands = srcCMP->numComponents;1893hintP->cvtSrcToDefault = TRUE;18941895if (dstCMP->isDefaultCompatCM) {1896hintP->allocDefaultDst = FALSE;1897hintP->cvtToDst = FALSE;1898}1899else if (dstCMP->isDefaultCompatCM) {1900hintP->allocDefaultDst = FALSE;1901hintP->cvtToDst = FALSE;1902}1903}1904else {1905nbands = 1;1906hintP->cvtSrcToDefault = FALSE;1907}19081909}1910else {1911if (srcP->hints.packing & INTERLEAVED) {1912nbands = srcCMP->numComponents;1913}1914else {1915nbands = 1;1916}19171918/* Look at the packing */1919if ((srcP->hints.packing&BYTE_INTERLEAVED)==BYTE_INTERLEAVED ||1920(srcP->hints.packing&SHORT_INTERLEAVED)==SHORT_INTERLEAVED||1921(srcP->hints.packing&BYTE_SINGLE_BAND) == BYTE_SINGLE_BAND||1922(srcP->hints.packing&SHORT_SINGLE_BAND)==SHORT_SINGLE_BAND||1923(srcP->hints.packing&BYTE_BANDED) == BYTE_BANDED ||1924(srcP->hints.packing&SHORT_BANDED) == SHORT_BANDED) {1925/* Can use src directly */1926hintP->cvtSrcToDefault = FALSE;1927}1928else {1929/* Must be packed or custom */1930hintP->cvtSrcToDefault = TRUE;1931}1932}1933}1934if (hintP->cvtSrcToDefault) {1935/* By definition */1936nbands = 4; /* What about alpha? */1937hintP->dataType = BYTE_DATA_TYPE;1938hintP->needToCopy = TRUE;19391940if (srcP->imageType == dstP->imageType) {1941hintP->cvtToDst = TRUE;1942}1943else if (dstP->cmodel.isDefaultCM) {1944/* Not necessarily */1945hintP->cvtToDst = FALSE;1946}1947else {1948hintP->cvtToDst = TRUE;1949}1950}1951else {1952int srcImageType = srcP->imageType;1953int dstImageType = dstP->imageType;1954/* Special case where we need to fill in alpha values */1955if (srcCMP->isDefaultCompatCM && dstCMP->isDefaultCompatCM) {1956int i;1957if (!srcCMP->supportsAlpha &&dstCMP->supportsAlpha) {1958hintP->addAlpha = TRUE;1959}1960for (i=0; i < srcCMP->numComponents; i++) {1961if (srcP->hints.colorOrder[i] != dstP->hints.colorOrder[i]){1962if (!srcCMP->isDefaultCM) {1963hintP->cvtSrcToDefault = TRUE;1964srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;1965}1966if (!dstCMP->isDefaultCM) {1967hintP->cvtToDst = TRUE;1968dstImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;1969}19701971break;1972}1973}1974}1975else if (srcCMP->cmType != INDEX_CM_TYPE &&1976!srcCMP->supportsAlpha && dstCMP->supportsAlpha)1977{1978/* We've already handled the index case. This is for the rest of the cases */1979srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;1980hintP->cvtSrcToDefault = TRUE;1981}19821983hintP->allocDefaultDst = FALSE;1984if (srcImageType == dstImageType) {1985/* Same image type so use it */1986hintP->cvtToDst = FALSE;1987}1988else if (srcImageType == TYPE_INT_RGB &&1989(dstImageType == TYPE_INT_ARGB ||1990dstImageType == TYPE_INT_ARGB_PRE)) {1991hintP->cvtToDst = FALSE;1992}1993else if (srcImageType == TYPE_INT_BGR &&1994(dstImageType == TYPE_4BYTE_ABGR ||1995dstImageType == TYPE_4BYTE_ABGR_PRE)) {1996hintP->cvtToDst = FALSE;1997}1998else if (srcP->hints.packing == dstP->hints.packing) {1999/* Now what? */20002001/* Check color order */20022003/* Check if just need to scale the data */20042005hintP->cvtToDst = TRUE;2006}2007else {2008/* Don't know what it is so convert it */2009hintP->allocDefaultDst = TRUE;2010hintP->cvtToDst = TRUE;2011}2012hintP->needToCopy = (ncomponents > nbands);2013}20142015return nbands;2016}201720182019static int2020expandPacked(JNIEnv *env, BufImageS_t *img, ColorModelS_t *cmP,2021RasterS_t *rasterP, int component, unsigned char *bdataP) {20222023if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {2024switch (rasterP->dataType) {2025case BYTE_DATA_TYPE:2026if (expandPackedBCR(env, rasterP, component, bdataP) < 0) {2027/* Must have been an error */2028return -1;2029}2030break;20312032case SHORT_DATA_TYPE:2033if (expandPackedICR(env, rasterP, component, bdataP) < 0) {2034/* Must have been an error */2035return -1;2036}2037break;20382039case INT_DATA_TYPE:2040if (expandPackedICR(env, rasterP, component, bdataP) < 0) {2041/* Must have been an error */2042return -1;2043}2044break;20452046default:2047/* REMIND: Return some sort of error */2048return -1;2049}2050}2051else {2052/* REMIND: Return some sort of error */2053return -1;2054}20552056return 0;2057}20582059#define NUM_LINES 1020602061static int2062cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,2063unsigned char *dataP) {2064const RasterS_t *rasterP = &imageP->raster;2065const int w = rasterP->width;2066const int h = rasterP->height;20672068int y;2069jintArray jpixels = NULL;2070jint *pixels;2071unsigned char *dP = dataP;2072int numLines = h > NUM_LINES ? NUM_LINES : h;20732074/* it is safe to calculate the scan length, because width has been verified2075* on creation of the mlib image2076*/2077const int scanLength = w * 4;20782079int nbytes = 0;2080if (!SAFE_TO_MULT(numLines, scanLength)) {2081return -1;2082}20832084nbytes = numLines * scanLength;20852086jpixels = (*env)->NewIntArray(env, nbytes);2087if (JNU_IsNull(env, jpixels)) {2088(*env)->ExceptionClear(env);2089JNU_ThrowOutOfMemoryError(env, "Out of Memory");2090return -1;2091}20922093for (y = 0; y < h; y += numLines) {2094if (y + numLines > h) {2095numLines = h - y;2096nbytes = numLines * scanLength;2097}20982099(*env)->CallObjectMethod(env, imageP->jimage,2100g_BImgGetRGBMID, 0, y,2101w, numLines,2102jpixels, 0, w);2103if ((*env)->ExceptionOccurred(env)) {2104(*env)->DeleteLocalRef(env, jpixels);2105return -1;2106}21072108pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);2109if (pixels == NULL) {2110(*env)->DeleteLocalRef(env, jpixels);2111return -1;2112}21132114memcpy(dP, pixels, nbytes);2115dP += nbytes;21162117(*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels,2118JNI_ABORT);2119}21202121/* Need to release the array */2122(*env)->DeleteLocalRef(env, jpixels);21232124return 0;2125}21262127static int2128cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component,2129unsigned char *dataP) {2130const RasterS_t *rasterP = &imageP->raster;2131const int w = rasterP->width;2132const int h = rasterP->height;21332134int y;2135jintArray jpixels = NULL;2136jint *pixels;2137unsigned char *dP = dataP;2138int numLines = h > NUM_LINES ? NUM_LINES : h;21392140/* it is safe to calculate the scan length, because width has been verified2141* on creation of the mlib image2142*/2143const int scanLength = w * 4;21442145int nbytes = 0;2146if (!SAFE_TO_MULT(numLines, scanLength)) {2147return -1;2148}21492150nbytes = numLines * scanLength;21512152jpixels = (*env)->NewIntArray(env, nbytes);2153if (JNU_IsNull(env, jpixels)) {2154(*env)->ExceptionClear(env);2155JNU_ThrowOutOfMemoryError(env, "Out of Memory");2156return -1;2157}21582159for (y = 0; y < h; y += numLines) {2160if (y + numLines > h) {2161numLines = h - y;2162nbytes = numLines * scanLength;2163}21642165pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);2166if (pixels == NULL) {2167(*env)->DeleteLocalRef(env, jpixels);2168return -1;2169}21702171memcpy(pixels, dP, nbytes);2172dP += nbytes;21732174(*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, 0);21752176(*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y,2177w, numLines, jpixels,21780, w);2179if ((*env)->ExceptionOccurred(env)) {2180(*env)->DeleteLocalRef(env, jpixels);2181return -1;2182}2183}21842185/* Need to release the array */2186(*env)->DeleteLocalRef(env, jpixels);21872188return 0;2189}21902191static int2192allocateArray(JNIEnv *env, BufImageS_t *imageP,2193mlib_image **mlibImagePP, void **dataPP, int isSrc,2194int cvtToDefault, int addAlpha) {2195void *dataP;2196unsigned char *cDataP;2197RasterS_t *rasterP = &imageP->raster;2198ColorModelS_t *cmP = &imageP->cmodel;2199int dataType = BYTE_DATA_TYPE;2200int width;2201int height;2202HintS_t *hintP = &imageP->hints;2203*dataPP = NULL;22042205width = rasterP->width;2206height = rasterP->height;22072208/* Useful for convolution? */2209/* This code is zero'ed out so that it cannot be called */22102211/* To do this correctly, we need to expand src and dst in the */2212/* same direction up/down/left/right only if both can be expanded */2213/* in that direction. Expanding right and down is easy - */2214/* increment width. Expanding top and left requires bumping */2215/* around pointers and incrementing the width/height */22162217#if 02218if (0 && useEdges) {2219baseWidth = rasterP->baseRasterWidth;2220baseHeight = rasterP->baseRasterHeight;2221baseXoff = rasterP->baseOriginX;2222baseYoff = rasterP->baseOriginY;22232224if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {2225/* Can use edge */2226width++;2227}2228if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {2229/* Can use edge */2230height++;2231}22322233if (rasterP->minX > baseXoff ) {2234/* Can use edge */2235width++;2236/* NEED TO BUMP POINTER BACK A PIXELSTRIDE */2237}2238if (rasterP->minY > baseYoff) {2239/* Can use edge */2240height++;2241/* NEED TO BUMP POINTER BACK A SCANLINE */2242}224322442245}2246#endif2247if (cvtToDefault) {2248int status = 0;2249*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);2250if (*mlibImagePP == NULL) {2251return -1;2252}2253cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2254/* Make sure the image is cleared.2255* NB: the image dimension is already verified, so we can2256* safely calculate the length of the buffer.2257*/2258memset(cDataP, 0, width*height*4);22592260if (!isSrc) {2261return 0;2262}22632264switch(imageP->cmodel.cmType) {2265case INDEX_CM_TYPE:2266/* REMIND: Need to rearrange according to dst cm */2267/* Fix 4213160, 4184283 */2268if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {2269return expandICM(env, imageP, (unsigned int *)cDataP);2270}2271else {2272return cvtCustomToDefault(env, imageP, -1, cDataP);2273}22742275case DIRECT_CM_TYPE:2276switch(imageP->raster.dataType) {2277case BYTE_DATA_TYPE:2278return expandPackedBCRdefault(env, rasterP, -1, cDataP,2279!imageP->cmodel.supportsAlpha);2280case SHORT_DATA_TYPE:2281return expandPackedSCRdefault(env, rasterP, -1, cDataP,2282!imageP->cmodel.supportsAlpha);2283case INT_DATA_TYPE:2284return expandPackedICRdefault(env, rasterP, -1, cDataP,2285!imageP->cmodel.supportsAlpha);2286}2287} /* switch(imageP->cmodel.cmType) */22882289return cvtCustomToDefault(env, imageP, -1, cDataP);2290}22912292/* Interleaved with shared data */2293dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2294NULL);2295if (dataP == NULL) {2296return -1;2297}22982299/* Means we need to fill in alpha */2300if (!cvtToDefault && addAlpha) {2301*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);2302if (*mlibImagePP != NULL) {2303unsigned int *dstP = (unsigned int *)2304mlib_ImageGetData(*mlibImagePP);2305int dstride = (*mlibImagePP)->stride>>2;2306int sstride = hintP->sStride>>2;2307unsigned int *srcP = (unsigned int *)2308((unsigned char *)dataP + hintP->dataOffset);2309unsigned int *dP, *sP;2310int x, y;2311for (y=0; y < height; y++, srcP += sstride, dstP += dstride){2312sP = srcP;2313dP = dstP;2314for (x=0; x < width; x++) {2315dP[x] = sP[x] | 0xff000000;2316}2317}2318}2319(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2320JNI_ABORT);2321return 0;2322}2323else if ((hintP->packing & BYTE_INTERLEAVED) == BYTE_INTERLEAVED) {2324int nChans = (cmP->isDefaultCompatCM ? 4 : hintP->numChans);2325/* Easy case. It is or is similar to the default CM so use2326* the array. Must be byte data.2327*/2328/* Create the medialib image */2329*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE,2330nChans,2331width,2332height,2333hintP->sStride,2334(unsigned char *)dataP2335+ hintP->dataOffset);2336}2337else if ((hintP->packing & SHORT_INTERLEAVED) == SHORT_INTERLEAVED) {2338*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,2339hintP->numChans,2340width,2341height,2342imageP->raster.scanlineStride*2,2343(unsigned short *)dataP2344+ hintP->channelOffset);2345}2346else {2347/* Release the data array */2348(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2349JNI_ABORT);2350return -1;2351}23522353*dataPP = dataP;2354return 0;2355}23562357static int2358allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,2359mlib_image **mlibImagePP, void **dataPP, int isSrc) {2360void *dataP;2361unsigned char *cDataP;2362int dataType = BYTE_DATA_TYPE;2363int width;2364int height;2365int dataSize;2366int offset;23672368*dataPP = NULL;23692370width = rasterP->width;2371height = rasterP->height;23722373if (rasterP->numBands <= 0 || rasterP->numBands > 4) {2374/* REMIND: Fix this */2375return -1;2376}23772378/* Useful for convolution? */2379/* This code is zero'ed out so that it cannot be called */23802381/* To do this correctly, we need to expand src and dst in the */2382/* same direction up/down/left/right only if both can be expanded */2383/* in that direction. Expanding right and down is easy - */2384/* increment width. Expanding top and left requires bumping */2385/* around pointers and incrementing the width/height */23862387#if 02388if (0 && useEdges) {2389baseWidth = rasterP->baseRasterWidth;2390baseHeight = rasterP->baseRasterHeight;2391baseXoff = rasterP->baseOriginX;2392baseYoff = rasterP->baseOriginY;23932394if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {2395/* Can use edge */2396width++;2397}2398if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {2399/* Can use edge */2400height++;2401}24022403if (rasterP->minX > baseXoff ) {2404/* Can use edge */2405width++;2406/* NEED TO BUMP POINTER BACK A PIXELSTRIDE */2407}2408if (rasterP->minY > baseYoff) {2409/* Can use edge */2410height++;2411/* NEED TO BUMP POINTER BACK A SCANLINE */2412}241324142415}2416#endif2417switch (rasterP->type) {2418case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:2419if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&2420SAFE_TO_ALLOC_2(width, 4) &&2421SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 4)))2422{2423return -1;2424}2425offset = 4 * rasterP->chanOffsets[0];2426dataSize = 4 * (*env)->GetArrayLength(env, rasterP->jdata);24272428if (offset < 0 || offset >= dataSize ||2429width > rasterP->scanlineStride ||2430((width + (height - 1) * rasterP->scanlineStride) * 4) > dataSize - offset)2431{2432// raster data buffer is too short2433return -1;2434}2435dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2436NULL);2437if (dataP == NULL) {2438return -1;2439}2440*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, 4,2441width, height,2442rasterP->scanlineStride*4,2443(unsigned char *)dataP + offset);2444*dataPP = dataP;2445return 0;2446case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:2447if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&2448SAFE_TO_ALLOC_2(rasterP->scanlineStride, height)))2449{2450return -1;2451}2452offset = rasterP->chanOffsets[0];2453dataSize = (*env)->GetArrayLength(env, rasterP->jdata);24542455if (offset < 0 || offset >= dataSize ||2456width * rasterP->numBands > rasterP->scanlineStride ||2457((width * rasterP->numBands) +2458(height - 1) * rasterP->scanlineStride) > dataSize - offset)2459{2460// raster data buffer is too short2461return -1;2462}2463dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2464NULL);2465if (dataP == NULL) {2466return -1;2467}2468*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, rasterP->numBands,2469width, height,2470rasterP->scanlineStride,2471(unsigned char *)dataP + offset);2472*dataPP = dataP;2473return 0;2474case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:2475if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&2476SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&2477SAFE_TO_ALLOC_3(rasterP->scanlineStride, height, 2)))2478{2479return -1;2480}2481offset = rasterP->chanOffsets[0] * 2;2482dataSize = 2 * (*env)->GetArrayLength(env, rasterP->jdata);24832484if (offset < 0 || offset >= dataSize ||2485width * rasterP->numBands > rasterP->scanlineStride ||2486(((width * rasterP->numBands) +2487(height - 1) * rasterP->scanlineStride)) * 2 > dataSize - offset)2488{2489// raster data buffer is too short2490return -1;2491}2492dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,2493NULL);2494if (dataP == NULL) {2495return -1;2496}2497*mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,2498rasterP->numBands,2499width, height,2500rasterP->scanlineStride*2,2501(unsigned char *)dataP + offset);2502*dataPP = dataP;2503return 0;25042505case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:2506*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2507width, height);2508if (*mlibImagePP == NULL) {2509return -1;2510}2511if (!isSrc) return 0;2512cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2513return expandPackedBCR(env, rasterP, -1, cDataP);25142515case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:2516if (rasterP->sppsm.maxBitSize <= 8) {2517*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2518width, height);2519if (*mlibImagePP == NULL) {2520return -1;2521}2522if (!isSrc) return 0;2523cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2524return expandPackedSCR(env, rasterP, -1, cDataP);2525}2526break;2527case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:2528if (rasterP->sppsm.maxBitSize <= 8) {2529*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2530width, height);2531if (*mlibImagePP == NULL) {2532return -1;2533}2534if (!isSrc) return 0;2535cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);2536return expandPackedICR(env, rasterP, -1, cDataP);2537}2538break;2539}25402541/* Just expand it right now */2542switch (rasterP->dataType) {2543case BYTE_DATA_TYPE:2544if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,2545width, height)) == NULL) {2546return -1;2547}2548if (isSrc) {2549if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {2550(*sMlibSysFns.deleteImageFP)(*mlibImagePP);2551return -1;2552}2553}2554break;25552556case SHORT_DATA_TYPE:2557if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_SHORT,2558rasterP->numBands,2559width, height)) == NULL) {2560return -1;2561}2562if (isSrc) {2563if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) {2564(*sMlibSysFns.deleteImageFP)(*mlibImagePP);2565return -1;2566}2567}2568break;25692570default:2571return -1;2572}2573return 0;2574}25752576static void2577freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,2578void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,2579void *dstdataP) {2580jobject srcJdata = (srcimageP != NULL ? srcimageP->raster.jdata : NULL);2581jobject dstJdata = (dstimageP != NULL ? dstimageP->raster.jdata : NULL);2582freeDataArray(env, srcJdata, srcmlibImP, srcdataP,2583dstJdata, dstmlibImP, dstdataP);2584}2585static void2586freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,2587void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,2588void *dstdataP)2589{2590/* Free the medialib image */2591if (srcmlibImP) {2592(*sMlibSysFns.deleteImageFP)(srcmlibImP);2593}25942595/* Release the array */2596if (srcdataP) {2597(*env)->ReleasePrimitiveArrayCritical(env, srcJdata,2598srcdataP, JNI_ABORT);2599}26002601/* Free the medialib image */2602if (dstmlibImP) {2603(*sMlibSysFns.deleteImageFP)(dstmlibImP);2604}26052606/* Release the array */2607if (dstdataP) {2608(*env)->ReleasePrimitiveArrayCritical(env, dstJdata,2609dstdataP, 0);2610}2611}26122613#define ERR_BAD_IMAGE_LAYOUT (-2)26142615#define CHECK_DST_ARRAY(start_offset, elements_per_scan, elements_per_pixel) \2616do { \2617int offset = (start_offset); \2618int lastScanOffset; \2619\2620if (!SAFE_TO_MULT((elements_per_scan), \2621(rasterP->height - 1))) \2622{ \2623return ERR_BAD_IMAGE_LAYOUT; \2624} \2625lastScanOffset = (elements_per_scan) * (rasterP->height - 1); \2626\2627if (!SAFE_TO_ADD(offset, lastScanOffset)) { \2628return ERR_BAD_IMAGE_LAYOUT; \2629} \2630lastScanOffset += offset; \2631\2632if (!SAFE_TO_MULT((elements_per_pixel), rasterP->width)) { \2633return ERR_BAD_IMAGE_LAYOUT; \2634} \2635offset = (elements_per_pixel) * rasterP->width; \2636\2637if (!SAFE_TO_ADD(offset, lastScanOffset)) { \2638return ERR_BAD_IMAGE_LAYOUT; \2639} \2640lastScanOffset += offset; \2641\2642if (dataArrayLength < lastScanOffset) { \2643return ERR_BAD_IMAGE_LAYOUT; \2644} \2645} while(0); \26462647static int2648storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,2649mlib_image *mlibImP) {2650int mStride;2651unsigned char *cmDataP, *dataP, *cDataP;2652HintS_t *hintP = &dstP->hints;2653RasterS_t *rasterP = &dstP->raster;2654jsize dataArrayLength = (*env)->GetArrayLength(env, rasterP->jdata);2655int y;26562657/* REMIND: Store mlib data type? */26582659/* Check if it is an IndexColorModel */2660if (dstP->cmodel.cmType == INDEX_CM_TYPE) {2661if (dstP->raster.rasterType == COMPONENT_RASTER_TYPE) {2662return storeICMarray(env, srcP, dstP, mlibImP);2663}2664else {2665/* Packed or some other custom raster */2666cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2667return cvtDefaultToCustom(env, dstP, -1, cmDataP);2668}2669}26702671if (hintP->packing == BYTE_INTERLEAVED) {2672/* Write it back to the destination */2673if (rasterP->dataType != BYTE_DATA_TYPE) {2674/* We are working with a raster which was marked2675as a byte interleaved due to performance reasons.2676So, we have to convert the length of the data2677array to bytes as well.2678*/2679if (!SAFE_TO_MULT(rasterP->dataSize, dataArrayLength)) {2680return ERR_BAD_IMAGE_LAYOUT;2681}2682dataArrayLength *= rasterP->dataSize;2683}26842685CHECK_DST_ARRAY(hintP->dataOffset, hintP->sStride, hintP->numChans);2686cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2687mStride = mlib_ImageGetStride(mlibImP);2688dataP = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env,2689rasterP->jdata, NULL);2690if (dataP == NULL) return 0;2691cDataP = dataP + hintP->dataOffset;2692for (y=0; y < rasterP->height;2693y++, cmDataP += mStride, cDataP += hintP->sStride)2694{2695memcpy(cDataP, cmDataP, rasterP->width*hintP->numChans);2696}2697(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2698JNI_ABORT);2699}2700else if (dstP->cmodel.cmType == DIRECT_CM_TYPE) {2701/* Just need to move bits */2702if (mlibImP->type == MLIB_BYTE) {2703if (dstP->hints.packing == PACKED_BYTE_INTER) {2704return setPackedBCRdefault(env, rasterP, -1,2705(unsigned char *) mlibImP->data,2706dstP->cmodel.supportsAlpha);2707} else if (dstP->hints.packing == PACKED_SHORT_INTER) {2708return setPackedSCRdefault(env, rasterP, -1,2709(unsigned char *) mlibImP->data,2710dstP->cmodel.supportsAlpha);2711} else if (dstP->hints.packing == PACKED_INT_INTER) {2712return setPackedICRdefault(env, rasterP, -1,2713(unsigned char *) mlibImP->data,2714dstP->cmodel.supportsAlpha);2715}2716}2717else if (mlibImP->type == MLIB_SHORT) {2718return setPixelsFormMlibImage(env, rasterP, mlibImP);2719}2720}2721else {2722return cvtDefaultToCustom(env, dstP, -1,2723(unsigned char *)mlibImP->data);2724}27252726return 0;2727}27282729static int2730storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,2731mlib_image *mlibImP) {2732unsigned char *cDataP;27332734switch(dstP->type) {2735case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:2736cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2737return setPackedBCR(env, dstP, -1, cDataP);27382739case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:2740if (dstP->sppsm.maxBitSize <= 8) {2741cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2742return setPackedSCR(env, dstP, -1, cDataP);2743}2744break;2745case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:2746if (dstP->sppsm.maxBitSize <= 8) {2747cDataP = (unsigned char *) mlib_ImageGetData(mlibImP);2748return setPackedICR(env, dstP, -1, cDataP);2749}2750}27512752return -1;2753}275427552756static int2757storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,2758mlib_image *mlibImP)2759{2760int *argb;2761int x, y;2762unsigned char *dataP, *cDataP, *cP;2763unsigned char *sP;2764int aIdx, rIdx, gIdx, bIdx;2765ColorModelS_t *cmodelP = &dstP->cmodel;2766RasterS_t *rasterP = &dstP->raster;27672768/* REMIND: Only works for RGB */2769if (cmodelP->csType != java_awt_color_ColorSpace_TYPE_RGB) {2770JNU_ThrowInternalError(env, "Writing to non-RGB images not implemented yet");2771return -1;2772}27732774if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||2775srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||2776srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)2777{2778aIdx = 0;2779rIdx = 1;2780gIdx = 2;2781bIdx = 3;2782}2783else if (srcP->imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR||2784srcP->imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)2785{2786aIdx = 0;2787rIdx = 3;2788gIdx = 2;2789bIdx = 1;2790}2791else if (srcP->imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR){2792rIdx = 2;2793gIdx = 1;2794bIdx = 0;2795aIdx = 0; /* Ignored */2796}2797else if (srcP->cmodel.cmType == INDEX_CM_TYPE) {2798rIdx = 0;2799gIdx = 1;2800bIdx = 2;2801aIdx = 3; /* Use supportsAlpha to see if it is really there */2802}2803else {2804return -1;2805}28062807/* Lock down the destination raster */2808dataP = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env,2809rasterP->jdata, NULL);2810if (dataP == NULL) {2811return -1;2812}2813argb = (*env)->GetPrimitiveArrayCritical(env, cmodelP->jrgb, NULL);2814if (argb == NULL) {2815(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2816JNI_ABORT);2817return -1;2818}28192820cDataP = dataP + dstP->hints.dataOffset;2821sP = (unsigned char *) mlib_ImageGetData(mlibImP);28222823for (y=0; y < rasterP->height; y++, cDataP += rasterP->scanlineStride) {2824cP = cDataP;2825for (x=0; x < rasterP->width; x++, cP += rasterP->pixelStride) {2826*cP = colorMatch(sP[rIdx], sP[gIdx], sP[bIdx], sP[aIdx],2827(unsigned char *)argb, cmodelP->mapSize);2828sP += cmodelP->numComponents;2829}2830}28312832(*env)->ReleasePrimitiveArrayCritical(env, cmodelP->jrgb, argb, JNI_ABORT);2833(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,2834JNI_ABORT);2835return -1;2836}28372838static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP)2839{2840ColorModelS_t *cmP = &imageP->cmodel;2841RasterS_t *rasterP = &imageP->raster;2842HintS_t *hintP = &imageP->hints;2843int *rgb;2844int status = 0;2845unsigned char *dataP, *cP;2846unsigned int *mP;2847int width = rasterP->width;2848int height = rasterP->height;2849int x, y;28502851/* Need to grab the lookup tables. Right now only bytes */2852rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, cmP->jrgb, NULL);2853CHECK_NULL_RETURN(rgb, -1);28542855/* Interleaved with shared data */2856dataP = (void *) (*env)->GetPrimitiveArrayCritical(env,2857rasterP->jdata, NULL);2858if (dataP == NULL) {2859/* Release the lookup tables */2860(*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb, JNI_ABORT);2861return -1;2862}28632864if (rasterP->dataType == BYTE_DATA_TYPE) {2865unsigned char *cDataP = ((unsigned char *)dataP) + hintP->dataOffset;28662867for (y=0; y < height; y++) {2868mP = mDataP;2869cP = cDataP;2870for (x=0; x < width; x++, cP += rasterP->pixelStride) {2871*mP++ = rgb[*cP];2872}2873mDataP += width;2874cDataP += rasterP->scanlineStride;2875}2876}2877else if (rasterP->dataType == SHORT_DATA_TYPE) {2878unsigned short *sDataP, *sP;2879sDataP = ((unsigned short *)dataP) + hintP->channelOffset;28802881for (y=0; y < height; y++) {2882mP = mDataP;2883sP = sDataP;2884for (x=0; x < width; x++, sP+=rasterP->pixelStride) {2885*mP++ = rgb[*sP];2886}2887mDataP += width;2888sDataP += rasterP->scanlineStride;2889}2890}2891else {2892/* Unknown type */2893status = -1;2894}2895/* Release the lookup table data */2896(*env)->ReleasePrimitiveArrayCritical(env, imageP->cmodel.jrgb,2897rgb, JNI_ABORT);2898/* Release the data array */2899(*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata,2900dataP, JNI_ABORT);2901return status;2902}2903/* This routine is expecting a ByteComponentRaster with a PackedColorModel */2904static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,2905unsigned char *outDataP)2906{2907int x, y, c;2908unsigned char *outP = outDataP;2909unsigned char *lineInP, *inP;2910jarray jInDataP;2911jint *inDataP;2912int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];29132914if (rasterP->numBands > MAX_NUMBANDS) {2915return -1;2916}29172918/* Grab data ptr, strides, offsets from raster */2919jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);2920inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);2921if (inDataP == NULL) {2922return -1;2923}2924lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0];29252926if (component < 0) {2927for (c=0; c < rasterP->numBands; c++) {2928roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);2929if (roff[c] < 0) {2930loff[c] = -roff[c];2931roff[c] = 0;2932}2933else loff[c] = 0;2934}2935/* Convert the all bands */2936if (rasterP->numBands < 4) {2937/* Need to put in alpha */2938for (y=0; y < rasterP->height; y++) {2939inP = lineInP;2940for (x=0; x < rasterP->width; x++) {2941for (c=0; c < rasterP->numBands; c++) {2942*outP++ = (unsigned char)2943(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])2944<<loff[c]);2945}2946inP++;2947}2948lineInP += rasterP->scanlineStride;2949}2950}2951else {2952for (y=0; y < rasterP->height; y++) {2953inP = lineInP;2954for (x=0; x < rasterP->width; x++) {2955for (c=0; c < rasterP->numBands; c++) {2956*outP++ = (unsigned char)2957(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])2958<<loff[c]);2959}2960inP++;2961}2962lineInP += rasterP->scanlineStride;2963}2964}2965}2966else {2967c = component;2968roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);2969if (roff[0] < 0) {2970loff[0] = -roff[0];2971roff[0] = 0;2972}2973else loff[c] = 0;2974for (y=0; y < rasterP->height; y++) {2975inP = lineInP;2976for (x=0; x < rasterP->width; x++) {2977*outP++ = (unsigned char)2978((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];2979inP++;2980}2981lineInP += rasterP->scanlineStride;2982}2983}29842985(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);29862987return 0;2988}29892990/* This routine is expecting a ByteComponentRaster with a PackedColorModel */2991static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,2992int component, unsigned char *outDataP,2993int forceAlpha)2994{2995int x, y, c;2996unsigned char *outP = outDataP;2997unsigned char *lineInP, *inP;2998jarray jInDataP;2999jint *inDataP;3000int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3001int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);3002int a = numBands;30033004if (rasterP->numBands > MAX_NUMBANDS) {3005return -1;3006}30073008/* Grab data ptr, strides, offsets from raster */3009jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);3010inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3011if (inDataP == NULL) {3012return -1;3013}3014lineInP = (unsigned char *)inDataP + rasterP->chanOffsets[0];30153016if (component < 0) {3017for (c=0; c < rasterP->numBands; c++) {3018roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3019if (roff[c] < 0) {3020loff[c] = -roff[c];3021roff[c] = 0;3022}3023else loff[c] = 0;3024}30253026/* Need to put in alpha */3027if (forceAlpha) {3028for (y=0; y < rasterP->height; y++) {3029inP = lineInP;3030for (x=0; x < rasterP->width; x++) {3031*outP++ = 0xff;3032for (c=0; c < numBands; c++) {3033*outP++ = (unsigned char)3034(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3035<<loff[c]);3036}3037inP++;3038}3039lineInP += rasterP->scanlineStride;3040}3041}3042else {3043for (y=0; y < rasterP->height; y++) {3044inP = lineInP;3045for (x=0; x < rasterP->width; x++) {3046*outP++ = (unsigned char)3047(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])3048<<loff[a]);3049for (c=0; c < numBands; c++) {3050*outP++ = (unsigned char)3051(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3052<<loff[c]);3053}3054inP++;3055}3056lineInP += rasterP->scanlineStride;3057}3058}3059}3060else {3061c = component;3062roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3063if (roff[0] < 0) {3064loff[0] = -roff[0];3065roff[0] = 0;3066}3067else loff[c] = 0;3068for (y=0; y < rasterP->height; y++) {3069inP = lineInP;3070for (x=0; x < rasterP->width; x++) {3071*outP++ = (unsigned char)3072((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];3073inP++;3074}3075lineInP += rasterP->scanlineStride;3076}3077}30783079(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);30803081return 0;3082}30833084/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3085static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,3086unsigned char *outDataP)3087{3088int x, y, c;3089unsigned char *outP = outDataP;3090unsigned short *lineInP, *inP;3091jarray jInDataP;3092jint *inDataP;3093int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];30943095if (rasterP->numBands > MAX_NUMBANDS) {3096return -1;3097}30983099/* Grab data ptr, strides, offsets from raster */3100jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3101inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3102if (inDataP == NULL) {3103return -1;3104}3105lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0];31063107if (component < 0) {3108for (c=0; c < rasterP->numBands; c++) {3109roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3110if (roff[c] < 0) {3111loff[c] = -roff[c];3112roff[c] = 0;3113}3114else loff[c] = 0;3115}3116/* Convert the all bands */3117if (rasterP->numBands < 4) {3118/* Need to put in alpha */3119for (y=0; y < rasterP->height; y++) {3120inP = lineInP;3121for (x=0; x < rasterP->width; x++) {3122for (c=0; c < rasterP->numBands; c++) {3123/*3124*Not correct. Might need to unpremult,3125* shift, etc3126*/3127*outP++ = (unsigned char)3128(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3129<<loff[c]);3130}3131inP++;3132}3133lineInP += rasterP->scanlineStride;3134}3135} else {3136for (y=0; y < rasterP->height; y++) {3137inP = lineInP;3138for (x=0; x < rasterP->width; x++) {3139for (c=0; c < rasterP->numBands; c++) {3140/*3141*Not correct. Might need to unpremult,3142* shift, etc3143*/3144*outP++ = (unsigned char)3145(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3146<<loff[c]);3147}3148inP++;3149}3150lineInP += rasterP->scanlineStride;3151}3152}3153}3154else {3155c = component;3156roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3157if (roff[0] < 0) {3158loff[0] = -roff[0];3159roff[0] = 0;3160}3161else loff[c] = 0;3162for (y=0; y < rasterP->height; y++) {3163inP = lineInP;3164for (x=0; x < rasterP->width; x++) {3165*outP++ = (unsigned char)3166((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];3167inP++;3168}3169lineInP += rasterP->scanlineStride;3170}3171}31723173(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);31743175return 0;3176}31773178/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3179static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,3180int component, unsigned char *outDataP,3181int forceAlpha)3182{3183int x, y, c;3184unsigned char *outP = outDataP;3185unsigned short *lineInP, *inP;3186jarray jInDataP;3187jint *inDataP;3188int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3189int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);3190int a = numBands;31913192if (rasterP->numBands > MAX_NUMBANDS) {3193return -1;3194}31953196/* Grab data ptr, strides, offsets from raster */3197jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3198inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3199if (inDataP == NULL) {3200return -1;3201}3202lineInP = (unsigned short *)inDataP + rasterP->chanOffsets[0];32033204if (component < 0) {3205for (c=0; c < rasterP->numBands; c++) {3206roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3207if (roff[c] < 0) {3208loff[c] = -roff[c];3209roff[c] = 0;3210}3211else loff[c] = 0;3212}32133214/* Need to put in alpha */3215if (forceAlpha) {3216for (y=0; y < rasterP->height; y++) {3217inP = lineInP;3218for (x=0; x < rasterP->width; x++) {3219*outP++ = 0xff;3220for (c=0; c < numBands; c++) {3221/*3222* Not correct. Might need to unpremult,3223* shift, etc3224*/3225*outP++ = (unsigned char)3226(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3227<<loff[c]);3228}3229inP++;3230}3231lineInP += rasterP->scanlineStride;3232}3233}3234else {3235for (y=0; y < rasterP->height; y++) {3236inP = lineInP;3237for (x=0; x < rasterP->width; x++) {3238*outP++ = (unsigned char)3239(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])3240<<loff[a]);3241for (c=0; c < numBands; c++) {3242/*3243* Not correct. Might need to3244* unpremult, shift, etc3245*/3246*outP++ = (unsigned char)3247(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3248<<loff[c]);3249}3250inP++;3251}3252lineInP += rasterP->scanlineStride;3253}3254}3255}3256else {3257c = component;3258roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3259if (roff[0] < 0) {3260loff[0] = -roff[0];3261roff[0] = 0;3262}3263else loff[c] = 0;3264for (y=0; y < rasterP->height; y++) {3265inP = lineInP;3266for (x=0; x < rasterP->width; x++) {3267*outP++ = (unsigned char)3268((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];3269inP++;3270}3271lineInP += rasterP->scanlineStride;3272}3273}32743275(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);32763277return 0;32783279}32803281/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3282static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,3283unsigned char *outDataP)3284{3285int x, y, c;3286unsigned char *outP = outDataP;3287unsigned int *lineInP, *inP;3288jarray jInDataP;3289jint *inDataP;3290int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];32913292if (rasterP->numBands > MAX_NUMBANDS) {3293return -1;3294}32953296/* Grab data ptr, strides, offsets from raster */3297jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3298inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3299if (inDataP == NULL) {3300return -1;3301}3302lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0];33033304if (component < 0) {3305for (c=0; c < rasterP->numBands; c++) {3306roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3307if (roff[c] < 0) {3308loff[c] = -roff[c];3309roff[c] = 0;3310}3311else loff[c] = 0;3312}3313/* Convert the all bands */3314if (rasterP->numBands < 4) {3315for (y=0; y < rasterP->height; y++) {3316inP = lineInP;3317for (x=0; x < rasterP->width; x++) {3318for (c=0; c < rasterP->numBands; c++) {3319/*3320* Not correct. Might need to unpremult,3321* shift, etc3322*/3323*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3324<<loff[c]);3325}3326inP++;3327}3328lineInP += rasterP->scanlineStride;3329}3330}3331else {3332for (y=0; y < rasterP->height; y++) {3333inP = lineInP;3334for (x=0; x < rasterP->width; x++) {3335for (c=0; c < rasterP->numBands; c++) {3336/*3337* Not correct. Might need to3338* unpremult, shift, etc3339*/3340*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3341<<loff[c]);3342}3343inP++;3344}3345lineInP += rasterP->scanlineStride;3346}3347}3348}3349else {3350c = component;3351roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3352if (roff[0] < 0) {3353loff[0] = -roff[0];3354roff[0] = 0;3355}3356else loff[c] = 0;3357for (y=0; y < rasterP->height; y++) {3358inP = lineInP;3359for (x=0; x < rasterP->width; x++) {3360*outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);3361inP++;3362}3363lineInP += rasterP->scanlineStride;3364}3365}33663367(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);33683369return 0;3370}33713372/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3373static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,3374int component, unsigned char *outDataP,3375int forceAlpha)3376{3377int x, y, c;3378unsigned char *outP = outDataP;3379unsigned int *lineInP, *inP;3380jarray jInDataP;3381jint *inDataP;3382int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3383int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);3384int a = numBands;33853386if (rasterP->numBands > MAX_NUMBANDS) {3387return -1;3388}33893390/* Grab data ptr, strides, offsets from raster */3391jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3392inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);3393if (inDataP == NULL) {3394return -1;3395}3396lineInP = (unsigned int *)inDataP + rasterP->chanOffsets[0];33973398if (component < 0) {3399for (c=0; c < rasterP->numBands; c++) {3400roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3401if (roff[c] < 0) {3402loff[c] = -roff[c];3403roff[c] = 0;3404}3405else loff[c] = 0;3406}34073408/* Need to put in alpha */3409if (forceAlpha) {3410for (y=0; y < rasterP->height; y++) {3411inP = lineInP;3412for (x=0; x < rasterP->width; x++) {3413*outP++ = 0xff;3414for (c=0; c < numBands; c++) {3415/*3416* Not correct. Might need to unpremult,3417* shift, etc3418*/3419*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3420<<loff[c]);3421}3422inP++;3423}3424lineInP += rasterP->scanlineStride;3425}3426}3427else {3428for (y=0; y < rasterP->height; y++) {3429inP = lineInP;3430for (x=0; x < rasterP->width; x++) {3431*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])3432<<loff[a]);3433for (c=0; c < numBands; c++) {3434/*3435* Not correct. Might need to3436* unpremult, shift, etc3437*/3438*outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])3439<<loff[c]);3440}3441inP++;3442}3443lineInP += rasterP->scanlineStride;3444}3445}3446}3447else {3448c = component;3449roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3450if (roff[0] < 0) {3451loff[0] = -roff[0];3452roff[0] = 0;3453}3454else loff[c] = 0;3455for (y=0; y < rasterP->height; y++) {3456inP = lineInP;3457for (x=0; x < rasterP->width; x++) {3458*outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);3459inP++;3460}3461lineInP += rasterP->scanlineStride;3462}3463}34643465(*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);34663467return 0;3468}34693470/* This routine is expecting a ByteComponentRaster with a PackedColorModel */3471static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,3472unsigned char *inDataP)3473{3474int x, y, c;3475unsigned char *inP = inDataP;3476unsigned char *lineOutP, *outP;3477jarray jOutDataP;3478jsize dataArrayLength;3479unsigned char *outDataP;3480int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];34813482if (rasterP->numBands > MAX_NUMBANDS) {3483return -1;3484}34853486/* Grab data ptr, strides, offsets from raster */3487jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);3488if (JNU_IsNull(env, jOutDataP)) {3489return -1;3490}34913492dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3493CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);34943495outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3496if (outDataP == NULL) {3497return -1;3498}3499lineOutP = outDataP + rasterP->chanOffsets[0];35003501if (component < 0) {3502for (c=0; c < rasterP->numBands; c++) {3503loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3504if (loff[c] < 0) {3505roff[c] = -loff[c];3506loff[c] = 0;3507}3508else roff[c] = 0;3509}3510/* Convert the all bands */3511for (y=0; y < rasterP->height; y++) {3512outP = lineOutP;3513*outP = 0;3514for (x=0; x < rasterP->width; x++) {3515for (c=0; c < rasterP->numBands; c++, inP++) {3516*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3517}3518outP++;3519}3520lineOutP += rasterP->scanlineStride;3521}3522}3523else {3524c = component;3525loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3526if (loff[0] < 0) {3527roff[0] = -loff[0];3528loff[0] = 0;3529}3530else roff[c] = 0;3531for (y=0; y < rasterP->height; y++) {3532outP = lineOutP;3533for (x=0; x < rasterP->width; x++, inP++) {3534*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3535outP++;3536}3537lineOutP += rasterP->scanlineStride;3538}3539}35403541(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);35423543return 0;3544}35453546/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3547static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,3548unsigned char *inDataP)3549{3550int x, y, c;3551unsigned char *inP = inDataP;3552unsigned short *lineOutP, *outP;3553jarray jOutDataP;3554jsize dataArrayLength;3555unsigned short *outDataP;3556int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];35573558if (rasterP->numBands > MAX_NUMBANDS) {3559return -1;3560}35613562/* Grab data ptr, strides, offsets from raster */3563jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3564if (JNU_IsNull(env, jOutDataP)) {3565return -1;3566}35673568dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3569CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);35703571outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3572if (outDataP == NULL) {3573return -1;3574}3575lineOutP = outDataP + rasterP->chanOffsets[0];35763577if (component < 0) {3578for (c=0; c < rasterP->numBands; c++) {3579loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3580if (loff[c] < 0) {3581roff[c] = -loff[c];3582loff[c] = 0;3583}3584else roff[c] = 0;3585}3586/* Convert the all bands */3587for (y=0; y < rasterP->height; y++) {3588outP = lineOutP;3589for (x=0; x < rasterP->width; x++) {3590for (c=0; c < rasterP->numBands; c++, inP++) {3591/* Not correct. Might need to unpremult, shift, etc */3592*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3593}3594outP++;3595}3596lineOutP += rasterP->scanlineStride;3597}3598}3599else {3600c = component;3601loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3602if (loff[0] < 0) {3603roff[0] = -loff[0];3604loff[0] = 0;3605}3606else roff[c] = 0;3607for (y=0; y < rasterP->height; y++) {3608outP = lineOutP;3609for (x=0; x < rasterP->width; x++, inP++) {3610*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3611outP++;3612}3613lineOutP += rasterP->scanlineStride;3614}3615}36163617(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);36183619return 0;3620}36213622/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3623static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,3624unsigned char *inDataP)3625{3626int x, y, c;3627unsigned char *inP = inDataP;3628unsigned int *lineOutP, *outP;3629jarray jOutDataP;3630jsize dataArrayLength;3631unsigned int *outDataP;3632int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];36333634if (rasterP->numBands > MAX_NUMBANDS) {3635return -1;3636}36373638/* Grab data ptr, strides, offsets from raster */3639jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3640if (JNU_IsNull(env, jOutDataP)) {3641return -1;3642}36433644dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3645CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);36463647outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3648if (outDataP == NULL) {3649return -1;3650}3651lineOutP = outDataP + rasterP->chanOffsets[0];36523653if (component < 0) {3654for (c=0; c < rasterP->numBands; c++) {3655loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3656if (loff[c] < 0) {3657roff[c] = -loff[c];3658loff[c] = 0;3659}3660else roff[c] = 0;3661}3662/* Convert the all bands */3663for (y=0; y < rasterP->height; y++) {3664outP = lineOutP;3665for (x=0; x < rasterP->width; x++) {3666for (c=0; c < rasterP->numBands; c++, inP++) {3667/* Not correct. Might need to unpremult, shift, etc */3668*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3669}3670outP++;3671}3672lineOutP += rasterP->scanlineStride;3673}3674}3675else {3676c = component;3677loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3678if (loff[0] < 0) {3679roff[0] = -loff[0];3680loff[0] = 0;3681}3682else roff[c] = 0;36833684for (y=0; y < rasterP->height; y++) {3685outP = lineOutP;3686for (x=0; x < rasterP->width; x++, inP++) {3687*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3688outP++;3689}3690lineOutP += rasterP->scanlineStride;3691}3692}36933694(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);36953696return 0;3697}36983699/* This routine is expecting a ByteComponentRaster with a PackedColorModel */3700static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,3701int component, unsigned char *inDataP,3702int supportsAlpha)3703{3704int x, y, c;3705unsigned char *inP = inDataP;3706unsigned char *lineOutP, *outP;3707jarray jOutDataP;3708jsize dataArrayLength;3709unsigned char *outDataP;3710int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3711int a = rasterP->numBands - 1;37123713if (rasterP->numBands > MAX_NUMBANDS) {3714return -1;3715}37163717/* Grab data ptr, strides, offsets from raster */3718jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);3719if (JNU_IsNull(env, jOutDataP)) {3720return -1;3721}37223723dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3724CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);37253726outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3727if (outDataP == NULL) {3728return -1;3729}3730lineOutP = outDataP + rasterP->chanOffsets[0];37313732if (component < 0) {3733for (c=0; c < rasterP->numBands; c++) {3734loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3735if (loff[c] < 0) {3736roff[c] = -loff[c];3737loff[c] = 0;3738}3739else roff[c] = 0;3740}3741/* Convert the all bands */3742if (supportsAlpha) {3743for (y=0; y < rasterP->height; y++) {3744outP = lineOutP;3745*outP = 0;3746for (x=0; x < rasterP->width; x++) {3747*outP |= (*inP<<loff[a]>>roff[a])&3748rasterP->sppsm.maskArray[a];3749inP++;3750for (c=0; c < rasterP->numBands-1; c++, inP++) {3751*outP |= (*inP<<loff[c]>>roff[c])&3752rasterP->sppsm.maskArray[c];3753}3754outP++;3755}3756lineOutP += rasterP->scanlineStride;3757}3758}3759else {3760for (y=0; y < rasterP->height; y++) {3761outP = lineOutP;3762*outP = 0;3763for (x=0; x < rasterP->width; x++) {3764inP++;3765for (c=0; c < rasterP->numBands; c++, inP++) {3766*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3767}3768outP++;3769}3770lineOutP += rasterP->scanlineStride;3771}3772}3773}3774else {3775c = component;3776loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3777if (loff[0] < 0) {3778roff[0] = -loff[0];3779loff[0] = 0;3780}3781else roff[c] = 0;3782for (y=0; y < rasterP->height; y++) {3783outP = lineOutP;3784for (x=0; x < rasterP->width; x++, inP++) {3785*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3786outP++;3787}3788lineOutP += rasterP->scanlineStride;3789}3790}37913792(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);37933794return 0;3795}37963797/* This routine is expecting a ShortComponentRaster with a PackedColorModel */3798static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,3799int component, unsigned char *inDataP,3800int supportsAlpha)3801{3802int x, y, c;3803unsigned char *inP = inDataP;3804unsigned short *lineOutP, *outP;3805jarray jOutDataP;3806jsize dataArrayLength;3807unsigned short *outDataP;3808int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3809int a = rasterP->numBands - 1;38103811if (rasterP->numBands > MAX_NUMBANDS) {3812return -1;3813}38143815/* Grab data ptr, strides, offsets from raster */3816jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);3817if (JNU_IsNull(env, jOutDataP)) {3818return -1;3819}3820dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3821CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);38223823outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3824if (outDataP == NULL) {3825return -1;3826}3827lineOutP = outDataP + rasterP->chanOffsets[0];38283829if (component < 0) {3830for (c=0; c < rasterP->numBands; c++) {3831loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3832if (loff[c] < 0) {3833roff[c] = -loff[c];3834loff[c] = 0;3835}3836else roff[c] = 0;3837}3838/* Convert the all bands */3839if (supportsAlpha) {3840for (y=0; y < rasterP->height; y++) {3841outP = lineOutP;3842for (x=0; x < rasterP->width; x++) {3843*outP |= (*inP<<loff[a]>>roff[a])&3844rasterP->sppsm.maskArray[a];3845inP++;3846for (c=0; c < rasterP->numBands-1; c++, inP++) {3847/* Not correct. Might need to unpremult, shift, etc */3848*outP |= (*inP<<loff[c]>>roff[c])&3849rasterP->sppsm.maskArray[c];3850}3851outP++;3852}3853lineOutP += rasterP->scanlineStride;3854}3855}3856else {3857for (y=0; y < rasterP->height; y++) {3858outP = lineOutP;3859for (x=0; x < rasterP->width; x++) {3860inP++;3861for (c=0; c < rasterP->numBands; c++, inP++) {3862/* Not correct. Might need to unpremult, shift, etc */3863*outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];3864}3865outP++;3866}3867lineOutP += rasterP->scanlineStride;3868}3869}3870}3871else {3872c = component;3873loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3874if (loff[0] < 0) {3875roff[0] = -loff[0];3876loff[0] = 0;3877}3878else roff[c] = 0;3879for (y=0; y < rasterP->height; y++) {3880outP = lineOutP;3881for (x=0; x < rasterP->width; x++, inP++) {3882*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3883outP++;3884}3885lineOutP += rasterP->scanlineStride;3886}3887}38883889(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);38903891return 0;3892}38933894/* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/3895static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,3896int component, unsigned char *inDataP,3897int supportsAlpha)3898{3899int x, y, c;3900unsigned char *inP = inDataP;3901unsigned int *lineOutP, *outP;3902jarray jOutDataP;3903jsize dataArrayLength;3904unsigned int *outDataP;3905int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];3906int a = rasterP->numBands - 1;39073908if (rasterP->numBands > MAX_NUMBANDS) {3909return -1;3910}39113912/* Grab data ptr, strides, offsets from raster */3913jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);3914if (JNU_IsNull(env, jOutDataP)) {3915return -1;3916}39173918dataArrayLength = (*env)->GetArrayLength(env, jOutDataP);3919CHECK_DST_ARRAY(rasterP->chanOffsets[0], rasterP->scanlineStride, 1);39203921outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);3922if (outDataP == NULL) {3923return -1;3924}3925lineOutP = outDataP + rasterP->chanOffsets[0];39263927if (component < 0) {3928for (c=0; c < rasterP->numBands; c++) {3929loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3930if (loff[c] < 0) {3931roff[c] = -loff[c];3932loff[c] = 0;3933}3934else roff[c] = 0;3935}3936/* Convert the all bands */3937if (supportsAlpha) {3938for (y=0; y < rasterP->height; y++) {3939outP = lineOutP;3940for (x=0; x < rasterP->width; x++) {3941*outP |= (*inP<<loff[a]>>roff[a])&3942rasterP->sppsm.maskArray[a];3943inP++;3944for (c=0; c < rasterP->numBands-1; c++, inP++) {3945/* Not correct. Might need to unpremult, shift, etc */3946*outP |= (*inP<<loff[c]>>roff[c])&3947rasterP->sppsm.maskArray[c];3948}3949outP++;3950}3951lineOutP += rasterP->scanlineStride;3952}3953}3954else {3955for (y=0; y < rasterP->height; y++) {3956outP = lineOutP;3957for (x=0; x < rasterP->width; x++) {3958inP++;3959for (c=0; c < rasterP->numBands; c++, inP++) {3960/* Not correct. Might need to unpremult, shift, etc */3961*outP |= (*inP<<loff[c]>>roff[c])&3962rasterP->sppsm.maskArray[c];3963}3964outP++;3965}3966lineOutP += rasterP->scanlineStride;3967}3968}3969}3970else {3971c = component;3972loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);3973if (loff[0] < 0) {3974roff[0] = -loff[0];3975loff[0] = 0;3976}3977else roff[c] = 0;39783979for (y=0; y < rasterP->height; y++) {3980outP = lineOutP;3981for (x=0; x < rasterP->width; x++, inP++) {3982*outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];3983outP++;3984}3985lineOutP += rasterP->scanlineStride;3986}3987}39883989(*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);39903991return 0;3992}39933994/* This is temporary code. Should go away when there is better color3995* conversion code available.3996* REMIND: Ignoring alpha3997*/3998/* returns the absolute value x */3999#define ABS(x) ((x) < 0 ? -(x) : (x))4000#define CLIP(val,min,max) ((val < min) ? min : ((val > max) ? max : val))40014002static int4003colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors) {4004int besti = 0;4005int mindist, i, t, d;4006unsigned char red, green, blue;40074008r = CLIP(r, 0, 255);4009g = CLIP(g, 0, 255);4010b = CLIP(b, 0, 255);40114012/* look for pure gray match */4013if ((r == g) && (g == b)) {4014mindist = 256;4015for (i = 0 ; i < numColors ; i++, argb+=4) {4016red = argb[1];4017green = argb[2];4018blue = argb[3];4019if (! ((red == green) && (green == blue)) ) {4020continue;4021}4022d = ABS(red - r);4023if (d == 0)4024return i;4025if (d < mindist) {4026besti = i;4027mindist = d;4028}4029}4030return besti;4031}40324033/* look for non-pure gray match */4034mindist = 256 * 256 * 256;4035for (i = 0 ; i < numColors ; i++, argb+=4) {4036red = argb[1];4037green = argb[2];4038blue = argb[3];4039t = red - r;4040d = t * t;4041if (d >= mindist) {4042continue;4043}4044t = green - g;4045d += t * t;4046if (d >= mindist) {4047continue;4048}4049t = blue - b;4050d += t * t;4051if (d >= mindist) {4052continue;4053}4054if (d == 0)4055return i;4056if (d < mindist) {4057besti = i;4058mindist = d;4059}4060}40614062return besti;4063}406440654066