1 /*
   2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include "sun_awt_image_ImagingLib.h"
  30 #include "java_awt_Transparency.h"
  31 #include "java_awt_image_AffineTransformOp.h"
  32 #include "java_awt_image_BufferedImage.h"
  33 #include "java_awt_color_ColorSpace.h"
  34 #include "java_awt_image_ConvolveOp.h"
  35 #include "sun_awt_image_IntegerComponentRaster.h"
  36 #include "awt_ImagingLib.h"
  37 #include "awt_parseImage.h"
  38 #include "imageInitIDs.h"
  39 #include <jni.h>
  40 #include <jni_util.h>
  41 #include <assert.h>
  42 #include "awt_Mlib.h"
  43 #include "gdefs.h"
  44 #include "safe_alloc.h"
  45 
  46 /***************************************************************************
  47  *                               Definitions                               *
  48  ***************************************************************************/
  49 #define jio_fprintf fprintf
  50 
  51 #ifndef TRUE
  52 #define TRUE 1
  53 #endif /* TRUE */
  54 
  55 #ifndef FALSE
  56 #define FALSE 0
  57 #endif /* FALSE */
  58 
  59 #define TYPE_CUSTOM         java_awt_image_BufferedImage_TYPE_CUSTOM
  60 #define TYPE_INT_RGB        java_awt_image_BufferedImage_TYPE_INT_RGB
  61 #define TYPE_INT_ARGB       java_awt_image_BufferedImage_TYPE_INT_ARGB
  62 #define TYPE_INT_ARGB_PRE   java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE
  63 #define TYPE_INT_BGR        java_awt_image_BufferedImage_TYPE_INT_BGR
  64 #define TYPE_4BYTE_ABGR     java_awt_image_BufferedImage_TYPE_4BYTE_ABGR
  65 #define TYPE_4BYTE_ABGR_PRE java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE
  66 
  67 /* (alpha*color)>>nbits + alpha>>(nbits-1) */
  68 #define BLEND(color, alpha, alphaNbits) \
  69     ((((alpha)*(color))>>(alphaNbits)) + ((alpha) >> ((alphaNbits)-1)))
  70 
  71     /* ((color - (alpha>>(nBits-1)))<<nBits)/alpha */
  72 #define UNBLEND(color, alpha, alphaNbits) \
  73     ((((color)-((alpha)>>((alphaNbits)-1)))<<(alphaNbits))/(alpha))
  74 
  75 /* Enumeration of all of the mlib functions used */
  76 typedef enum {
  77     MLIB_CONVMxN,
  78     MLIB_AFFINE,
  79     MLIB_LOOKUP,
  80     MLIB_CONVKERNCVT
  81 } mlibTypeE_t;
  82 
  83 typedef struct {
  84     int dataType;           /* One of BYTE_DATA_TYPE, SHORT_DATA_TYPE, */
  85     int needToCopy;
  86     int cvtSrcToDefault;    /* If TRUE, convert the src to def CM (pre?) */
  87     int allocDefaultDst;    /* If TRUE, alloc def CM dst buffer */
  88     int cvtToDst;           /* If TRUE, convert dst buffer to Dst CM */
  89     int addAlpha;
  90 } mlibHintS_t;
  91 
  92 /***************************************************************************
  93  *                     Static Variables/Structures                         *
  94  ***************************************************************************/
  95 
  96 static mlibSysFnS_t sMlibSysFns = {
  97     NULL, // placeholder for j2d_mlib_ImageCreate
  98     NULL, // placeholder for j2d_mlib_ImageCreateStruct
  99     NULL, // placeholder for j2d_mlib_ImageDelete
 100 };
 101 
 102 static 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 };
 109 
 110 static int s_timeIt = 0;
 111 static int s_printIt = 0;
 112 static int s_startOff = 0;
 113 static int s_nomlib = 0;
 114 
 115 /***************************************************************************
 116  *                          Static Function Prototypes                     *
 117  ***************************************************************************/
 118 
 119 static int
 120 allocateArray(JNIEnv *env, BufImageS_t *imageP,
 121               mlib_image **mlibImagePP, void **dataPP, int isSrc,
 122               int cvtToDefault, int addAlpha);
 123 static int
 124 allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
 125                     mlib_image **mlibImagePP, void **dataPP, int isSrc);
 126 
 127 static void
 128 freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,
 129           void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,
 130           void *dstdataP);
 131 static void
 132 freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,
 133           void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,
 134           void *dstdataP);
 135 
 136 static int
 137 storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
 138                 mlib_image *mlibImP);
 139 
 140 static int
 141 storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,
 142                 mlib_image *mlibImP);
 143 
 144 static int
 145 storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
 146               mlib_image *mlibImP);
 147 
 148 static int
 149 colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors);
 150 
 151 static int
 152 setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
 153               int expandICM, int useAlpha,
 154               int premultiply, mlibHintS_t *hintP);
 155 
 156 
 157 static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP);
 158 static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
 159                            unsigned char *outDataP);
 160 static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
 161                            unsigned char *outDataP);
 162 static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
 163                            unsigned char *outDataP);
 164 static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
 165                                   int component, unsigned char *outDataP,
 166                                   int forceAlpha);
 167 static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
 168                                   int component, unsigned char *outDataP,
 169                                   int forceAlpha);
 170 static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
 171                                   int component, unsigned char *outDataP,
 172                                   int forceAlpha);
 173 static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
 174                         unsigned char *outDataP);
 175 static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
 176                         unsigned char *outDataP);
 177 static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
 178                         unsigned char *outDataP);
 179 static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
 180                                int component, unsigned char *outDataP,
 181                                int supportsAlpha);
 182 static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
 183                                int component, unsigned char *outDataP,
 184                                int supportsAlpha);
 185 static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
 186                                int component, unsigned char *outDataP,
 187                                int supportsAlpha);
 188 
 189 mlib_start_timer start_timer = NULL;
 190 mlib_stop_timer stop_timer = NULL;
 191 
 192 /***************************************************************************
 193  *                          Debugging Definitions                          *
 194  ***************************************************************************/
 195 #ifdef DEBUG
 196 
 197 static void
 198 printMedialibError(int status) {
 199     switch(status) {
 200     case MLIB_FAILURE:
 201         jio_fprintf(stderr, "failure\n");
 202         break;
 203     case MLIB_NULLPOINTER:
 204         jio_fprintf(stderr, "null pointer\n");
 205         break;
 206     case MLIB_OUTOFRANGE:
 207         jio_fprintf (stderr, "out of range\n");
 208         break;
 209     default:
 210         jio_fprintf (stderr, "medialib error\n");
 211         break;
 212     }
 213 }
 214 #else /* ! DEBUG */
 215 #  define printMedialibError(x)
 216 
 217 #endif /* ! DEBUG */
 218 
 219 static int
 220 getMlibEdgeHint(jint edgeHint) {
 221     switch (edgeHint) {
 222     case java_awt_image_ConvolveOp_EDGE_NO_OP:
 223         return MLIB_EDGE_DST_COPY_SRC;
 224     case java_awt_image_ConvolveOp_EDGE_ZERO_FILL:
 225     default:
 226         return MLIB_EDGE_DST_FILL_ZERO;
 227     }
 228 }
 229 
 230 /***************************************************************************
 231  *                          External Functions                             *
 232  ***************************************************************************/
 233 JNIEXPORT jint JNICALL
 234 Java_sun_awt_image_ImagingLib_convolveBI(JNIEnv *env, jobject this,
 235                                          jobject jsrc, jobject jdst,
 236                                          jobject jkernel, jint edgeHint)
 237 {
 238     void *sdata, *ddata;
 239     mlib_image *src;
 240     mlib_image *dst;
 241     int i, scale;
 242     mlib_d64 *dkern;
 243     mlib_s32 *kdata;
 244     int klen;
 245     float kmax;
 246     mlib_s32 cmask;
 247     mlib_status status;
 248     int retStatus = 1;
 249     float *kern;
 250     BufImageS_t *srcImageP, *dstImageP;
 251     jobject jdata;
 252     int kwidth;
 253     int kheight;
 254     int w, h;
 255     int x, y;
 256     mlibHintS_t hint;
 257     int nbands;
 258 
 259     /* This function requires a lot of local refs ??? Is 64 enough ??? */
 260     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
 261         return 0;
 262 
 263     if (s_nomlib) return 0;
 264     if (s_timeIt)     (*start_timer)(3600);
 265 
 266     kwidth  = (*env)->GetIntField(env, jkernel, g_KernelWidthID);
 267     kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID);
 268     jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID);
 269     klen  = (*env)->GetArrayLength(env, jdata);
 270     kern  = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
 271     if (kern == NULL) {
 272         /* out of memory exception already thrown */
 273         return 0;
 274     }
 275 
 276     if ((kwidth&0x1) == 0) {
 277         /* Kernel has even width */
 278         w = kwidth+1;
 279     }
 280     else {
 281         w = kwidth;
 282     }
 283     if ((kheight&0x1) == 0) {
 284         /* Kernel has even height */
 285         h = kheight+1;
 286     }
 287     else {
 288         h = kheight;
 289     }
 290 
 291     dkern = NULL;
 292     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) {
 293         dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64));
 294     }
 295     if (dkern == NULL) {
 296         (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
 297         return 0;
 298     }
 299 
 300     /* Need to flip and find max value of the kernel.
 301      * Also, save the kernel values as mlib_d64 values.
 302      * The flip is to operate correctly with medialib,
 303      * which doesn't do the mathemetically correct thing,
 304      * i.e. it doesn't rotate the kernel by 180 degrees.
 305      * REMIND: This should perhaps be done at the Java
 306      * level by ConvolveOp.
 307      * REMIND: Should the max test be looking at absolute
 308      * values?
 309      * REMIND: What if klen != kheight * kwidth?
 310      */
 311     kmax = kern[klen-1];
 312     i = klen-1;
 313     for (y=0; y < kheight; y++) {
 314         for (x=0; x < kwidth; x++, i--) {
 315             dkern[y*w+x] = (mlib_d64) kern[i];
 316             if (kern[i] > kmax) {
 317                 kmax = kern[i];
 318             }
 319         }
 320     }
 321 
 322     (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
 323 
 324     if (kmax > 1<<16) {
 325         /* We can only handle 16 bit max */
 326         free(dkern);
 327         return 0;
 328     }
 329 
 330 
 331     /* Parse the source image */
 332     if ((status = awt_parseImage(env, jsrc, &srcImageP, FALSE)) <= 0) {
 333         /* Can't handle any custom images */
 334         free(dkern);
 335         return 0;
 336     }
 337 
 338     /* Parse the destination image */
 339     if ((status = awt_parseImage(env, jdst, &dstImageP, FALSE)) <= 0) {
 340         /* Can't handle any custom images */
 341         awt_freeParsedImage(srcImageP, TRUE);
 342         free(dkern);
 343         return 0;
 344     }
 345 
 346     nbands = setImageHints(env, srcImageP, dstImageP, TRUE, TRUE,
 347                         FALSE, &hint);
 348     if (nbands < 1) {
 349         /* Can't handle any custom images */
 350         awt_freeParsedImage(srcImageP, TRUE);
 351         awt_freeParsedImage(dstImageP, TRUE);
 352         free(dkern);
 353         return 0;
 354     }
 355     /* Allocate the arrays */
 356     if (allocateArray(env, srcImageP, &src, &sdata, TRUE,
 357                       hint.cvtSrcToDefault, hint.addAlpha) < 0) {
 358         /* Must be some problem */
 359         awt_freeParsedImage(srcImageP, TRUE);
 360         awt_freeParsedImage(dstImageP, TRUE);
 361         free(dkern);
 362         return 0;
 363     }
 364     if (allocateArray(env, dstImageP, &dst, &ddata, FALSE,
 365                       hint.cvtToDst, FALSE) < 0) {
 366         /* Must be some problem */
 367         freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
 368         awt_freeParsedImage(srcImageP, TRUE);
 369         awt_freeParsedImage(dstImageP, TRUE);
 370         free(dkern);
 371         return 0;
 372     }
 373 
 374     kdata = NULL;
 375     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) {
 376         kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32));
 377     }
 378     if (kdata == NULL) {
 379         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
 380         awt_freeParsedImage(srcImageP, TRUE);
 381         awt_freeParsedImage(dstImageP, TRUE);
 382         free(dkern);
 383         return 0;
 384     }
 385 
 386     if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h,
 387                                     mlib_ImageGetType(src)) != MLIB_SUCCESS) {
 388         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
 389         awt_freeParsedImage(srcImageP, TRUE);
 390         awt_freeParsedImage(dstImageP, TRUE);
 391         free(dkern);
 392         free(kdata);
 393         return 0;
 394     }
 395 
 396     if (s_printIt) {
 397         fprintf(stderr, "Orig Kernel(len=%d):\n",klen);
 398         for (y=kheight-1; y >= 0; y--) {
 399             for (x=kwidth-1; x >= 0; x--) {
 400                 fprintf(stderr, "%g ", dkern[y*w+x]);
 401             }
 402             fprintf(stderr, "\n");
 403         }
 404         fprintf(stderr, "New Kernel(scale=%d):\n", scale);
 405         for (y=kheight-1; y >= 0; y--) {
 406             for (x=kwidth-1; x >= 0; x--) {
 407                 fprintf(stderr, "%d ", kdata[y*w+x]);
 408             }
 409             fprintf(stderr, "\n");
 410         }
 411     }
 412 
 413     cmask = (1<<src->channels)-1;
 414     status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
 415                                (w-1)/2, (h-1)/2, scale, cmask,
 416                                getMlibEdgeHint(edgeHint));
 417 
 418     if (status != MLIB_SUCCESS) {
 419         printMedialibError(status);
 420         retStatus = 0;
 421     }
 422 
 423     if (s_printIt) {
 424         unsigned int *dP;
 425         if (s_startOff != 0) {
 426             printf("Starting at %d\n", s_startOff);
 427         }
 428         if (sdata == NULL) {
 429             dP = (unsigned int *) mlib_ImageGetData(src);
 430         }
 431         else {
 432             dP = (unsigned int *) sdata;
 433         }
 434         printf("src is\n");
 435         for (i=0; i < 20; i++) {
 436             printf("%x ",dP[s_startOff+i]);
 437         }
 438         printf("\n");
 439         if (ddata == NULL) {
 440             dP = (unsigned int *)mlib_ImageGetData(dst);
 441         }
 442         else {
 443             dP = (unsigned int *) ddata;
 444         }
 445         printf("dst is \n");
 446         for (i=0; i < 20; i++) {
 447             printf("%x ",dP[s_startOff+i]);
 448         }
 449         printf("\n");
 450     }
 451 
 452     /* Means that we couldn't write directly into the destination buffer */
 453     if (ddata == NULL) {
 454 
 455         /* Need to store it back into the array */
 456         if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
 457             /* Error */
 458             retStatus = 0;
 459         }
 460     }
 461 
 462     /* Release the pinned memory */
 463     freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
 464     awt_freeParsedImage(srcImageP, TRUE);
 465     awt_freeParsedImage(dstImageP, TRUE);
 466     free(dkern);
 467     free(kdata);
 468 
 469     if (s_timeIt) (*stop_timer)(3600, 1);
 470 
 471     return retStatus;
 472 }
 473 
 474 JNIEXPORT jint JNICALL
 475 Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this,
 476                                              jobject jsrc, jobject jdst,
 477                                              jobject jkernel, jint edgeHint)
 478 {
 479     mlib_image *src;
 480     mlib_image *dst;
 481     int i, scale;
 482     mlib_d64 *dkern;
 483     mlib_s32 *kdata;
 484     int klen;
 485     float kmax;
 486     int retStatus = 1;
 487     mlib_status status;
 488     mlib_s32 cmask;
 489     void *sdata;
 490     void *ddata;
 491     RasterS_t *srcRasterP;
 492     RasterS_t *dstRasterP;
 493     int kwidth;
 494     int kheight;
 495     int w, h;
 496     int x, y;
 497     jobject jdata;
 498     float *kern;
 499 
 500     /* This function requires a lot of local refs ??? Is 64 enough ??? */
 501     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
 502         return 0;
 503 
 504     if (s_nomlib) return 0;
 505     if (s_timeIt)     (*start_timer)(3600);
 506 
 507     kwidth  = (*env)->GetIntField(env, jkernel, g_KernelWidthID);
 508     kheight = (*env)->GetIntField(env, jkernel, g_KernelHeightID);
 509     jdata = (*env)->GetObjectField(env, jkernel, g_KernelDataID);
 510     klen  = (*env)->GetArrayLength(env, jdata);
 511     kern  = (float *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
 512     if (kern == NULL) {
 513         /* out of memory exception already thrown */
 514         return 0;
 515     }
 516 
 517     if ((kwidth&0x1) == 0) {
 518         /* Kernel has even width */
 519         w = kwidth+1;
 520     }
 521     else {
 522         w = kwidth;
 523     }
 524     if ((kheight&0x1) == 0) {
 525         /* Kernel has even height */
 526         h = kheight+1;
 527     }
 528     else {
 529         h = kheight;
 530     }
 531 
 532     dkern = NULL;
 533     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_d64))) {
 534         dkern = (mlib_d64 *)calloc(1, w * h * sizeof(mlib_d64));
 535     }
 536     if (dkern == NULL) {
 537         (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
 538         return 0;
 539     }
 540 
 541     /* Need to flip and find max value of the kernel.
 542      * Also, save the kernel values as mlib_d64 values.
 543      * The flip is to operate correctly with medialib,
 544      * which doesn't do the mathemetically correct thing,
 545      * i.e. it doesn't rotate the kernel by 180 degrees.
 546      * REMIND: This should perhaps be done at the Java
 547      * level by ConvolveOp.
 548      * REMIND: Should the max test be looking at absolute
 549      * values?
 550      * REMIND: What if klen != kheight * kwidth?
 551      */
 552     kmax = kern[klen-1];
 553     i = klen-1;
 554     for (y=0; y < kheight; y++) {
 555         for (x=0; x < kwidth; x++, i--) {
 556             dkern[y*w+x] = (mlib_d64) kern[i];
 557             if (kern[i] > kmax) {
 558                 kmax = kern[i];
 559             }
 560         }
 561     }
 562 
 563     (*env)->ReleasePrimitiveArrayCritical(env, jdata, kern, JNI_ABORT);
 564 
 565     if (kmax > 1<<16) {
 566         /* We can only handle 16 bit max */
 567         free(dkern);
 568         return 0;
 569     }
 570 
 571     /* Parse the source image */
 572     if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
 573         JNU_ThrowOutOfMemoryError(env, "Out of memory");
 574         free(dkern);
 575         return -1;
 576     }
 577 
 578     if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
 579         JNU_ThrowOutOfMemoryError(env, "Out of memory");
 580         free(srcRasterP);
 581         free(dkern);
 582         return -1;
 583     }
 584 
 585     /* Parse the source raster */
 586     if ((status = awt_parseRaster(env, jsrc, srcRasterP)) <= 0) {
 587         /* Can't handle any custom rasters */
 588         free(srcRasterP);
 589         free(dstRasterP);
 590         free(dkern);
 591         return 0;
 592     }
 593 
 594     /* Parse the destination raster */
 595     if ((status = awt_parseRaster(env, jdst, dstRasterP)) <= 0) {
 596         /* Can't handle any custom images */
 597         awt_freeParsedRaster(srcRasterP, TRUE);
 598         free(dstRasterP);
 599         free(dkern);
 600         return 0;
 601     }
 602 
 603     /* Allocate the arrays */
 604     if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
 605         /* Must be some problem */
 606         awt_freeParsedRaster(srcRasterP, TRUE);
 607         awt_freeParsedRaster(dstRasterP, TRUE);
 608         free(dkern);
 609         return 0;
 610     }
 611     if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
 612         /* Must be some problem */
 613         freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
 614         awt_freeParsedRaster(srcRasterP, TRUE);
 615         awt_freeParsedRaster(dstRasterP, TRUE);
 616         free(dkern);
 617         return 0;
 618     }
 619 
 620     kdata = NULL;
 621     if (SAFE_TO_ALLOC_3(w, h, sizeof(mlib_s32))) {
 622         kdata = (mlib_s32 *)malloc(w * h * sizeof(mlib_s32));
 623     }
 624     if (kdata == NULL) {
 625         freeDataArray(env, srcRasterP->jdata, src, sdata,
 626                       dstRasterP->jdata, dst, ddata);
 627         awt_freeParsedRaster(srcRasterP, TRUE);
 628         awt_freeParsedRaster(dstRasterP, TRUE);
 629         free(dkern);
 630         return 0;
 631     }
 632 
 633     if ((*sMlibFns[MLIB_CONVKERNCVT].fptr)(kdata, &scale, dkern, w, h,
 634                                     mlib_ImageGetType(src)) != MLIB_SUCCESS) {
 635         freeDataArray(env, srcRasterP->jdata, src, sdata,
 636                       dstRasterP->jdata, dst, ddata);
 637         awt_freeParsedRaster(srcRasterP, TRUE);
 638         awt_freeParsedRaster(dstRasterP, TRUE);
 639         free(dkern);
 640         free(kdata);
 641         return 0;
 642     }
 643 
 644     if (s_printIt) {
 645         fprintf(stderr, "Orig Kernel(len=%d):\n",klen);
 646         for (y=kheight-1; y >= 0; y--) {
 647             for (x=kwidth-1; x >= 0; x--) {
 648                 fprintf(stderr, "%g ", dkern[y*w+x]);
 649             }
 650             fprintf(stderr, "\n");
 651         }
 652         fprintf(stderr, "New Kernel(scale=%d):\n", scale);
 653         for (y=kheight-1; y >= 0; y--) {
 654             for (x=kwidth-1; x >= 0; x--) {
 655                 fprintf(stderr, "%d ", kdata[y*w+x]);
 656             }
 657             fprintf(stderr, "\n");
 658         }
 659     }
 660 
 661     cmask = (1<<src->channels)-1;
 662     status = (*sMlibFns[MLIB_CONVMxN].fptr)(dst, src, kdata, w, h,
 663                                (w-1)/2, (h-1)/2, scale, cmask,
 664                                getMlibEdgeHint(edgeHint));
 665 
 666     if (status != MLIB_SUCCESS) {
 667         printMedialibError(status);
 668         retStatus = 0;
 669     }
 670 
 671     if (s_printIt) {
 672         unsigned int *dP;
 673         if (s_startOff != 0) {
 674             printf("Starting at %d\n", s_startOff);
 675         }
 676         if (sdata == NULL) {
 677             dP = (unsigned int *) mlib_ImageGetData(src);
 678         }
 679         else {
 680             dP = (unsigned int *) sdata;
 681         }
 682         printf("src is\n");
 683         for (i=0; i < 20; i++) {
 684             printf("%x ",dP[s_startOff+i]);
 685         }
 686         printf("\n");
 687         if (ddata == NULL) {
 688             dP = (unsigned int *)mlib_ImageGetData(dst);
 689         }
 690         else {
 691             dP = (unsigned int *) ddata;
 692         }
 693         printf("dst is\n");
 694         for (i=0; i < 20; i++) {
 695             printf("%x ",dP[s_startOff+i]);
 696         }
 697         printf("\n");
 698     }
 699 
 700     /* Means that we couldn't write directly into the destination buffer */
 701     if (ddata == NULL) {
 702         unsigned char *bdataP;
 703         unsigned short *sdataP;
 704 
 705         /* Punt for now */
 706         switch (dstRasterP->dataType) {
 707         case BYTE_DATA_TYPE:
 708             bdataP  = (unsigned char *) mlib_ImageGetData(dst);
 709             retStatus = (awt_setPixelByte(env, -1, dstRasterP, bdataP) >= 0) ;
 710             break;
 711         case SHORT_DATA_TYPE:
 712             sdataP  = (unsigned short *) mlib_ImageGetData(dst);
 713             retStatus = (awt_setPixelShort(env, -1, dstRasterP, sdataP) >= 0) ;
 714             break;
 715         default:
 716             retStatus = 0;
 717         }
 718     }
 719 
 720     /* Release the pinned memory */
 721     freeDataArray(env, srcRasterP->jdata, src, sdata,
 722                   dstRasterP->jdata, dst, ddata);
 723     awt_freeParsedRaster(srcRasterP, TRUE);
 724     awt_freeParsedRaster(dstRasterP, TRUE);
 725     free(dkern);
 726     free(kdata);
 727 
 728     if (s_timeIt) (*stop_timer)(3600,1);
 729 
 730     return retStatus;
 731 }
 732 
 733 
 734 JNIEXPORT jint JNICALL
 735 Java_sun_awt_image_ImagingLib_transformBI(JNIEnv *env, jobject this,
 736                                           jobject jsrc,
 737                                           jobject jdst,
 738                                           jdoubleArray jmatrix,
 739                                           jint interpType)
 740 {
 741     mlib_image *src;
 742     mlib_image *dst;
 743     int i;
 744     int retStatus = 1;
 745     mlib_status status;
 746     double *matrix;
 747     mlib_d64 mtx[6];
 748     void *sdata;
 749     void *ddata;
 750     BufImageS_t *srcImageP;
 751     BufImageS_t *dstImageP;
 752     mlib_filter filter;
 753     mlibHintS_t hint;
 754     unsigned int *dP;
 755     int useIndexed;
 756     int nbands;
 757 
 758     /* This function requires a lot of local refs ??? Is 64 enough ??? */
 759     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
 760         return 0;
 761 
 762     if (s_nomlib) return 0;
 763     if (s_timeIt) {
 764         (*start_timer)(3600);
 765     }
 766 
 767     switch(interpType) {
 768     case java_awt_image_AffineTransformOp_TYPE_BILINEAR:
 769         filter = MLIB_BILINEAR;
 770         break;
 771     case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR:
 772         filter = MLIB_NEAREST;
 773         break;
 774     case java_awt_image_AffineTransformOp_TYPE_BICUBIC:
 775         filter = MLIB_BICUBIC;
 776         break;
 777     default:
 778         JNU_ThrowInternalError(env, "Unknown interpolation type");
 779         return -1;
 780     }
 781 
 782     if ((*env)->GetArrayLength(env, jmatrix) < 6) {
 783         /*
 784          * Very unlikely, however we should check for this:
 785          * if given matrix array is too short, we can't handle it
 786          */
 787         return 0;
 788     }
 789 
 790     matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL);
 791     if (matrix == NULL) {
 792         /* out of memory error already thrown */
 793         return 0;
 794     }
 795 
 796     if (s_printIt) {
 797         printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
 798                matrix[2], matrix[3], matrix[4], matrix[5]);
 799     }
 800 
 801     mtx[0] = matrix[0];
 802     mtx[1] = matrix[2];
 803     mtx[2] = matrix[4];
 804     mtx[3] = matrix[1];
 805     mtx[4] = matrix[3];
 806     mtx[5] = matrix[5];
 807 
 808     (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
 809 
 810     /* Parse the source image */
 811     if ((status = awt_parseImage(env, jsrc, &srcImageP, FALSE)) <= 0) {
 812         /* Can't handle any custom images */
 813         return 0;
 814     }
 815 
 816     /* Parse the destination image */
 817     if ((status = awt_parseImage(env, jdst, &dstImageP, FALSE)) <= 0) {
 818         /* Can't handle any custom images */
 819         awt_freeParsedImage(srcImageP, TRUE);
 820         return 0;
 821     }
 822 
 823     /* REMIND!!  Can't assume that it is the same LUT!! */
 824     /* Fix 4213160, 4184283 */
 825     useIndexed = (srcImageP->cmodel.cmType == INDEX_CM_TYPE &&
 826                   dstImageP->cmodel.cmType == INDEX_CM_TYPE &&
 827                   srcImageP->raster.rasterType == dstImageP->raster.rasterType &&
 828                   srcImageP->raster.rasterType == COMPONENT_RASTER_TYPE);
 829 
 830     nbands = setImageHints(env, srcImageP, dstImageP, !useIndexed, TRUE,
 831                         FALSE, &hint);
 832     if (nbands < 1) {
 833         /* Can't handle any custom images */
 834         awt_freeParsedImage(srcImageP, TRUE);
 835         awt_freeParsedImage(dstImageP, TRUE);
 836         return 0;
 837     }
 838 
 839     /* Allocate the arrays */
 840     if (allocateArray(env, srcImageP, &src, &sdata, TRUE,
 841                       hint.cvtSrcToDefault, hint.addAlpha) < 0) {
 842         /* Must be some problem */
 843         awt_freeParsedImage(srcImageP, TRUE);
 844         awt_freeParsedImage(dstImageP, TRUE);
 845         return 0;
 846     }
 847     if (allocateArray(env, dstImageP, &dst, &ddata, FALSE,
 848                       hint.cvtToDst, FALSE) < 0) {
 849         /* Must be some problem */
 850         freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
 851         awt_freeParsedImage(srcImageP, TRUE);
 852         awt_freeParsedImage(dstImageP, TRUE);
 853         return 0;
 854     }
 855 #if 0
 856 fprintf(stderr,"Src----------------\n");
 857 fprintf(stderr,"Type : %d\n",src->type);
 858 fprintf(stderr,"Channels: %d\n",src->channels);
 859 fprintf(stderr,"Width   : %d\n",src->width);
 860 fprintf(stderr,"Height  : %d\n",src->height);
 861 fprintf(stderr,"Stride  : %d\n",src->stride);
 862 fprintf(stderr,"Flags   : %d\n",src->flags);
 863 
 864 fprintf(stderr,"Dst----------------\n");
 865 fprintf(stderr,"Type : %d\n",dst->type);
 866 fprintf(stderr,"Channels: %d\n",dst->channels);
 867 fprintf(stderr,"Width   : %d\n",dst->width);
 868 fprintf(stderr,"Height  : %d\n",dst->height);
 869 fprintf(stderr,"Stride  : %d\n",dst->stride);
 870 fprintf(stderr,"Flags   : %d\n",dst->flags);
 871 #endif
 872 
 873     if (dstImageP->cmodel.cmType == INDEX_CM_TYPE) {
 874         /* Need to clear the destination to the transparent pixel */
 875         unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);
 876 
 877         memset(cP, dstImageP->cmodel.transIdx,
 878                mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));
 879     }
 880     /* Perform the transformation */
 881     if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,
 882                                   MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))
 883     {
 884         printMedialibError(status);
 885         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
 886         awt_freeParsedImage(srcImageP, TRUE);
 887         awt_freeParsedImage(dstImageP, TRUE);
 888 
 889         return 0;
 890     }
 891 
 892     if (s_printIt) {
 893         if (sdata == NULL) {
 894             dP = (unsigned int *) mlib_ImageGetData(src);
 895         }
 896         else {
 897             dP = (unsigned int *) sdata;
 898         }
 899         printf("src is\n");
 900         for (i=0; i < 20; i++) {
 901             printf("%x ",dP[i]);
 902         }
 903         printf("\n");
 904         if (ddata == NULL) {
 905             dP = (unsigned int *)mlib_ImageGetData(dst);
 906         }
 907         else {
 908             dP = (unsigned int *) ddata;
 909         }
 910         printf("dst is\n");
 911         for (i=0; i < 20; i++) {
 912             printf("%x ",dP[i]);
 913         }
 914         printf("\n");
 915     }
 916 
 917     /* Means that we couldn't write directly into the destination buffer */
 918     if (ddata == NULL) {
 919         freeDataArray(env, srcImageP->raster.jdata, src, sdata,
 920                       NULL, NULL, NULL);
 921         /* Need to store it back into the array */
 922         if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
 923             /* Error */
 924             retStatus = 0;
 925         }
 926         freeDataArray(env, NULL, NULL, NULL, dstImageP->raster.jdata,
 927                       dst, ddata);
 928     }
 929     else {
 930         /* Release the pinned memory */
 931         freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
 932     }
 933 
 934     awt_freeParsedImage(srcImageP, TRUE);
 935     awt_freeParsedImage(dstImageP, TRUE);
 936 
 937     if (s_timeIt) (*stop_timer)(3600,1);
 938 
 939     return retStatus;
 940 }
 941 
 942 JNIEXPORT jint JNICALL
 943 Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv *env, jobject this,
 944                                               jobject jsrc,
 945                                               jobject jdst,
 946                                               jdoubleArray jmatrix,
 947                                               jint interpType)
 948 {
 949     mlib_image *src;
 950     mlib_image *dst;
 951     int i;
 952     int retStatus = 1;
 953     mlib_status status;
 954     double *matrix;
 955     mlib_d64 mtx[6];
 956     void *sdata;
 957     void *ddata;
 958     RasterS_t *srcRasterP;
 959     RasterS_t *dstRasterP;
 960     mlib_filter filter;
 961     unsigned int *dP;
 962 
 963     /* This function requires a lot of local refs ??? Is 64 enough ??? */
 964     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
 965         return 0;
 966 
 967     if (s_nomlib) return 0;
 968     if (s_timeIt) {
 969         (*start_timer)(3600);
 970     }
 971 
 972     switch(interpType) {
 973     case java_awt_image_AffineTransformOp_TYPE_BILINEAR:
 974         filter = MLIB_BILINEAR;
 975         break;
 976     case java_awt_image_AffineTransformOp_TYPE_NEAREST_NEIGHBOR:
 977         filter = MLIB_NEAREST;
 978         break;
 979     case java_awt_image_AffineTransformOp_TYPE_BICUBIC:
 980         filter = MLIB_BICUBIC;
 981         break;
 982     default:
 983         JNU_ThrowInternalError(env, "Unknown interpolation type");
 984         return -1;
 985     }
 986 
 987     if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
 988         JNU_ThrowOutOfMemoryError(env, "Out of memory");
 989         return -1;
 990     }
 991 
 992     if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
 993         JNU_ThrowOutOfMemoryError(env, "Out of memory");
 994         free(srcRasterP);
 995         return -1;
 996     }
 997 
 998     if ((*env)->GetArrayLength(env, jmatrix) < 6) {
 999         /*
1000          * Very unlikely, however we should check for this:
1001          * if given matrix array is too short, we can't handle it.
1002          */
1003         free(srcRasterP);
1004         free(dstRasterP);
1005         return 0;
1006     }
1007 
1008     matrix = (*env)->GetPrimitiveArrayCritical(env, jmatrix, NULL);
1009     if (matrix == NULL) {
1010         /* out of memory error already thrown */
1011         free(srcRasterP);
1012         free(dstRasterP);
1013         return 0;
1014     }
1015 
1016     if (s_printIt) {
1017         printf("matrix is %g %g %g %g %g %g\n", matrix[0], matrix[1],
1018                matrix[2], matrix[3], matrix[4], matrix[5]);
1019     }
1020 
1021     mtx[0] = matrix[0];
1022     mtx[1] = matrix[2];
1023     mtx[2] = matrix[4];
1024     mtx[3] = matrix[1];
1025     mtx[4] = matrix[3];
1026     mtx[5] = matrix[5];
1027 
1028     (*env)->ReleasePrimitiveArrayCritical(env, jmatrix, matrix, JNI_ABORT);
1029 
1030     /* Parse the source raster */
1031     if ((status = awt_parseRaster(env, jsrc, srcRasterP)) <= 0) {
1032         /* Can't handle any custom rasters */
1033         free(srcRasterP);
1034         free(dstRasterP);
1035         return 0;
1036     }
1037 
1038     /* Parse the destination raster */
1039     if ((status = awt_parseRaster(env, jdst, dstRasterP)) <= 0) {
1040         /* Can't handle any custom images */
1041         awt_freeParsedRaster(srcRasterP, TRUE);
1042         free(dstRasterP);
1043         return 0;
1044     }
1045 
1046     /* Allocate the arrays */
1047     if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
1048         /* Must be some problem */
1049         awt_freeParsedRaster(srcRasterP, TRUE);
1050         awt_freeParsedRaster(dstRasterP, TRUE);
1051         return 0;
1052     }
1053     if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
1054         /* Must be some problem */
1055         freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
1056         awt_freeParsedRaster(srcRasterP, TRUE);
1057         awt_freeParsedRaster(dstRasterP, TRUE);
1058         return 0;
1059     }
1060 
1061 #if 0
1062 fprintf(stderr,"Src----------------\n");
1063 fprintf(stderr,"Type : %d\n",src->type);
1064 fprintf(stderr,"Channels: %d\n",src->channels);
1065 fprintf(stderr,"Width   : %d\n",src->width);
1066 fprintf(stderr,"Height  : %d\n",src->height);
1067 fprintf(stderr,"Stride  : %d\n",src->stride);
1068 fprintf(stderr,"Flags   : %d\n",src->flags);
1069 
1070 fprintf(stderr,"Dst----------------\n");
1071 fprintf(stderr,"Type : %d\n",dst->type);
1072 fprintf(stderr,"Channels: %d\n",dst->channels);
1073 fprintf(stderr,"Width   : %d\n",dst->width);
1074 fprintf(stderr,"Height  : %d\n",dst->height);
1075 fprintf(stderr,"Stride  : %d\n",dst->stride);
1076 fprintf(stderr,"Flags   : %d\n",dst->flags);
1077 #endif
1078 
1079     {
1080         unsigned char *cP = (unsigned char *)mlib_ImageGetData(dst);
1081 
1082         memset(cP, 0, mlib_ImageGetWidth(dst)*mlib_ImageGetHeight(dst));
1083     }
1084 
1085     /* Perform the transformation */
1086     if ((status = (*sMlibFns[MLIB_AFFINE].fptr)(dst, src, mtx, filter,
1087                                   MLIB_EDGE_SRC_EXTEND) != MLIB_SUCCESS))
1088     {
1089         printMedialibError(status);
1090         /* REMIND: Free the regions */
1091         return 0;
1092     }
1093 
1094     if (s_printIt) {
1095         if (sdata == NULL) {
1096             dP = (unsigned int *) mlib_ImageGetData(src);
1097         }
1098         else {
1099             dP = (unsigned int *) sdata;
1100         }
1101         printf("src is\n");
1102         for (i=0; i < 20; i++) {
1103             printf("%x ",dP[i]);
1104         }
1105         printf("\n");
1106         if (ddata == NULL) {
1107             dP = (unsigned int *)mlib_ImageGetData(dst);
1108         }
1109         else {
1110             dP = (unsigned int *) ddata;
1111         }
1112         printf("dst is\n");
1113         for (i=0; i < 20; i++) {
1114             printf("%x ",dP[i]);
1115         }
1116         printf("\n");
1117     }
1118 
1119     /* Means that we couldn't write directly into the destination buffer */
1120     if (ddata == NULL) {
1121         unsigned char *bdataP;
1122         unsigned short *sdataP;
1123 
1124         /* Need to store it back into the array */
1125         if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) {
1126             /* Punt for now */
1127             switch (dst->type) {
1128             case MLIB_BYTE:
1129                 bdataP  = (unsigned char *) mlib_ImageGetData(dst);
1130                 retStatus = (awt_setPixelByte(env, -1, dstRasterP, bdataP) >= 0) ;
1131                 break;
1132             case MLIB_SHORT:
1133                 sdataP  = (unsigned short *) mlib_ImageGetData(dst);
1134                 retStatus = (awt_setPixelShort(env, -1, dstRasterP, sdataP) >= 0) ;
1135                 break;
1136             default:
1137                 retStatus = 0;
1138             }
1139         }
1140     }
1141 
1142     /* Release the pinned memory */
1143     freeDataArray(env, srcRasterP->jdata, src, sdata,
1144                   dstRasterP->jdata, dst, ddata);
1145 
1146     awt_freeParsedRaster(srcRasterP, TRUE);
1147     awt_freeParsedRaster(dstRasterP, TRUE);
1148 
1149     if (s_timeIt) (*stop_timer)(3600,1);
1150 
1151     return retStatus;
1152 }
1153 
1154 JNIEXPORT jint JNICALL
1155 Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject this,
1156                                            jobject jsrc, jobject jdst,
1157                                            jobjectArray jtableArrays)
1158 {
1159     mlib_image *src;
1160     mlib_image *dst;
1161     void *sdata, *ddata;
1162     unsigned char **table;
1163     unsigned char **tbl;
1164     unsigned char lut[256];
1165     int retStatus = 1;
1166     int i;
1167     mlib_status status;
1168     int jlen;
1169     jobject *jtable;
1170     BufImageS_t *srcImageP, *dstImageP;
1171     int nbands;
1172     int ncomponents;
1173     mlibHintS_t hint;
1174 
1175     /* This function requires a lot of local refs ??? Is 64 enough ??? */
1176     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1177         return 0;
1178 
1179     if (s_nomlib) return 0;
1180     if (s_timeIt) (*start_timer)(3600);
1181 
1182     /* Parse the source image */
1183     if ((status = awt_parseImage(env, jsrc, &srcImageP, FALSE)) <= 0) {
1184         /* Can't handle any custom images */
1185         return 0;
1186     }
1187 
1188     /* Parse the destination image */
1189     if ((status = awt_parseImage(env, jdst, &dstImageP, FALSE)) <= 0) {
1190         /* Can't handle any custom images */
1191         awt_freeParsedImage(srcImageP, TRUE);
1192         return 0;
1193     }
1194 
1195     jlen = (*env)->GetArrayLength(env, jtableArrays);
1196 
1197     ncomponents = srcImageP->cmodel.isDefaultCompatCM
1198         ? 4
1199         : srcImageP->cmodel.numComponents;
1200 
1201     tbl = NULL;
1202     if (SAFE_TO_ALLOC_2(ncomponents, sizeof(unsigned char *))) {
1203         tbl = (unsigned char **)
1204             calloc(1, ncomponents * sizeof(unsigned char *));
1205     }
1206 
1207     jtable = NULL;
1208     if (SAFE_TO_ALLOC_2(jlen, sizeof(jobject *))) {
1209         jtable = (jobject *)malloc(jlen * sizeof (jobject *));
1210     }
1211 
1212     table = NULL;
1213     if (SAFE_TO_ALLOC_2(jlen, sizeof(unsigned char *))) {
1214         table = (unsigned char **)malloc(jlen * sizeof(unsigned char *));
1215     }
1216 
1217     if (tbl == NULL || table == NULL || jtable == NULL) {
1218         if (tbl != NULL) free(tbl);
1219         if (table != NULL) free(table);
1220         if (jtable != NULL) free(jtable);
1221         awt_freeParsedImage(srcImageP, TRUE);
1222         awt_freeParsedImage(dstImageP, TRUE);
1223         JNU_ThrowNullPointerException(env, "NULL LUT");
1224         return 0;
1225     }
1226     /* Need to grab these pointers before we lock down arrays */
1227     for (i=0; i < jlen; i++) {
1228         jtable[i] = (*env)->GetObjectArrayElement(env, jtableArrays, i);
1229         if (jtable[i] == NULL) {
1230             free(tbl);
1231             free(table);
1232             free(jtable);
1233             awt_freeParsedImage(srcImageP, TRUE);
1234             awt_freeParsedImage(dstImageP, TRUE);
1235             return 0;
1236         }
1237     }
1238 
1239     nbands = setImageHints(env, srcImageP, dstImageP, FALSE, TRUE,
1240                         FALSE, &hint);
1241     if (nbands < 1) {
1242         /* Can't handle any custom images */
1243         free(tbl);
1244         free(table);
1245         free(jtable);
1246         awt_freeParsedImage(srcImageP, TRUE);
1247         awt_freeParsedImage(dstImageP, TRUE);
1248         return 0;
1249     }
1250 
1251     /* Allocate the arrays */
1252     if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) {
1253         /* Must be some problem */
1254         free(tbl);
1255         free(table);
1256         free(jtable);
1257         awt_freeParsedImage(srcImageP, TRUE);
1258         awt_freeParsedImage(dstImageP, TRUE);
1259         return 0;
1260     }
1261     if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) {
1262         /* Must be some problem */
1263         free(tbl);
1264         free(table);
1265         free(jtable);
1266         freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
1267         awt_freeParsedImage(srcImageP, TRUE);
1268         awt_freeParsedImage(dstImageP, TRUE);
1269         return 0;
1270     }
1271 
1272     /* Set up a straight lut so we don't mess around with alpha */
1273     /*
1274      * NB: medialib lookup routine expects lookup array for each
1275      * component of source image including alpha.
1276      * If lookup table we got form the java layer does not contain
1277      * sufficient number of lookup arrays we add references to identity
1278      * lookup array to make medialib happier.
1279      */
1280     if (jlen < ncomponents) {
1281         int j;
1282         /* REMIND: This should be the size of the input lut!! */
1283         for (j=0; j < 256; j++) {
1284             lut[j] = j;
1285         }
1286         for (j=0; j < ncomponents; j++) {
1287             tbl[j] = lut;
1288         }
1289 
1290     }
1291 
1292     for (i=0; i < jlen; i++) {
1293         table[i] = (unsigned char *)
1294             (*env)->GetPrimitiveArrayCritical(env, jtable[i], NULL);
1295         if (table[i] == NULL) {
1296             /* Free what we've got so far. */
1297             int j;
1298             for (j = 0; j < i; j++) {
1299                 (*env)->ReleasePrimitiveArrayCritical(env,
1300                                                       jtable[j],
1301                                                       (jbyte *) table[j],
1302                                                       JNI_ABORT);
1303             }
1304             free(tbl);
1305             free(table);
1306             free(jtable);
1307             freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
1308             awt_freeParsedImage(srcImageP, TRUE);
1309             awt_freeParsedImage(dstImageP, TRUE);
1310             return 0;
1311         }
1312         tbl[srcImageP->hints.colorOrder[i]] = table[i];
1313     }
1314 
1315     if (jlen == 1) {
1316         for (i=1; i < nbands -
1317                  srcImageP->cmodel.supportsAlpha; i++) {
1318             tbl[srcImageP->hints.colorOrder[i]] = table[0];
1319         }
1320     }
1321 
1322     /* Mlib needs 16bit lookuptable and must be signed! */
1323     if (src->type == MLIB_SHORT) {
1324         unsigned short *sdataP = (unsigned short *) src->data;
1325         unsigned short *sP;
1326         if (dst->type == MLIB_BYTE) {
1327             unsigned char *cdataP  = (unsigned char *)  dst->data;
1328             unsigned char *cP;
1329             if (nbands > 1) {
1330                 retStatus = 0;
1331             }
1332             else {
1333                 int x, y;
1334                 for (y=0; y < src->height; y++) {
1335                     cP = cdataP;
1336                     sP = sdataP;
1337                     for (x=0; x < src->width; x++) {
1338                         *cP++ = table[0][*sP++];
1339                     }
1340 
1341                     /*
1342                      * 4554571: increment pointers using the scanline stride
1343                      * in pixel units (not byte units)
1344                      */
1345                     cdataP += dstImageP->raster.scanlineStride;
1346                     sdataP += srcImageP->raster.scanlineStride;
1347                 }
1348             }
1349         }
1350         /* How about ddata == null? */
1351     }
1352     else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,
1353                                       (void **)tbl) != MLIB_SUCCESS)) {
1354         printMedialibError(status);
1355         retStatus = 0;
1356     }
1357 
1358     /*
1359      * Means that we couldn't write directly into
1360      * the destination buffer
1361      */
1362     if (ddata == NULL) {
1363 
1364         /* Need to store it back into the array */
1365         if (storeImageArray(env, srcImageP, dstImageP, dst) < 0) {
1366             /* Error */
1367             retStatus = 0;
1368         }
1369     }
1370 
1371     /* Release the LUT */
1372     for (i=0; i < jlen; i++) {
1373         (*env)->ReleasePrimitiveArrayCritical(env, jtable[i],
1374                                               (jbyte *) table[i], JNI_ABORT);
1375     }
1376     free ((void *) jtable);
1377     free ((void *) table);
1378     free ((void *) tbl);
1379 
1380     /* Release the pinned memory */
1381     freeArray(env, srcImageP, src, sdata, dstImageP, dst, ddata);
1382 
1383     awt_freeParsedImage(srcImageP, TRUE);
1384     awt_freeParsedImage(dstImageP, TRUE);
1385 
1386     if (s_timeIt) (*stop_timer)(3600, 1);
1387 
1388     return retStatus;
1389 }
1390 
1391 
1392 JNIEXPORT jint JNICALL
1393 Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env,
1394                                                jobject this,
1395                                                jobject jsrc,
1396                                                jobject jdst,
1397                                                jobjectArray jtableArrays)
1398 {
1399     RasterS_t*     srcRasterP;
1400     RasterS_t*     dstRasterP;
1401     mlib_image*    src;
1402     mlib_image*    dst;
1403     void*          sdata;
1404     void*          ddata;
1405     jobject        jtable[4];
1406     unsigned char* table[4];
1407     int            i;
1408     int            retStatus = 1;
1409     mlib_status    status;
1410     int            jlen;
1411     int            lut_nbands;
1412     int            src_nbands;
1413     int            dst_nbands;
1414     unsigned char  ilut[256];
1415 
1416     /* This function requires a lot of local refs ??? Is 64 enough ??? */
1417     if ((*env)->EnsureLocalCapacity(env, 64) < 0)
1418         return 0;
1419 
1420     if (s_nomlib) return 0;
1421     if (s_timeIt) (*start_timer)(3600);
1422 
1423     if ((srcRasterP = (RasterS_t*) calloc(1, sizeof(RasterS_t))) == NULL) {
1424         JNU_ThrowOutOfMemoryError(env, "Out of memory");
1425         return -1;
1426     }
1427 
1428     if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
1429         JNU_ThrowOutOfMemoryError(env, "Out of memory");
1430         free(srcRasterP);
1431         return -1;
1432     }
1433 
1434     /* Parse the source raster - reject custom images */
1435     if ((status = awt_parseRaster(env, jsrc, srcRasterP)) <= 0) {
1436         free(srcRasterP);
1437         free(dstRasterP);
1438         return 0;
1439     }
1440 
1441     /* Parse the destination image - reject custom images */
1442     if ((status = awt_parseRaster(env, jdst, dstRasterP)) <= 0) {
1443         awt_freeParsedRaster(srcRasterP, TRUE);
1444         free(dstRasterP);
1445         return 0;
1446     }
1447 
1448     jlen = (*env)->GetArrayLength(env, jtableArrays);
1449 
1450     lut_nbands = jlen;
1451     src_nbands = srcRasterP->numBands;
1452     dst_nbands = dstRasterP->numBands;
1453 
1454     /* MediaLib can't do more than 4 bands */
1455     if (src_nbands <= 0 || src_nbands > 4 ||
1456         dst_nbands <= 0 || dst_nbands > 4 ||
1457         lut_nbands <= 0 || lut_nbands > 4 ||
1458         src_nbands != dst_nbands ||
1459         ((lut_nbands != 1) && (lut_nbands != src_nbands)))
1460     {
1461         // we should free parsed rasters here
1462         awt_freeParsedRaster(srcRasterP, TRUE);
1463         awt_freeParsedRaster(dstRasterP, TRUE);
1464         return 0;
1465     }
1466 
1467     /* Allocate the raster arrays */
1468     if (allocateRasterArray(env, srcRasterP, &src, &sdata, TRUE) < 0) {
1469         /* Must be some problem */
1470         awt_freeParsedRaster(srcRasterP, TRUE);
1471         awt_freeParsedRaster(dstRasterP, TRUE);
1472         return 0;
1473     }
1474     if (allocateRasterArray(env, dstRasterP, &dst, &ddata, FALSE) < 0) {
1475         /* Must be some problem */
1476         freeDataArray(env, srcRasterP->jdata, src, sdata, NULL, NULL, NULL);
1477         awt_freeParsedRaster(srcRasterP, TRUE);
1478         awt_freeParsedRaster(dstRasterP, TRUE);
1479         return 0;
1480     }
1481 
1482     /*
1483      * Well, until now we have analyzed number of bands in
1484      * src and dst rasters.
1485      * However, it is not enough because medialib lookup routine uses
1486      * number of channels of medialib image. Note that in certain
1487      * case number of channels may differs form the number of bands.
1488      * Good example is raster that is used in TYPE_INT_RGB buffered
1489      * image: it has 3 bands, but their medialib representation has
1490      * 4 channels.
1491      *
1492      * In order to avoid the lookup routine failure, we need:
1493      *
1494      * 1. verify that src and dst have same number of channels.
1495      * 2. provide lookup array for every channel. If we have "extra"
1496      *    channel (like the raster described above) then we need to
1497      *    provide identical lookup array.
1498      */
1499     if (src->channels != dst->channels) {
1500         freeDataArray(env, srcRasterP->jdata, src, sdata,
1501                       dstRasterP->jdata, dst, ddata);
1502 
1503         awt_freeParsedRaster(srcRasterP, TRUE);
1504         awt_freeParsedRaster(dstRasterP, TRUE);
1505         return 0;
1506     }
1507 
1508     if (src_nbands < src->channels) {
1509         for (i = 0; i < 256; i++) {
1510             ilut[i] = i;
1511         }
1512     }
1513 
1514 
1515     /* Get references to the lookup table arrays */
1516     /* Need to grab these pointers before we lock down arrays */
1517     for (i=0; i < lut_nbands; i++) {
1518         jtable[i] = (*env)->GetObjectArrayElement(env, jtableArrays, i);
1519         if (jtable[i] == NULL) {
1520             return 0;
1521         }
1522     }
1523 
1524     for (i=0; i < lut_nbands; i++) {
1525         table[i] = (unsigned char *)
1526             (*env)->GetPrimitiveArrayCritical(env, jtable[i], NULL);
1527         if (table[i] == NULL) {
1528             /* Free what we've got so far. */
1529             int j;
1530             for (j = 0; j < i; j++) {
1531                 (*env)->ReleasePrimitiveArrayCritical(env,
1532                                                       jtable[j],
1533                                                       (jbyte *) table[j],
1534                                                       JNI_ABORT);
1535             }
1536             freeDataArray(env, srcRasterP->jdata, src, sdata,
1537                           dstRasterP->jdata, dst, ddata);
1538             awt_freeParsedRaster(srcRasterP, TRUE);
1539             awt_freeParsedRaster(dstRasterP, TRUE);
1540             return 0;
1541         }
1542     }
1543 
1544     /*
1545      * Medialib routine expects lookup array for each band of raster.
1546      * Setup the  rest of lookup arrays if supplied lookup table
1547      * contains single lookup array.
1548      */
1549     for (i = lut_nbands; i < src_nbands; i++) {
1550         table[i] = table[0];
1551     }
1552 
1553     /*
1554      * Setup lookup array for "extra" channels
1555      */
1556     for ( ; i < src->channels; i++) {
1557         table[i] = ilut;
1558     }
1559 
1560 #define NLUT 8
1561     /* Mlib needs 16bit lookuptable and must be signed! */
1562     if (src->type == MLIB_SHORT) {
1563         unsigned short *sdataP = (unsigned short *) src->data;
1564         unsigned short *sP;
1565         if (dst->type == MLIB_BYTE) {
1566             unsigned char *cdataP  = (unsigned char *)  dst->data;
1567             unsigned char *cP;
1568             if (lut_nbands > 1) {
1569                 retStatus = 0;
1570             } else {
1571                 int x, y;
1572                 unsigned int mask = NLUT-1;
1573                 unsigned char* pLut = table[0];
1574                 unsigned int endianTest = 0xff000000;
1575                 for (y=0; y < src->height; y++) {
1576                     int nloop, nx;
1577                     unsigned short* srcP;
1578                     int* dstP;
1579                     int npix = src->width;
1580                     cP = cdataP;
1581                     sP = sdataP;
1582                     /* Get to 32 bit-aligned point */
1583                     while(((uintptr_t)cP & 0x3) != 0 && npix>0) {
1584                           *cP++ = pLut[*sP++];
1585                           npix--;
1586                     }
1587 
1588                     /*
1589                      * Do NLUT pixels per loop iteration.
1590                      * Pack into ints and write out 2 at a time.
1591                      */
1592                     nloop = npix/NLUT;
1593                     nx = npix%NLUT;
1594                     srcP = sP;
1595                     dstP = (int*)cP;
1596 
1597                     if(((char*)(&endianTest))[0] != 0) {
1598                         /* Big endian loop */
1599                         for(x=nloop; x!=0; x--) {
1600                             dstP[0] = (int)
1601                                     ((pLut[srcP[0]] << 24) |
1602                                      (pLut[srcP[1]] << 16) |
1603                                      (pLut[srcP[2]] << 8)  |
1604                                       pLut[srcP[3]]);
1605                             dstP[1] = (int)
1606                                     ((pLut[srcP[4]] << 24) |
1607                                      (pLut[srcP[5]] << 16) |
1608                                      (pLut[srcP[6]] << 8)  |
1609                                       pLut[srcP[7]]);
1610                             dstP += NLUT/4;
1611                             srcP += NLUT;
1612                         }
1613                     } else {
1614                         /* Little endian loop */
1615                         for(x=nloop; x!=0; x--) {
1616                             dstP[0] = (int)
1617                                     ((pLut[srcP[3]] << 24) |
1618                                      (pLut[srcP[2]] << 16) |
1619                                      (pLut[srcP[1]] << 8)  |
1620                                       pLut[srcP[0]]);
1621                             dstP[1] = (int)
1622                                     ((pLut[srcP[7]] << 24) |
1623                                      (pLut[srcP[6]] << 16) |
1624                                      (pLut[srcP[5]] << 8)  |
1625                                       pLut[srcP[4]]);
1626                             dstP += NLUT/4;
1627                             srcP += NLUT;
1628                         }
1629                     }
1630                     /*
1631                      * Complete any remaining pixels
1632                      */
1633                     cP = cP + NLUT * nloop;
1634                     sP = sP + NLUT * nloop;
1635                     for(x=nx; x!=0; x--) {
1636                         *cP++ = pLut[*sP++];
1637                     }
1638 
1639                     /*
1640                      * 4554571: increment pointers using the scanline stride
1641                      * in pixel units (not byte units)
1642                      */
1643                     cdataP += dstRasterP->scanlineStride;
1644                     sdataP += srcRasterP->scanlineStride;
1645                 }
1646             }
1647         }
1648         /* How about ddata == null? */
1649     } else if ((status = (*sMlibFns[MLIB_LOOKUP].fptr)(dst, src,
1650                                       (void **)table) != MLIB_SUCCESS)) {
1651         printMedialibError(status);
1652         retStatus = 0;
1653     }
1654 
1655     /*
1656      * Means that we couldn't write directly into
1657      * the destination buffer
1658      */
1659     if (ddata == NULL) {
1660         unsigned char*  bdataP;
1661         unsigned short* sdataP;
1662 
1663         switch (dstRasterP->dataType) {
1664           case BYTE_DATA_TYPE:
1665             bdataP  = (unsigned char *) mlib_ImageGetData(dst);
1666             retStatus = (awt_setPixelByte(env, -1, dstRasterP, bdataP) >= 0) ;
1667             break;
1668           case SHORT_DATA_TYPE:
1669             sdataP  = (unsigned short *) mlib_ImageGetData(dst);
1670             retStatus = (awt_setPixelShort(env, -1, dstRasterP, sdataP) >= 0) ;
1671             break;
1672           default:
1673             retStatus = 0;
1674         }
1675     }
1676 
1677     /* Release the LUT */
1678     for (i=0; i < lut_nbands; i++) {
1679         (*env)->ReleasePrimitiveArrayCritical(env, jtable[i],
1680                                               (jbyte *) table[i], JNI_ABORT);
1681     }
1682 
1683     /* Release the pinned memory */
1684     freeDataArray(env, srcRasterP->jdata, src, sdata,
1685                   dstRasterP->jdata, dst, ddata);
1686 
1687     awt_freeParsedRaster(srcRasterP, TRUE);
1688     awt_freeParsedRaster(dstRasterP, TRUE);
1689 
1690     if (s_timeIt) (*stop_timer)(3600, 1);
1691 
1692     return retStatus;
1693 }
1694 
1695 
1696 JNIEXPORT jboolean JNICALL
1697 Java_sun_awt_image_ImagingLib_init(JNIEnv *env, jclass thisClass) {
1698     char *start;
1699     if (getenv("IMLIB_DEBUG")) {
1700         start_timer = awt_setMlibStartTimer();
1701         stop_timer = awt_setMlibStopTimer();
1702         if (start_timer && stop_timer) {
1703             s_timeIt = 1;
1704         }
1705     }
1706 
1707     if (getenv("IMLIB_PRINT")) {
1708         s_printIt = 1;
1709     }
1710     if ((start = getenv("IMLIB_START")) != NULL) {
1711         sscanf(start, "%d", &s_startOff);
1712     }
1713 
1714     if (getenv ("IMLIB_NOMLIB")) {
1715         s_nomlib = 1;
1716         return JNI_FALSE;
1717     }
1718 
1719     /* This function is platform-dependent and is in awt_mlib.c */
1720     if (awt_getImagingLib(env, (mlibFnS_t *)&sMlibFns, &sMlibSysFns) !=
1721         MLIB_SUCCESS)
1722     {
1723         s_nomlib = 1;
1724         return JNI_FALSE;
1725     }
1726     return JNI_TRUE;
1727 }
1728 
1729 /* REMIND: How to specify border? */
1730 static void extendEdge(JNIEnv *env, BufImageS_t *imageP,
1731                        int *widthP, int *heightP) {
1732     RasterS_t *rasterP = &imageP->raster;
1733     int width;
1734     int height;
1735     /* Useful for convolution? */
1736 
1737     jobject jbaseraster = (*env)->GetObjectField(env, rasterP->jraster,
1738                                                  g_RasterBaseRasterID);
1739     width = rasterP->width;
1740     height = rasterP->height;
1741 #ifdef WORKING
1742     if (! JNU_IsNull(env, jbaseraster) &&
1743         !(*env)->IsSameObject(env, rasterP->jraster, jbaseraster)) {
1744         int xOff;
1745         int yOff;
1746         int baseWidth;
1747         int baseHeight;
1748         int baseXoff;
1749         int baseYoff;
1750         /* Not the same object so get the width and height */
1751         xOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterXOffsetID);
1752         yOff = (*env)->GetIntField(env, rasterP->jraster, g_RasterYOffsetID);
1753         baseWidth  = (*env)->GetIntField(env, jbaseraster, g_RasterWidthID);
1754         baseHeight = (*env)->GetIntField(env, jbaseraster, g_RasterHeightID);
1755         baseXoff   = (*env)->GetIntField(env, jbaseraster, g_RasterXOffsetID);
1756         baseYoff   = (*env)->GetIntField(env, jbaseraster, g_RasterYOffsetID);
1757 
1758         if (xOff + rasterP->width < baseXoff + baseWidth) {
1759             /* Can use edge */
1760             width++;
1761         }
1762         if (yOff + rasterP->height < baseYoff + baseHeight) {
1763             /* Can use edge */
1764             height++;
1765         }
1766 
1767     }
1768 #endif
1769 
1770 }
1771 
1772 static int
1773 setImageHints(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
1774               int expandICM, int useAlpha,
1775               int premultiply, mlibHintS_t *hintP)
1776 {
1777     ColorModelS_t *srcCMP = &srcP->cmodel;
1778     ColorModelS_t *dstCMP = &dstP->cmodel;
1779     int nbands = 0;
1780     int ncomponents;
1781 
1782     hintP->dataType = srcP->raster.dataType;
1783     hintP->addAlpha = FALSE;
1784 
1785     /* Are the color spaces the same? */
1786     if (srcCMP->csType != dstCMP->csType) {
1787         /* If the src is GRAY and dst RGB, we can handle it */
1788         if (!(srcCMP->csType == java_awt_color_ColorSpace_TYPE_GRAY &&
1789               dstCMP->csType == java_awt_color_ColorSpace_TYPE_RGB)) {
1790             /* Nope, need to handle that in java for now */
1791             return -1;
1792         }
1793         else {
1794             hintP->cvtSrcToDefault = TRUE;
1795         }
1796     }
1797     else {
1798         if (srcP->hints.needToExpand) {
1799             hintP->cvtSrcToDefault = TRUE;
1800         }
1801         else {
1802             /* Need to initialize this */
1803             hintP->cvtSrcToDefault = FALSE;
1804         }
1805     }
1806 
1807     ncomponents = srcCMP->numComponents;
1808     if ((useAlpha == 0) && srcCMP->supportsAlpha) {
1809         ncomponents--;  /* ?? */
1810         /* Not really, more like shrink src to get rid of alpha */
1811         hintP->cvtSrcToDefault = TRUE;
1812     }
1813 
1814     hintP->dataType = srcP->raster.dataType;
1815     if (hintP->cvtSrcToDefault == FALSE) {
1816         if (srcCMP->cmType == INDEX_CM_TYPE) {
1817             if (expandICM) {
1818                 nbands = srcCMP->numComponents;
1819                 hintP->cvtSrcToDefault = TRUE;
1820 
1821                 if (dstCMP->isDefaultCompatCM) {
1822                     hintP->allocDefaultDst = FALSE;
1823                     hintP->cvtToDst = FALSE;
1824                 }
1825                 else if (dstCMP->isDefaultCompatCM) {
1826                     hintP->allocDefaultDst = FALSE;
1827                     hintP->cvtToDst = FALSE;
1828                 }
1829             }
1830             else {
1831                 nbands = 1;
1832                 hintP->cvtSrcToDefault = FALSE;
1833             }
1834 
1835         }
1836         else {
1837             if (srcP->hints.packing & INTERLEAVED) {
1838                 nbands = srcCMP->numComponents;
1839             }
1840             else {
1841                 nbands = 1;
1842             }
1843 
1844             /* Look at the packing */
1845             if ((srcP->hints.packing&BYTE_INTERLEAVED)==BYTE_INTERLEAVED ||
1846                 (srcP->hints.packing&SHORT_INTERLEAVED)==SHORT_INTERLEAVED||
1847                 (srcP->hints.packing&BYTE_SINGLE_BAND) == BYTE_SINGLE_BAND||
1848                 (srcP->hints.packing&SHORT_SINGLE_BAND)==SHORT_SINGLE_BAND||
1849                 (srcP->hints.packing&BYTE_BANDED)  == BYTE_BANDED       ||
1850                 (srcP->hints.packing&SHORT_BANDED) == SHORT_BANDED) {
1851                 /* Can use src directly */
1852                 hintP->cvtSrcToDefault = FALSE;
1853             }
1854             else {
1855                 /* Must be packed or custom */
1856                 hintP->cvtSrcToDefault = TRUE;
1857             }
1858         }
1859     }
1860     if (hintP->cvtSrcToDefault) {
1861         /* By definition */
1862         nbands = 4;  /* What about alpha? */
1863         hintP->dataType = BYTE_DATA_TYPE;
1864         hintP->needToCopy = TRUE;
1865 
1866         if (srcP->imageType == dstP->imageType) {
1867             hintP->cvtToDst = TRUE;
1868         }
1869         else if (dstP->cmodel.isDefaultCM) {
1870             /* Not necessarily */
1871             hintP->cvtToDst = FALSE;
1872         }
1873         else {
1874             hintP->cvtToDst = TRUE;
1875         }
1876     }
1877     else {
1878         int srcImageType = srcP->imageType;
1879         int dstImageType = dstP->imageType;
1880         /* Special case where we need to fill in alpha values */
1881         if (srcCMP->isDefaultCompatCM && dstCMP->isDefaultCompatCM) {
1882             int i;
1883             if (!srcCMP->supportsAlpha &&dstCMP->supportsAlpha) {
1884                 hintP->addAlpha = TRUE;
1885             }
1886             for (i=0; i < srcCMP->numComponents; i++) {
1887                 if (srcP->hints.colorOrder[i] != dstP->hints.colorOrder[i]){
1888                     if (!srcCMP->isDefaultCM) {
1889                         hintP->cvtSrcToDefault = TRUE;
1890                         srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1891                     }
1892                     if (!dstCMP->isDefaultCM) {
1893                         hintP->cvtToDst = TRUE;
1894                         dstImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1895                     }
1896 
1897                     break;
1898                 }
1899             }
1900         }
1901         else if (srcCMP->cmType != INDEX_CM_TYPE &&
1902                  !srcCMP->supportsAlpha && dstCMP->supportsAlpha)
1903         {
1904             /* We've already handled the index case.  This is for the rest of the cases */
1905             srcImageType = java_awt_image_BufferedImage_TYPE_INT_ARGB;
1906             hintP->cvtSrcToDefault = TRUE;
1907         }
1908 
1909         hintP->allocDefaultDst = FALSE;
1910         if (srcImageType == dstImageType) {
1911             /* Same image type so use it */
1912             hintP->cvtToDst = FALSE;
1913         }
1914         else if (srcImageType == TYPE_INT_RGB &&
1915                  (dstImageType == TYPE_INT_ARGB ||
1916                   dstImageType == TYPE_INT_ARGB_PRE)) {
1917             hintP->cvtToDst = FALSE;
1918         }
1919         else if (srcImageType == TYPE_INT_BGR &&
1920                  (dstImageType == TYPE_4BYTE_ABGR ||
1921                   dstImageType == TYPE_4BYTE_ABGR_PRE)) {
1922             hintP->cvtToDst = FALSE;
1923         }
1924         else if (srcP->hints.packing == dstP->hints.packing) {
1925             /* Now what? */
1926 
1927             /* Check color order */
1928 
1929             /* Check if just need to scale the data */
1930 
1931             hintP->cvtToDst = TRUE;
1932         }
1933         else {
1934             /* Don't know what it is so convert it */
1935             hintP->allocDefaultDst = TRUE;
1936             hintP->cvtToDst = TRUE;
1937         }
1938         hintP->needToCopy = (ncomponents > nbands);
1939     }
1940 
1941     return nbands;
1942 }
1943 
1944 
1945 static int
1946 expandPacked(JNIEnv *env, BufImageS_t *img, ColorModelS_t *cmP,
1947              RasterS_t *rasterP, int component, unsigned char *bdataP) {
1948 
1949     if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {
1950         switch (rasterP->dataType) {
1951         case BYTE_DATA_TYPE:
1952             if (expandPackedBCR(env, rasterP, component, bdataP) < 0) {
1953                 /* Must have been an error */
1954                 return -1;
1955             }
1956             break;
1957 
1958         case SHORT_DATA_TYPE:
1959             if (expandPackedICR(env, rasterP, component, bdataP) < 0) {
1960                 /* Must have been an error */
1961                 return -1;
1962             }
1963             break;
1964 
1965         case INT_DATA_TYPE:
1966             if (expandPackedICR(env, rasterP, component, bdataP) < 0) {
1967                 /* Must have been an error */
1968                 return -1;
1969             }
1970             break;
1971 
1972         default:
1973             /* REMIND: Return some sort of error */
1974             return -1;
1975         }
1976     }
1977     else {
1978         /* REMIND: Return some sort of error */
1979         return -1;
1980     }
1981 
1982     return 0;
1983 }
1984 
1985 static int
1986 cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,
1987                    unsigned char *dataP) {
1988     ColorModelS_t *cmP = &imageP->cmodel;
1989     RasterS_t *rasterP = &imageP->raster;
1990     int y;
1991     jobject jpixels = NULL;
1992     jint *pixels;
1993     unsigned char *dP = dataP;
1994 #define NUM_LINES    10
1995     int numLines = NUM_LINES;
1996     int nbytes = rasterP->width*4*NUM_LINES;
1997 
1998     for (y=0; y < rasterP->height; y+=numLines) {
1999         /* getData, one scanline at a time */
2000         if (y+numLines > rasterP->height) {
2001             numLines = rasterP->height - y;
2002             nbytes = rasterP->width*4*numLines;
2003         }
2004         jpixels = (*env)->CallObjectMethod(env, imageP->jimage,
2005                                            g_BImgGetRGBMID, 0, y,
2006                                            rasterP->width, numLines,
2007                                            jpixels,0, rasterP->width);
2008         if (jpixels == NULL) {
2009             JNU_ThrowInternalError(env, "Can't retrieve pixels.");
2010             return -1;
2011         }
2012 
2013         pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);
2014         memcpy(dP, pixels, nbytes);
2015         dP += nbytes;
2016         (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels,
2017                                               JNI_ABORT);
2018     }
2019     return 0;
2020 }
2021 
2022 static int
2023 cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component,
2024                    unsigned char *dataP) {
2025     ColorModelS_t *cmP = &imageP->cmodel;
2026     RasterS_t *rasterP = &imageP->raster;
2027     int y;
2028     jint *pixels;
2029     unsigned char *dP = dataP;
2030 #define NUM_LINES    10
2031     int numLines = NUM_LINES;
2032     int nbytes = rasterP->width*4*NUM_LINES;
2033     jintArray jpixels;
2034 
2035     jpixels = (*env)->NewIntArray(env, nbytes);
2036     if (JNU_IsNull(env, jpixels)) {
2037         JNU_ThrowOutOfMemoryError(env, "Out of Memory");
2038         return -1;
2039     }
2040 
2041     for (y=0; y < rasterP->height; y+=NUM_LINES) {
2042         if (y+numLines > rasterP->height) {
2043             numLines = rasterP->height - y;
2044             nbytes = rasterP->width*4*numLines;
2045         }
2046         pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL);
2047         if (pixels == NULL) {
2048             /* JNI error */
2049             return -1;
2050         }
2051 
2052         memcpy(pixels, dP, nbytes);
2053         dP += nbytes;
2054 
2055        (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, 0);
2056 
2057        /* setData, one scanline at a time */
2058        /* Fix 4223648, 4184283 */
2059        (*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y,
2060                                 rasterP->width, numLines, jpixels, 0,
2061                                 rasterP->width);
2062        if ((*env)->ExceptionOccurred(env)) {
2063            return -1;
2064        }
2065     }
2066 
2067     /* Need to release the array */
2068     (*env)->DeleteLocalRef(env, jpixels);
2069 
2070     return 0;
2071 }
2072 
2073 static int
2074 allocateArray(JNIEnv *env, BufImageS_t *imageP,
2075               mlib_image **mlibImagePP, void **dataPP, int isSrc,
2076               int cvtToDefault, int addAlpha) {
2077     void *dataP;
2078     unsigned char *cDataP;
2079     RasterS_t *rasterP = &imageP->raster;
2080     ColorModelS_t *cmP = &imageP->cmodel;
2081     int dataType = BYTE_DATA_TYPE;
2082     int width;
2083     int height;
2084     HintS_t *hintP = &imageP->hints;
2085     *dataPP = NULL;
2086 
2087     width = rasterP->width;
2088     height = rasterP->height;
2089 
2090     /* Useful for convolution? */
2091     /* This code is zero'ed out so that it cannot be called */
2092 
2093     /* To do this correctly, we need to expand src and dst in the     */
2094     /* same direction up/down/left/right only if both can be expanded */
2095     /* in that direction.  Expanding right and down is easy -         */
2096     /* increment width.  Expanding top and left requires bumping      */
2097     /* around pointers and incrementing the width/height              */
2098 
2099 #if 0
2100     if (0 && useEdges) {
2101         baseWidth  = rasterP->baseRasterWidth;
2102         baseHeight = rasterP->baseRasterHeight;
2103         baseXoff = rasterP->baseOriginX;
2104         baseYoff = rasterP->baseOriginY;
2105 
2106         if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {
2107             /* Can use edge */
2108             width++;
2109         }
2110         if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {
2111             /* Can use edge */
2112             height++;
2113         }
2114 
2115         if (rasterP->minX > baseXoff ) {
2116             /* Can use edge */
2117             width++;
2118             /* NEED TO BUMP POINTER BACK A PIXELSTRIDE */
2119         }
2120         if (rasterP->minY  > baseYoff) {
2121             /* Can use edge */
2122             height++;
2123             /* NEED TO BUMP POINTER BACK A SCANLINE */
2124         }
2125 
2126 
2127     }
2128 #endif
2129     if (cvtToDefault) {
2130         int status = 0;
2131         *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
2132         cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2133         /* Make sure the image is cleared */
2134         memset(cDataP, 0, width*height*4);
2135 
2136         if (!isSrc) {
2137             return 0;
2138         }
2139 
2140         switch(imageP->cmodel.cmType) {
2141         case INDEX_CM_TYPE:
2142             /* REMIND: Need to rearrange according to dst cm */
2143             /* Fix 4213160, 4184283 */
2144             if (rasterP->rasterType == COMPONENT_RASTER_TYPE) {
2145                 return expandICM(env, imageP, (unsigned int *)cDataP);
2146             }
2147             else {
2148                 return cvtCustomToDefault(env, imageP, -1, cDataP);
2149             }
2150 
2151         case DIRECT_CM_TYPE:
2152             switch(imageP->raster.dataType) {
2153             case BYTE_DATA_TYPE:
2154                 return expandPackedBCRdefault(env, rasterP, -1, cDataP,
2155                                               !imageP->cmodel.supportsAlpha);
2156             case SHORT_DATA_TYPE:
2157                 return expandPackedSCRdefault(env, rasterP, -1, cDataP,
2158                                               !imageP->cmodel.supportsAlpha);
2159             case INT_DATA_TYPE:
2160                 return expandPackedICRdefault(env, rasterP, -1, cDataP,
2161                                               !imageP->cmodel.supportsAlpha);
2162             }
2163         } /* switch(imageP->cmodel.cmType) */
2164 
2165         return cvtCustomToDefault(env, imageP, -1, cDataP);
2166     }
2167 
2168     /* Interleaved with shared data */
2169     dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2170                                                        NULL);
2171     if (dataP == NULL) {
2172         return -1;
2173     }
2174 
2175     /* Means we need to fill in alpha */
2176     if (!cvtToDefault && addAlpha) {
2177         *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
2178         if (*mlibImagePP != NULL) {
2179             unsigned int *dstP  = (unsigned int *)
2180                 mlib_ImageGetData(*mlibImagePP);
2181             int dstride = (*mlibImagePP)->stride>>2;
2182             int sstride = hintP->sStride>>2;
2183             unsigned int *srcP = (unsigned int *)
2184                 ((unsigned char *)dataP + hintP->dataOffset);
2185             unsigned int *dP, *sP;
2186             int x, y;
2187             for (y=0; y < height; y++, srcP += sstride, dstP += dstride){
2188                 sP = srcP;
2189                 dP = dstP;
2190                 for (x=0; x < width; x++) {
2191                     dP[x] = sP[x] | 0xff000000;
2192                 }
2193             }
2194         }
2195         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2196                                               JNI_ABORT);
2197         return 0;
2198     }
2199     else if ((hintP->packing & BYTE_INTERLEAVED) == BYTE_INTERLEAVED) {
2200         int nChans = (cmP->isDefaultCompatCM ? 4 : hintP->numChans);
2201         /* Easy case.  It is or is similar to the default CM so use
2202      * the array.  Must be byte data.
2203          */
2204             /* Create the medialib image */
2205         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE,
2206                                               nChans,
2207                                               width,
2208                                               height,
2209                                               hintP->sStride,
2210                                               (unsigned char *)dataP
2211                                               + hintP->dataOffset);
2212     }
2213     else if ((hintP->packing & SHORT_INTERLEAVED) == SHORT_INTERLEAVED) {
2214         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
2215                                               hintP->numChans,
2216                                               width,
2217                                               height,
2218                                               imageP->raster.scanlineStride*2,
2219                                               (unsigned short *)dataP
2220                                               + hintP->channelOffset);
2221     }
2222     else {
2223         /* Release the data array */
2224         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2225                                               JNI_ABORT);
2226         return -1;
2227     }
2228 
2229     *dataPP = dataP;
2230     return 0;
2231 }
2232 
2233 static int
2234 allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
2235                     mlib_image **mlibImagePP, void **dataPP, int isSrc) {
2236     void *dataP;
2237     unsigned char *cDataP;
2238     unsigned short *sdataP;
2239     int dataType = BYTE_DATA_TYPE;
2240     int width;
2241     int height;
2242     int dataSize;
2243     int offset;
2244 
2245     *dataPP = NULL;
2246 
2247     width = rasterP->width;
2248     height = rasterP->height;
2249 
2250     if (rasterP->numBands <= 0 || rasterP->numBands > 4) {
2251         /* REMIND: Fix this */
2252         return -1;
2253     }
2254 
2255     /* Useful for convolution? */
2256     /* This code is zero'ed out so that it cannot be called */
2257 
2258     /* To do this correctly, we need to expand src and dst in the     */
2259     /* same direction up/down/left/right only if both can be expanded */
2260     /* in that direction.  Expanding right and down is easy -         */
2261     /* increment width.  Expanding top and left requires bumping      */
2262     /* around pointers and incrementing the width/height              */
2263 
2264 #if 0
2265     if (0 && useEdges) {
2266         baseWidth  = rasterP->baseRasterWidth;
2267         baseHeight = rasterP->baseRasterHeight;
2268         baseXoff = rasterP->baseOriginX;
2269         baseYoff = rasterP->baseOriginY;
2270 
2271         if (rasterP->minX + rasterP->width < baseXoff + baseWidth) {
2272             /* Can use edge */
2273             width++;
2274         }
2275         if (rasterP->minY + rasterP->height < baseYoff + baseHeight) {
2276             /* Can use edge */
2277             height++;
2278         }
2279 
2280         if (rasterP->minX > baseXoff ) {
2281             /* Can use edge */
2282             width++;
2283             /* NEED TO BUMP POINTER BACK A PIXELSTRIDE */
2284         }
2285         if (rasterP->minY  > baseYoff) {
2286             /* Can use edge */
2287             height++;
2288             /* NEED TO BUMP POINTER BACK A SCANLINE */
2289         }
2290 
2291 
2292     }
2293 #endif
2294     switch (rasterP->type) {
2295     case sun_awt_image_IntegerComponentRaster_TYPE_INT_8BIT_SAMPLES:
2296         if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 4)) &&
2297               SAFE_TO_ALLOC_2(width, 4) &&
2298               SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 4)))
2299         {
2300             return -1;
2301         }
2302         offset = 4 * rasterP->chanOffsets[0];
2303         dataSize = 4 * (*env)->GetArrayLength(env, rasterP->jdata);
2304 
2305         if (offset < 0 || offset >= dataSize ||
2306             width > rasterP->scanlineStride ||
2307             height * rasterP->scanlineStride * 4 > dataSize - offset)
2308         {
2309             // raster data buffer is too short
2310             return -1;
2311         }
2312         dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2313                                                            NULL);
2314         if (dataP == NULL) {
2315             return -1;
2316         }
2317         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, 4,
2318                                               width, height,
2319                                               rasterP->scanlineStride*4,
2320                                               (unsigned char *)dataP + offset);
2321         *dataPP = dataP;
2322         return 0;
2323     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_SAMPLES:
2324         if (!(SAFE_TO_ALLOC_2(width, rasterP->numBands) &&
2325               SAFE_TO_ALLOC_2(height, rasterP->scanlineStride)))
2326         {
2327             return -1;
2328         }
2329         offset = rasterP->chanOffsets[0];
2330         dataSize = (*env)->GetArrayLength(env, rasterP->jdata);
2331 
2332         if (offset < 0 || offset >= dataSize ||
2333             width * rasterP->numBands > rasterP->scanlineStride ||
2334             height * rasterP->scanlineStride > dataSize - offset)
2335         {
2336             // raster data buffer is too short
2337             return -1;
2338         }
2339         dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2340                                                            NULL);
2341         if (dataP == NULL) {
2342             return -1;
2343         }
2344         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_BYTE, rasterP->numBands,
2345                                               width, height,
2346                                               rasterP->scanlineStride,
2347                                               (unsigned char *)dataP + offset);
2348         *dataPP = dataP;
2349         return 0;
2350     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_SAMPLES:
2351         if (!((rasterP->chanOffsets[0] == 0 || SAFE_TO_ALLOC_2(rasterP->chanOffsets[0], 2)) &&
2352               SAFE_TO_ALLOC_3(width, rasterP->numBands, 2) &&
2353               SAFE_TO_ALLOC_3(height, rasterP->scanlineStride, 2)))
2354         {
2355               return -1;
2356         }
2357         offset = rasterP->chanOffsets[0] * 2;
2358         dataSize = 2 * (*env)->GetArrayLength(env, rasterP->jdata);
2359 
2360         if (offset < 0 || offset >= dataSize ||
2361             width * rasterP->numBands > rasterP->scanlineStride ||
2362             height * rasterP->scanlineStride * 2 > dataSize - offset)
2363         {
2364             // raster data buffer is too short
2365              return -1;
2366         }
2367         dataP = (void *) (*env)->GetPrimitiveArrayCritical(env, rasterP->jdata,
2368                                                            NULL);
2369         if (dataP == NULL) {
2370             return -1;
2371         }
2372         *mlibImagePP = (*sMlibSysFns.createStructFP)(MLIB_SHORT,
2373                                                      rasterP->numBands,
2374                                                      width, height,
2375                                                      rasterP->scanlineStride*2,
2376                                                      (unsigned char *)dataP + offset);
2377         *dataPP = dataP;
2378         return 0;
2379 
2380     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
2381         *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2382                                         width, height);
2383         if (!isSrc) return 0;
2384         cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2385         return expandPackedBCR(env, rasterP, -1, cDataP);
2386 
2387     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:
2388         if (rasterP->sppsm.maxBitSize <= 8) {
2389             *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2390                                             width, height);
2391             if (!isSrc) return 0;
2392             cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2393             return expandPackedSCR(env, rasterP, -1, cDataP);
2394         }
2395         break;
2396     case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:
2397         if (rasterP->sppsm.maxBitSize <= 8) {
2398             *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2399                                             width, height);
2400             if (!isSrc) return 0;
2401             cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2402             return expandPackedICR(env, rasterP, -1, cDataP);
2403         }
2404         break;
2405     }
2406 
2407     /* Just expand it right now */
2408     switch (rasterP->dataType) {
2409     case BYTE_DATA_TYPE:
2410         if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
2411                                              width, height)) == NULL) {
2412             return -1;
2413         }
2414         if (isSrc) {
2415             cDataP  = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
2416             if (awt_getPixelByte(env, -1, rasterP, cDataP) < 0) {
2417                 (*sMlibSysFns.deleteImageFP)(*mlibImagePP);
2418                 return -1;
2419             }
2420         }
2421         break;
2422 
2423     case SHORT_DATA_TYPE:
2424         if ((*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_SHORT,
2425                                                     rasterP->numBands,
2426                                                     width, height)) == NULL) {
2427             return -1;
2428         }
2429         if (isSrc) {
2430             sdataP  = (unsigned short *) mlib_ImageGetData(*mlibImagePP);
2431             if (awt_getPixelShort(env, -1, rasterP, sdataP) < 0) {
2432                 (*sMlibSysFns.deleteImageFP)(*mlibImagePP);
2433                 return -1;
2434             }
2435         }
2436         break;
2437 
2438     default:
2439         return -1;
2440     }
2441     return 0;
2442 }
2443 
2444 static void
2445 freeArray(JNIEnv *env, BufImageS_t *srcimageP, mlib_image *srcmlibImP,
2446           void *srcdataP, BufImageS_t *dstimageP, mlib_image *dstmlibImP,
2447           void *dstdataP) {
2448     jobject srcJdata = (srcimageP != NULL ? srcimageP->raster.jdata : NULL);
2449     jobject dstJdata = (dstimageP != NULL ? dstimageP->raster.jdata : NULL);
2450     freeDataArray(env, srcJdata, srcmlibImP, srcdataP,
2451                   dstJdata, dstmlibImP, dstdataP);
2452 }
2453 static void
2454 freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP,
2455           void *srcdataP, jobject dstJdata, mlib_image *dstmlibImP,
2456           void *dstdataP)
2457 {
2458     /* Free the medialib image */
2459     if (srcmlibImP) {
2460         (*sMlibSysFns.deleteImageFP)(srcmlibImP);
2461     }
2462 
2463     /* Release the array */
2464     if (srcdataP) {
2465         (*env)->ReleasePrimitiveArrayCritical(env, srcJdata,
2466                                               srcdataP, JNI_ABORT);
2467     }
2468 
2469     /* Free the medialib image */
2470     if (dstmlibImP) {
2471         (*sMlibSysFns.deleteImageFP)(dstmlibImP);
2472     }
2473 
2474     /* Release the array */
2475     if (dstdataP) {
2476         (*env)->ReleasePrimitiveArrayCritical(env, dstJdata,
2477                                               dstdataP, 0);
2478     }
2479 }
2480 
2481 static int
2482 storeDstArray(JNIEnv *env,  BufImageS_t *srcP, BufImageS_t *dstP,
2483               mlibHintS_t *hintP, mlib_image *mlibImP, void *ddata) {
2484     RasterS_t *rasterP = &dstP->raster;
2485 
2486     /* Nothing to do since it is the same image type */
2487     if (srcP->imageType == dstP->imageType
2488         && srcP->imageType != java_awt_image_BufferedImage_TYPE_CUSTOM
2489         && srcP->imageType != java_awt_image_BufferedImage_TYPE_BYTE_INDEXED
2490         && srcP->imageType != java_awt_image_BufferedImage_TYPE_BYTE_BINARY) {
2491         /* REMIND: Should check the ICM LUTS to see if it is the same */
2492         return 0;
2493     }
2494 
2495     /* These types are compatible with TYPE_INT_RGB */
2496     if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB
2497         && (dstP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||
2498            dstP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE)){
2499         return 0;
2500     }
2501 
2502     if (hintP->cvtSrcToDefault &&
2503         (srcP->cmodel.isAlphaPre == dstP->cmodel.isAlphaPre)) {
2504         if (srcP->cmodel.isAlphaPre) {
2505             if (dstP->imageType ==
2506                 java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE)
2507             {
2508                 return 0;
2509             }
2510             if (!srcP->cmodel.supportsAlpha &&
2511                 dstP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB){
2512                 return 0;
2513             }
2514         }
2515         else {
2516             /* REMIND: */
2517         }
2518     }
2519 
2520     if (dstP->cmodel.cmType == DIRECT_CM_TYPE) {
2521         /* Just need to move bits */
2522         if (mlibImP->type == MLIB_BYTE) {
2523             return awt_setPixelByte(env, -1, &dstP->raster,
2524                                     (unsigned char *) mlibImP->data);
2525         }
2526         else if (mlibImP->type == MLIB_SHORT) {
2527             return awt_setPixelByte(env, -1, &dstP->raster,
2528                                     (unsigned char *) mlibImP->data);
2529         }
2530     }
2531 
2532     return 0;
2533 }
2534 
2535 static int
2536 storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
2537                 mlib_image *mlibImP) {
2538     int mStride;
2539     unsigned char *cmDataP, *dataP, *cDataP;
2540     HintS_t *hintP = &dstP->hints;
2541     RasterS_t *rasterP = &dstP->raster;
2542     int y;
2543 
2544     /* REMIND: Store mlib data type? */
2545 
2546     /* Check if it is an IndexColorModel */
2547     if (dstP->cmodel.cmType == INDEX_CM_TYPE) {
2548         if (dstP->raster.rasterType == COMPONENT_RASTER_TYPE) {
2549             return storeICMarray(env, srcP, dstP, mlibImP);
2550         }
2551         else {
2552             /* Packed or some other custom raster */
2553             cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2554             return cvtDefaultToCustom(env, dstP, -1, cmDataP);
2555         }
2556     }
2557 
2558     if (hintP->packing == BYTE_INTERLEAVED) {
2559         /* Write it back to the destination */
2560         cmDataP = (unsigned char *) mlib_ImageGetData(mlibImP);
2561         mStride = mlib_ImageGetStride(mlibImP);
2562         dataP = (unsigned char *)(*env)->GetPrimitiveArrayCritical(env,
2563                                                       rasterP->jdata, NULL);
2564         if (dataP == NULL) return 0;
2565         cDataP = dataP + hintP->dataOffset;
2566         for (y=0; y < rasterP->height;
2567              y++, cmDataP += mStride, cDataP += hintP->sStride)
2568         {
2569             memcpy(cDataP, cmDataP, rasterP->width*hintP->numChans);
2570         }
2571         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2572                                               JNI_ABORT);
2573     }
2574     else if (hintP->packing == SHORT_INTERLEAVED) {
2575         /* Write it back to the destination */
2576         unsigned short *sdataP, *sDataP;
2577         unsigned short *smDataP = (unsigned short *)mlib_ImageGetData(mlibImP);
2578         mStride = mlib_ImageGetStride(mlibImP);
2579         sdataP = (unsigned short *)(*env)->GetPrimitiveArrayCritical(env,
2580                                                       rasterP->jdata, NULL);
2581         if (sdataP == NULL) return -1;
2582         sDataP = sdataP + hintP->dataOffset;
2583         for (y=0; y < rasterP->height;
2584              y++, smDataP += mStride, sDataP += hintP->sStride)
2585         {
2586             memcpy(sDataP, smDataP, rasterP->width*hintP->numChans);
2587         }
2588         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, sdataP,
2589                                               JNI_ABORT);
2590     }
2591     else if (dstP->cmodel.cmType == DIRECT_CM_TYPE) {
2592         /* Just need to move bits */
2593         if (mlibImP->type == MLIB_BYTE) {
2594             if (dstP->hints.packing == PACKED_BYTE_INTER) {
2595                 return setPackedBCRdefault(env, rasterP, -1,
2596                                            (unsigned char *) mlibImP->data,
2597                                            dstP->cmodel.supportsAlpha);
2598             } else if (dstP->hints.packing == PACKED_SHORT_INTER) {
2599                 return setPackedSCRdefault(env, rasterP, -1,
2600                                            (unsigned char *) mlibImP->data,
2601                                            dstP->cmodel.supportsAlpha);
2602             } else if (dstP->hints.packing == PACKED_INT_INTER) {
2603                 return setPackedICRdefault(env, rasterP, -1,
2604                                            (unsigned char *) mlibImP->data,
2605                                            dstP->cmodel.supportsAlpha);
2606             }
2607         }
2608         else if (mlibImP->type == MLIB_SHORT) {
2609             return awt_setPixelShort(env, -1, rasterP,
2610                                     (unsigned short *) mlibImP->data);
2611         }
2612     }
2613     else {
2614         return cvtDefaultToCustom(env, dstP, -1,
2615                                   (unsigned char *)mlibImP->data);
2616     }
2617 
2618     return 0;
2619 }
2620 
2621 static int
2622 storeRasterArray(JNIEnv *env, RasterS_t *srcP, RasterS_t *dstP,
2623                 mlib_image *mlibImP) {
2624     unsigned char *cDataP;
2625 
2626     switch(dstP->type) {
2627     case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
2628         cDataP  = (unsigned char *) mlib_ImageGetData(mlibImP);
2629         return setPackedBCR(env, dstP, -1, cDataP);
2630 
2631     case sun_awt_image_IntegerComponentRaster_TYPE_USHORT_PACKED_SAMPLES:
2632         if (dstP->sppsm.maxBitSize <= 8) {
2633             cDataP  = (unsigned char *) mlib_ImageGetData(mlibImP);
2634             return setPackedSCR(env, dstP, -1, cDataP);
2635         }
2636         break;
2637     case sun_awt_image_IntegerComponentRaster_TYPE_INT_PACKED_SAMPLES:
2638         if (dstP->sppsm.maxBitSize <= 8) {
2639             cDataP  = (unsigned char *) mlib_ImageGetData(mlibImP);
2640             return setPackedICR(env, dstP, -1, cDataP);
2641         }
2642     }
2643 
2644     return -1;
2645 }
2646 
2647 
2648 static int
2649 storeICMarray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP,
2650               mlib_image *mlibImP)
2651 {
2652     int *argb;
2653     int x, y;
2654     unsigned char *dataP, *cDataP, *cP;
2655     unsigned char *sP;
2656     int aIdx, rIdx, gIdx, bIdx;
2657     ColorModelS_t *cmodelP = &dstP->cmodel;
2658     RasterS_t *rasterP = &dstP->raster;
2659 
2660     /* REMIND: Only works for RGB */
2661     if (cmodelP->csType != java_awt_color_ColorSpace_TYPE_RGB) {
2662         JNU_ThrowInternalError(env, "Writing to non-RGB images not implemented yet");
2663         return -1;
2664     }
2665 
2666     if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||
2667         srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
2668         srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)
2669     {
2670         aIdx = 0;
2671         rIdx = 1;
2672         gIdx = 2;
2673         bIdx = 3;
2674     }
2675     else if (srcP->imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR||
2676         srcP->imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)
2677     {
2678         aIdx = 0;
2679         rIdx = 3;
2680         gIdx = 2;
2681         bIdx = 1;
2682     }
2683     else if (srcP->imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR){
2684         rIdx = 2;
2685         gIdx = 1;
2686         bIdx = 0;
2687         aIdx = 0;       /* Ignored */
2688     }
2689     else if (srcP->cmodel.cmType == INDEX_CM_TYPE) {
2690         rIdx = 0;
2691         gIdx = 1;
2692         bIdx = 2;
2693         aIdx = 3;   /* Use supportsAlpha to see if it is really there */
2694     }
2695     else {
2696         return -1;
2697     }
2698 
2699     /* Lock down the destination raster */
2700     dataP = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env,
2701                                                   rasterP->jdata, NULL);
2702     if (dataP == NULL) {
2703         return -1;
2704     }
2705     argb = (*env)->GetPrimitiveArrayCritical(env, cmodelP->jrgb, NULL);
2706     if (argb == NULL) {
2707         (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2708                                               JNI_ABORT);
2709         return -1;
2710     }
2711 
2712     cDataP = dataP + dstP->hints.dataOffset;
2713     sP = (unsigned char *) mlib_ImageGetData(mlibImP);
2714 
2715     for (y=0; y < rasterP->height; y++, cDataP += rasterP->scanlineStride) {
2716         cP = cDataP;
2717         for (x=0; x < rasterP->width; x++, cP += rasterP->pixelStride) {
2718             *cP = colorMatch(sP[rIdx], sP[gIdx], sP[bIdx], sP[aIdx],
2719                              (unsigned char *)argb, cmodelP->mapSize);
2720             sP += cmodelP->numComponents;
2721         }
2722     }
2723 
2724     (*env)->ReleasePrimitiveArrayCritical(env, cmodelP->jrgb, argb, JNI_ABORT);
2725     (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata, dataP,
2726                                           JNI_ABORT);
2727     return -1;
2728 }
2729 
2730 static int expandICM(JNIEnv *env, BufImageS_t *imageP, unsigned int *mDataP)
2731 {
2732     ColorModelS_t *cmP = &imageP->cmodel;
2733     RasterS_t *rasterP = &imageP->raster;
2734     HintS_t *hintP     = &imageP->hints;
2735     int *rgb;
2736     int status = 0;
2737     unsigned char *dataP, *cP;
2738     unsigned int *mP;
2739     int width = rasterP->width;
2740     int height = rasterP->height;
2741     int x, y;
2742 
2743     /* Need to grab the lookup tables.  Right now only bytes */
2744     rgb = (int *) (*env)->GetPrimitiveArrayCritical(env, cmP->jrgb, NULL);
2745 
2746     /* Interleaved with shared data */
2747     dataP = (void *) (*env)->GetPrimitiveArrayCritical(env,
2748                                                        rasterP->jdata, NULL);
2749     if (rgb == NULL || dataP == NULL) {
2750         /* Release the lookup tables */
2751         if (rgb) {
2752             (*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb,
2753                                                   JNI_ABORT);
2754         }
2755         if (dataP) {
2756             (*env)->ReleasePrimitiveArrayCritical(env,
2757                                                   rasterP->jdata, dataP,
2758                                                   JNI_ABORT);
2759         }
2760         return -1;
2761     }
2762 
2763     if (rasterP->dataType == BYTE_DATA_TYPE) {
2764         unsigned char *cDataP = ((unsigned char *)dataP) + hintP->dataOffset;
2765 
2766         for (y=0; y < height; y++) {
2767             mP = mDataP;
2768             cP = cDataP;
2769             for (x=0; x < width; x++, cP += rasterP->pixelStride) {
2770                 *mP++ = rgb[*cP];
2771             }
2772             mDataP += width;
2773             cDataP += rasterP->scanlineStride;
2774         }
2775     }
2776     else if (rasterP->dataType == SHORT_DATA_TYPE) {
2777         unsigned short *sDataP, *sP;
2778         sDataP = ((unsigned short *)dataP) + hintP->channelOffset;
2779 
2780         for (y=0; y < height; y++) {
2781             mP = mDataP;
2782             sP = sDataP;
2783             for (x=0; x < width; x++, sP+=rasterP->pixelStride) {
2784                 *mP++ = rgb[*sP];
2785             }
2786             mDataP += width;
2787             sDataP += rasterP->scanlineStride;
2788         }
2789     }
2790     else {
2791         /* Unknown type */
2792         status = -1;
2793     }
2794     /* Release the lookup table data */
2795     (*env)->ReleasePrimitiveArrayCritical(env, imageP->cmodel.jrgb,
2796                                           rgb, JNI_ABORT);
2797     /* Release the data array */
2798     (*env)->ReleasePrimitiveArrayCritical(env, rasterP->jdata,
2799                                           dataP, JNI_ABORT);
2800     return status;
2801 }
2802 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
2803 static int expandPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
2804                            unsigned char *outDataP)
2805 {
2806     int x, y, c;
2807     unsigned char *outP = outDataP;
2808     unsigned char *lineInP, *inP;
2809     jarray jInDataP;
2810     jint   *inDataP;
2811     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
2812 
2813     if (rasterP->numBands > MAX_NUMBANDS) {
2814         return -1;
2815     }
2816 
2817     /* Grab data ptr, strides, offsets from raster */
2818     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
2819     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
2820     if (inDataP == NULL) {
2821         return -1;
2822     }
2823     lineInP =  (unsigned char *)inDataP + rasterP->chanOffsets[0];
2824 
2825     if (component < 0) {
2826         for (c=0; c < rasterP->numBands; c++) {
2827             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2828             if (roff[c] < 0) {
2829                 loff[c] = -roff[c];
2830                 roff[c] = 0;
2831             }
2832             else loff[c] = 0;
2833         }
2834         /* Convert the all bands */
2835         if (rasterP->numBands < 4) {
2836             /* Need to put in alpha */
2837             for (y=0; y < rasterP->height; y++) {
2838                 inP = lineInP;
2839                 for (x=0; x < rasterP->width; x++) {
2840                     for (c=0; c < rasterP->numBands; c++) {
2841                         *outP++ = (unsigned char)
2842                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2843                              <<loff[c]);
2844                     }
2845                     inP++;
2846                 }
2847                 lineInP += rasterP->scanlineStride;
2848             }
2849         }
2850         else {
2851             for (y=0; y < rasterP->height; y++) {
2852                 inP = lineInP;
2853                 for (x=0; x < rasterP->width; x++) {
2854                     for (c=0; c < rasterP->numBands; c++) {
2855                         *outP++ = (unsigned char)
2856                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2857                              <<loff[c]);
2858                     }
2859                     inP++;
2860                 }
2861                 lineInP += rasterP->scanlineStride;
2862             }
2863         }
2864     }
2865     else {
2866         c = component;
2867         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2868         if (roff[0] < 0) {
2869             loff[0] = -roff[0];
2870             roff[0] = 0;
2871         }
2872         else loff[c] = 0;
2873         for (y=0; y < rasterP->height; y++) {
2874             inP = lineInP;
2875             for (x=0; x < rasterP->width; x++) {
2876                 *outP++ = (unsigned char)
2877                     ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
2878                 inP++;
2879             }
2880             lineInP += rasterP->scanlineStride;
2881         }
2882     }
2883 
2884     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
2885 
2886     return 0;
2887 }
2888 
2889 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
2890 static int expandPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
2891                                   int component, unsigned char *outDataP,
2892                                   int forceAlpha)
2893 {
2894     int x, y, c;
2895     unsigned char *outP = outDataP;
2896     unsigned char *lineInP, *inP;
2897     jarray jInDataP;
2898     jint   *inDataP;
2899     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
2900     int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
2901     int a = numBands;
2902 
2903     if (rasterP->numBands > MAX_NUMBANDS) {
2904         return -1;
2905     }
2906 
2907     /* Grab data ptr, strides, offsets from raster */
2908     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
2909     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
2910     if (inDataP == NULL) {
2911         return -1;
2912     }
2913     lineInP =  (unsigned char *)inDataP + rasterP->chanOffsets[0];
2914 
2915     if (component < 0) {
2916         for (c=0; c < rasterP->numBands; c++) {
2917             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2918             if (roff[c] < 0) {
2919                 loff[c] = -roff[c];
2920                 roff[c] = 0;
2921             }
2922             else loff[c] = 0;
2923         }
2924 
2925         /* Need to put in alpha */
2926         if (forceAlpha) {
2927             for (y=0; y < rasterP->height; y++) {
2928                 inP = lineInP;
2929                 for (x=0; x < rasterP->width; x++) {
2930                     *outP++ = 0xff;
2931                     for (c=0; c < numBands; c++) {
2932                         *outP++ = (unsigned char)
2933                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2934                              <<loff[c]);
2935                     }
2936                     inP++;
2937                 }
2938                 lineInP += rasterP->scanlineStride;
2939             }
2940         }
2941         else {
2942             for (y=0; y < rasterP->height; y++) {
2943                 inP = lineInP;
2944                 for (x=0; x < rasterP->width; x++) {
2945                     *outP++ = (unsigned char)
2946                         (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
2947                          <<loff[a]);
2948                     for (c=0; c < numBands; c++) {
2949                         *outP++ = (unsigned char)
2950                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
2951                              <<loff[c]);
2952                     }
2953                     inP++;
2954                 }
2955                 lineInP += rasterP->scanlineStride;
2956             }
2957         }
2958     }
2959     else {
2960         c = component;
2961         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
2962         if (roff[0] < 0) {
2963             loff[0] = -roff[0];
2964             roff[0] = 0;
2965         }
2966         else loff[c] = 0;
2967         for (y=0; y < rasterP->height; y++) {
2968             inP = lineInP;
2969             for (x=0; x < rasterP->width; x++) {
2970                 *outP++ = (unsigned char)
2971                     ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
2972                 inP++;
2973             }
2974             lineInP += rasterP->scanlineStride;
2975         }
2976     }
2977 
2978     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
2979 
2980     return 0;
2981 }
2982 
2983 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
2984 static int expandPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
2985                            unsigned char *outDataP)
2986 {
2987     int x, y, c;
2988     unsigned char *outP = outDataP;
2989     unsigned short *lineInP, *inP;
2990     jarray jInDataP;
2991     jint   *inDataP;
2992     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
2993 
2994     if (rasterP->numBands > MAX_NUMBANDS) {
2995         return -1;
2996     }
2997 
2998     /* Grab data ptr, strides, offsets from raster */
2999     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3000     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3001     if (inDataP == NULL) {
3002         return -1;
3003     }
3004     lineInP =  (unsigned short *)inDataP + rasterP->chanOffsets[0];
3005 
3006     if (component < 0) {
3007         for (c=0; c < rasterP->numBands; c++) {
3008             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3009             if (roff[c] < 0) {
3010                 loff[c] = -roff[c];
3011                 roff[c] = 0;
3012             }
3013             else loff[c] = 0;
3014         }
3015         /* Convert the all bands */
3016         if (rasterP->numBands < 4) {
3017             /* Need to put in alpha */
3018             for (y=0; y < rasterP->height; y++) {
3019                 inP = lineInP;
3020                 for (x=0; x < rasterP->width; x++) {
3021                     for (c=0; c < rasterP->numBands; c++) {
3022                         /*
3023                          *Not correct.  Might need to unpremult,
3024                          * shift, etc
3025                          */
3026                         *outP++ = (unsigned char)
3027                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3028                              <<loff[c]);
3029                     }
3030                     inP++;
3031                 }
3032                 lineInP += rasterP->scanlineStride;
3033             }
3034         } else {
3035             for (y=0; y < rasterP->height; y++) {
3036                 inP = lineInP;
3037                 for (x=0; x < rasterP->width; x++) {
3038                     for (c=0; c < rasterP->numBands; c++) {
3039                         /*
3040                          *Not correct.  Might need to unpremult,
3041                          * shift, etc
3042                          */
3043                         *outP++ = (unsigned char)
3044                             (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3045                              <<loff[c]);
3046                     }
3047                     inP++;
3048                 }
3049                 lineInP += rasterP->scanlineStride;
3050             }
3051         }
3052     }
3053     else {
3054         c = component;
3055         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3056         if (roff[0] < 0) {
3057             loff[0] = -roff[0];
3058             roff[0] = 0;
3059         }
3060         else loff[c] = 0;
3061         for (y=0; y < rasterP->height; y++) {
3062             inP = lineInP;
3063             for (x=0; x < rasterP->width; x++) {
3064                 *outP++ = (unsigned char)
3065                     ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3066                 inP++;
3067             }
3068             lineInP += rasterP->scanlineStride;
3069         }
3070     }
3071 
3072     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3073 
3074     return 0;
3075 }
3076 
3077 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3078 static int expandPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
3079                                   int component, unsigned char *outDataP,
3080                                   int forceAlpha)
3081 {
3082     int x, y, c;
3083     unsigned char *outP = outDataP;
3084     unsigned short *lineInP, *inP;
3085     jarray jInDataP;
3086     jint   *inDataP;
3087     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3088     int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3089     int a = numBands;
3090 
3091     if (rasterP->numBands > MAX_NUMBANDS) {
3092         return -1;
3093     }
3094 
3095     /* Grab data ptr, strides, offsets from raster */
3096     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3097     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3098     if (inDataP == NULL) {
3099         return -1;
3100     }
3101     lineInP =  (unsigned short *)inDataP + rasterP->chanOffsets[0];
3102 
3103     if (component < 0) {
3104         for (c=0; c < rasterP->numBands; c++) {
3105             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3106             if (roff[c] < 0) {
3107                 loff[c] = -roff[c];
3108                 roff[c] = 0;
3109             }
3110             else loff[c] = 0;
3111         }
3112 
3113         /* Need to put in alpha */
3114         if (forceAlpha) {
3115             for (y=0; y < rasterP->height; y++) {
3116                 inP = lineInP;
3117                 for (x=0; x < rasterP->width; x++) {
3118                     *outP++ = 0xff;
3119                     for (c=0; c < numBands; c++) {
3120                         /*
3121                          * Not correct.  Might need to unpremult,
3122                          * shift, etc
3123                          */
3124                         *outP++ = (unsigned char)
3125                                 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3126                                    <<loff[c]);
3127                     }
3128                     inP++;
3129                 }
3130                 lineInP += rasterP->scanlineStride;
3131             }
3132         }
3133         else {
3134             for (y=0; y < rasterP->height; y++) {
3135                 inP = lineInP;
3136                 for (x=0; x < rasterP->width; x++) {
3137                     *outP++ = (unsigned char)
3138                         (((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3139                                    <<loff[a]);
3140                     for (c=0; c < numBands; c++) {
3141                         /*
3142                          * Not correct.  Might need to
3143                          * unpremult, shift, etc
3144                          */
3145                         *outP++ = (unsigned char)
3146                                 (((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3147                                    <<loff[c]);
3148                     }
3149                     inP++;
3150                 }
3151                 lineInP += rasterP->scanlineStride;
3152             }
3153         }
3154     }
3155     else {
3156         c = component;
3157         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3158         if (roff[0] < 0) {
3159             loff[0] = -roff[0];
3160             roff[0] = 0;
3161         }
3162         else loff[c] = 0;
3163         for (y=0; y < rasterP->height; y++) {
3164             inP = lineInP;
3165             for (x=0; x < rasterP->width; x++) {
3166                 *outP++ = (unsigned char)
3167                         ((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0];
3168                 inP++;
3169             }
3170             lineInP += rasterP->scanlineStride;
3171         }
3172     }
3173 
3174     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3175 
3176     return 0;
3177 
3178 }
3179 
3180 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3181 static int expandPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
3182                            unsigned char *outDataP)
3183 {
3184     int x, y, c;
3185     unsigned char *outP = outDataP;
3186     unsigned int *lineInP, *inP;
3187     jarray jInDataP;
3188     jint   *inDataP;
3189     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3190 
3191     if (rasterP->numBands > MAX_NUMBANDS) {
3192         return -1;
3193     }
3194 
3195     /* Grab data ptr, strides, offsets from raster */
3196     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3197     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3198     if (inDataP == NULL) {
3199         return -1;
3200     }
3201     lineInP =  (unsigned int *)inDataP + rasterP->chanOffsets[0];
3202 
3203     if (component < 0) {
3204         for (c=0; c < rasterP->numBands; c++) {
3205             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3206             if (roff[c] < 0) {
3207                 loff[c] = -roff[c];
3208                 roff[c] = 0;
3209             }
3210             else loff[c] = 0;
3211         }
3212         /* Convert the all bands */
3213         if (rasterP->numBands < 4) {
3214             for (y=0; y < rasterP->height; y++) {
3215                 inP = lineInP;
3216                 for (x=0; x < rasterP->width; x++) {
3217                     for (c=0; c < rasterP->numBands; c++) {
3218                         /*
3219                          * Not correct.  Might need to unpremult,
3220                          * shift, etc
3221                          */
3222                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3223                                    <<loff[c]);
3224                     }
3225                     inP++;
3226                 }
3227                 lineInP += rasterP->scanlineStride;
3228             }
3229         }
3230         else {
3231             for (y=0; y < rasterP->height; y++) {
3232                 inP = lineInP;
3233                 for (x=0; x < rasterP->width; x++) {
3234                     for (c=0; c < rasterP->numBands; c++) {
3235                         /*
3236                          * Not correct.  Might need to
3237                          * unpremult, shift, etc
3238                          */
3239                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3240                                    <<loff[c]);
3241                     }
3242                     inP++;
3243                 }
3244                 lineInP += rasterP->scanlineStride;
3245             }
3246         }
3247     }
3248     else {
3249         c = component;
3250         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3251         if (roff[0] < 0) {
3252             loff[0] = -roff[0];
3253             roff[0] = 0;
3254         }
3255         else loff[c] = 0;
3256         for (y=0; y < rasterP->height; y++) {
3257             inP = lineInP;
3258             for (x=0; x < rasterP->width; x++) {
3259                 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);
3260                 inP++;
3261             }
3262             lineInP += rasterP->scanlineStride;
3263         }
3264     }
3265 
3266     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3267 
3268     return 0;
3269 }
3270 
3271 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3272 static int expandPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
3273                                   int component, unsigned char *outDataP,
3274                                   int forceAlpha)
3275 {
3276     int x, y, c;
3277     unsigned char *outP = outDataP;
3278     unsigned int *lineInP, *inP;
3279     jarray jInDataP;
3280     jint   *inDataP;
3281     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3282     int numBands = rasterP->numBands - (forceAlpha ? 0 : 1);
3283     int a = numBands;
3284 
3285     if (rasterP->numBands > MAX_NUMBANDS) {
3286         return -1;
3287     }
3288 
3289     /* Grab data ptr, strides, offsets from raster */
3290     jInDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3291     inDataP = (*env)->GetPrimitiveArrayCritical(env, jInDataP, 0);
3292     if (inDataP == NULL) {
3293         return -1;
3294     }
3295     lineInP =  (unsigned int *)inDataP + rasterP->chanOffsets[0];
3296 
3297     if (component < 0) {
3298         for (c=0; c < rasterP->numBands; c++) {
3299             roff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3300             if (roff[c] < 0) {
3301                 loff[c] = -roff[c];
3302                 roff[c] = 0;
3303             }
3304             else loff[c] = 0;
3305         }
3306 
3307         /* Need to put in alpha */
3308         if (forceAlpha) {
3309             for (y=0; y < rasterP->height; y++) {
3310                 inP = lineInP;
3311                 for (x=0; x < rasterP->width; x++) {
3312                     *outP++ = 0xff;
3313                     for (c=0; c < numBands; c++) {
3314                         /*
3315                          * Not correct.  Might need to unpremult,
3316                          * shift, etc
3317                          */
3318                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3319                                    <<loff[c]);
3320                     }
3321                     inP++;
3322                 }
3323                 lineInP += rasterP->scanlineStride;
3324             }
3325         }
3326         else {
3327             for (y=0; y < rasterP->height; y++) {
3328                 inP = lineInP;
3329                 for (x=0; x < rasterP->width; x++) {
3330                     *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[a]) >> roff[a])
3331                                    <<loff[a]);
3332                     for (c=0; c < numBands; c++) {
3333                         /*
3334                          * Not correct.  Might need to
3335                          * unpremult, shift, etc
3336                          */
3337                         *outP++ = (unsigned char)(((*inP&rasterP->sppsm.maskArray[c]) >> roff[c])
3338                                    <<loff[c]);
3339                     }
3340                     inP++;
3341                 }
3342                 lineInP += rasterP->scanlineStride;
3343             }
3344         }
3345     }
3346     else {
3347         c = component;
3348         roff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3349         if (roff[0] < 0) {
3350             loff[0] = -roff[0];
3351             roff[0] = 0;
3352         }
3353         else loff[c] = 0;
3354         for (y=0; y < rasterP->height; y++) {
3355             inP = lineInP;
3356             for (x=0; x < rasterP->width; x++) {
3357                 *outP++ = (unsigned char)(((*inP & rasterP->sppsm.maskArray[c])>>roff[0])<<loff[0]);
3358                 inP++;
3359             }
3360             lineInP += rasterP->scanlineStride;
3361         }
3362     }
3363 
3364     (*env)->ReleasePrimitiveArrayCritical(env, jInDataP, inDataP, JNI_ABORT);
3365 
3366     return 0;
3367 }
3368 
3369 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
3370 static int setPackedBCR(JNIEnv *env, RasterS_t *rasterP, int component,
3371                         unsigned char *inDataP)
3372 {
3373     int x, y, c;
3374     unsigned char *inP = inDataP;
3375     unsigned char *lineOutP, *outP;
3376     jarray jOutDataP;
3377     jint   *outDataP;
3378     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3379 
3380     if (rasterP->numBands > MAX_NUMBANDS) {
3381         return -1;
3382     }
3383 
3384     /* Grab data ptr, strides, offsets from raster */
3385     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3386     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3387     if (outDataP == NULL) {
3388         return -1;
3389     }
3390     lineOutP =  (unsigned char *)outDataP + rasterP->chanOffsets[0];
3391 
3392     if (component < 0) {
3393         for (c=0; c < rasterP->numBands; c++) {
3394             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3395             if (loff[c] < 0) {
3396                 roff[c] = -loff[c];
3397                 loff[c] = 0;
3398             }
3399             else roff[c] = 0;
3400         }
3401         /* Convert the all bands */
3402         for (y=0; y < rasterP->height; y++) {
3403             outP = lineOutP;
3404             *outP = 0;
3405             for (x=0; x < rasterP->width; x++) {
3406                 for (c=0; c < rasterP->numBands; c++, inP++) {
3407                     *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3408                 }
3409                 outP++;
3410             }
3411             lineOutP += rasterP->scanlineStride;
3412         }
3413     }
3414     else {
3415         c = component;
3416         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3417         if (loff[0] < 0) {
3418             roff[0] = -loff[0];
3419             loff[0] = 0;
3420         }
3421         else roff[c] = 0;
3422         for (y=0; y < rasterP->height; y++) {
3423             outP = lineOutP;
3424             for (x=0; x < rasterP->width; x++, inP++) {
3425                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3426                 outP++;
3427             }
3428             lineOutP += rasterP->scanlineStride;
3429         }
3430     }
3431 
3432     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3433 
3434     return 0;
3435 }
3436 
3437 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3438 static int setPackedSCR(JNIEnv *env, RasterS_t *rasterP, int component,
3439                            unsigned char *inDataP)
3440 {
3441     int x, y, c;
3442     unsigned char *inP = inDataP;
3443     unsigned short *lineOutP, *outP;
3444     jarray jOutDataP;
3445     jint   *outDataP;
3446     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3447 
3448     if (rasterP->numBands > MAX_NUMBANDS) {
3449         return -1;
3450     }
3451 
3452     /* Grab data ptr, strides, offsets from raster */
3453     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3454     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3455     if (outDataP == NULL) {
3456         return -1;
3457     }
3458     lineOutP =  (unsigned short *)outDataP + rasterP->chanOffsets[0];
3459 
3460     if (component < 0) {
3461         for (c=0; c < rasterP->numBands; c++) {
3462             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3463             if (loff[c] < 0) {
3464                 roff[c] = -loff[c];
3465                 loff[c] = 0;
3466             }
3467             else roff[c] = 0;
3468         }
3469         /* Convert the all bands */
3470         for (y=0; y < rasterP->height; y++) {
3471             outP = lineOutP;
3472             for (x=0; x < rasterP->width; x++) {
3473                 for (c=0; c < rasterP->numBands; c++, inP++) {
3474                     /* Not correct.  Might need to unpremult, shift, etc */
3475                     *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3476                 }
3477                 outP++;
3478             }
3479             lineOutP += rasterP->scanlineStride;
3480         }
3481     }
3482     else {
3483         c = component;
3484         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3485         if (loff[0] < 0) {
3486             roff[0] = -loff[0];
3487             loff[0] = 0;
3488         }
3489         else roff[c] = 0;
3490         for (y=0; y < rasterP->height; y++) {
3491             outP = lineOutP;
3492             for (x=0; x < rasterP->width; x++, inP++) {
3493                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3494                 outP++;
3495             }
3496             lineOutP += rasterP->scanlineStride;
3497         }
3498     }
3499 
3500     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3501 
3502     return 0;
3503 }
3504 
3505 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3506 static int setPackedICR(JNIEnv *env, RasterS_t *rasterP, int component,
3507                            unsigned char *inDataP)
3508 {
3509     int x, y, c;
3510     unsigned char *inP = inDataP;
3511     unsigned int *lineOutP, *outP;
3512     jarray jOutDataP;
3513     jint   *outDataP;
3514     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3515 
3516     if (rasterP->numBands > MAX_NUMBANDS) {
3517         return -1;
3518     }
3519 
3520     /* Grab data ptr, strides, offsets from raster */
3521     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3522     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3523     if (outDataP == NULL) {
3524         return -1;
3525     }
3526     lineOutP =  (unsigned int *)outDataP + rasterP->chanOffsets[0];
3527 
3528     if (component < 0) {
3529         for (c=0; c < rasterP->numBands; c++) {
3530             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3531             if (loff[c] < 0) {
3532                 roff[c] = -loff[c];
3533                 loff[c] = 0;
3534             }
3535             else roff[c] = 0;
3536         }
3537         /* Convert the all bands */
3538         for (y=0; y < rasterP->height; y++) {
3539             outP = lineOutP;
3540             for (x=0; x < rasterP->width; x++) {
3541                 for (c=0; c < rasterP->numBands; c++, inP++) {
3542                     /* Not correct.  Might need to unpremult, shift, etc */
3543                     *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3544                 }
3545                 outP++;
3546             }
3547             lineOutP += rasterP->scanlineStride;
3548         }
3549     }
3550     else {
3551         c = component;
3552         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3553         if (loff[0] < 0) {
3554             roff[0] = -loff[0];
3555             loff[0] = 0;
3556         }
3557         else roff[c] = 0;
3558 
3559         for (y=0; y < rasterP->height; y++) {
3560             outP = lineOutP;
3561             for (x=0; x < rasterP->width; x++, inP++) {
3562                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3563                 outP++;
3564             }
3565             lineOutP += rasterP->scanlineStride;
3566         }
3567     }
3568 
3569     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3570 
3571     return 0;
3572 }
3573 
3574 /* This routine is expecting a ByteComponentRaster with a PackedColorModel */
3575 static int setPackedBCRdefault(JNIEnv *env, RasterS_t *rasterP,
3576                                int component, unsigned char *inDataP,
3577                                int supportsAlpha)
3578 {
3579     int x, y, c;
3580     unsigned char *inP = inDataP;
3581     unsigned char *lineOutP, *outP;
3582     jarray jOutDataP;
3583     jint   *outDataP;
3584     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3585     int a = rasterP->numBands - 1;
3586 
3587     if (rasterP->numBands > MAX_NUMBANDS) {
3588         return -1;
3589     }
3590 
3591     /* Grab data ptr, strides, offsets from raster */
3592     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_BCRdataID);
3593     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3594     if (outDataP == NULL) {
3595         return -1;
3596     }
3597     lineOutP =  (unsigned char *)outDataP + rasterP->chanOffsets[0];
3598 
3599     if (component < 0) {
3600         for (c=0; c < rasterP->numBands; c++) {
3601             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3602             if (loff[c] < 0) {
3603                 roff[c] = -loff[c];
3604                 loff[c] = 0;
3605             }
3606             else roff[c] = 0;
3607         }
3608         /* Convert the all bands */
3609         if (supportsAlpha) {
3610             for (y=0; y < rasterP->height; y++) {
3611                 outP = lineOutP;
3612                 *outP = 0;
3613                 for (x=0; x < rasterP->width; x++) {
3614                     *outP |= (*inP<<loff[a]>>roff[a])&
3615                         rasterP->sppsm.maskArray[a];
3616                     inP++;
3617                     for (c=0; c < rasterP->numBands-1; c++, inP++) {
3618                         *outP |= (*inP<<loff[c]>>roff[c])&
3619                             rasterP->sppsm.maskArray[c];
3620                     }
3621                     outP++;
3622                 }
3623                 lineOutP += rasterP->scanlineStride;
3624             }
3625         }
3626         else {
3627             for (y=0; y < rasterP->height; y++) {
3628                 outP = lineOutP;
3629                 *outP = 0;
3630                 for (x=0; x < rasterP->width; x++) {
3631                     inP++;
3632                     for (c=0; c < rasterP->numBands; c++, inP++) {
3633                         *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3634                     }
3635                     outP++;
3636                 }
3637                 lineOutP += rasterP->scanlineStride;
3638             }
3639         }
3640     }
3641     else {
3642         c = component;
3643         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3644         if (loff[0] < 0) {
3645             roff[0] = -loff[0];
3646             loff[0] = 0;
3647         }
3648         else roff[c] = 0;
3649         for (y=0; y < rasterP->height; y++) {
3650             outP = lineOutP;
3651             for (x=0; x < rasterP->width; x++, inP++) {
3652                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3653                 outP++;
3654             }
3655             lineOutP += rasterP->scanlineStride;
3656         }
3657     }
3658 
3659     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3660 
3661     return 0;
3662 }
3663 
3664 /* This routine is expecting a ShortComponentRaster with a PackedColorModel */
3665 static int setPackedSCRdefault(JNIEnv *env, RasterS_t *rasterP,
3666                                int component, unsigned char *inDataP,
3667                                int supportsAlpha)
3668 {
3669     int x, y, c;
3670     unsigned char *inP = inDataP;
3671     unsigned short *lineOutP, *outP;
3672     jarray jOutDataP;
3673     jint   *outDataP;
3674     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3675     int a = rasterP->numBands - 1;
3676 
3677     if (rasterP->numBands > MAX_NUMBANDS) {
3678         return -1;
3679     }
3680 
3681     /* Grab data ptr, strides, offsets from raster */
3682     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_SCRdataID);
3683     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3684     if (outDataP == NULL) {
3685         return -1;
3686     }
3687     lineOutP =  (unsigned short *)outDataP + rasterP->chanOffsets[0];
3688 
3689     if (component < 0) {
3690         for (c=0; c < rasterP->numBands; c++) {
3691             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3692             if (loff[c] < 0) {
3693                 roff[c] = -loff[c];
3694                 loff[c] = 0;
3695             }
3696             else roff[c] = 0;
3697         }
3698         /* Convert the all bands */
3699         if (supportsAlpha) {
3700             for (y=0; y < rasterP->height; y++) {
3701                 outP = lineOutP;
3702                 for (x=0; x < rasterP->width; x++) {
3703                     *outP |= (*inP<<loff[a]>>roff[a])&
3704                         rasterP->sppsm.maskArray[a];
3705                     inP++;
3706                     for (c=0; c < rasterP->numBands-1; c++, inP++) {
3707                         /* Not correct.  Might need to unpremult, shift, etc */
3708                         *outP |= (*inP<<loff[c]>>roff[c])&
3709                             rasterP->sppsm.maskArray[c];
3710                     }
3711                     outP++;
3712                 }
3713                 lineOutP += rasterP->scanlineStride;
3714             }
3715         }
3716         else {
3717             for (y=0; y < rasterP->height; y++) {
3718                 outP = lineOutP;
3719                 for (x=0; x < rasterP->width; x++) {
3720                     inP++;
3721                     for (c=0; c < rasterP->numBands; c++, inP++) {
3722                         /* Not correct.  Might need to unpremult, shift, etc */
3723                         *outP |= (*inP<<loff[c]>>roff[c])&rasterP->sppsm.maskArray[c];
3724                     }
3725                     outP++;
3726                 }
3727                 lineOutP += rasterP->scanlineStride;
3728             }
3729         }
3730     }
3731     else {
3732         c = component;
3733         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3734         if (loff[0] < 0) {
3735             roff[0] = -loff[0];
3736             loff[0] = 0;
3737         }
3738         else roff[c] = 0;
3739         for (y=0; y < rasterP->height; y++) {
3740             outP = lineOutP;
3741             for (x=0; x < rasterP->width; x++, inP++) {
3742                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3743                 outP++;
3744             }
3745             lineOutP += rasterP->scanlineStride;
3746         }
3747     }
3748 
3749     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3750 
3751     return 0;
3752 }
3753 
3754 /* This routine is expecting a IntegerComponentRaster with a PackedColorModel*/
3755 static int setPackedICRdefault(JNIEnv *env, RasterS_t *rasterP,
3756                                int component, unsigned char *inDataP,
3757                                int supportsAlpha)
3758 {
3759     int x, y, c;
3760     unsigned char *inP = inDataP;
3761     unsigned int *lineOutP, *outP;
3762     jarray jOutDataP;
3763     jint   *outDataP;
3764     int loff[MAX_NUMBANDS], roff[MAX_NUMBANDS];
3765     int a = rasterP->numBands - 1;
3766 
3767     if (rasterP->numBands > MAX_NUMBANDS) {
3768         return -1;
3769     }
3770 
3771     /* Grab data ptr, strides, offsets from raster */
3772     jOutDataP = (*env)->GetObjectField(env, rasterP->jraster, g_ICRdataID);
3773     outDataP = (*env)->GetPrimitiveArrayCritical(env, jOutDataP, 0);
3774     if (outDataP == NULL) {
3775         return -1;
3776     }
3777     lineOutP =  (unsigned int *)outDataP + rasterP->chanOffsets[0];
3778 
3779     if (component < 0) {
3780         for (c=0; c < rasterP->numBands; c++) {
3781             loff[c] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3782             if (loff[c] < 0) {
3783                 roff[c] = -loff[c];
3784                 loff[c] = 0;
3785             }
3786             else roff[c] = 0;
3787         }
3788         /* Convert the all bands */
3789         if (supportsAlpha) {
3790             for (y=0; y < rasterP->height; y++) {
3791                 outP = lineOutP;
3792                 for (x=0; x < rasterP->width; x++) {
3793                     *outP |= (*inP<<loff[a]>>roff[a])&
3794                         rasterP->sppsm.maskArray[a];
3795                     inP++;
3796                     for (c=0; c < rasterP->numBands-1; c++, inP++) {
3797                         /* Not correct.  Might need to unpremult, shift, etc */
3798                         *outP |= (*inP<<loff[c]>>roff[c])&
3799                             rasterP->sppsm.maskArray[c];
3800                     }
3801                     outP++;
3802                 }
3803                 lineOutP += rasterP->scanlineStride;
3804             }
3805         }
3806         else {
3807             for (y=0; y < rasterP->height; y++) {
3808                 outP = lineOutP;
3809                 for (x=0; x < rasterP->width; x++) {
3810                     inP++;
3811                     for (c=0; c < rasterP->numBands; c++, inP++) {
3812                         /* Not correct.  Might need to unpremult, shift, etc */
3813                         *outP |= (*inP<<loff[c]>>roff[c])&
3814                             rasterP->sppsm.maskArray[c];
3815                     }
3816                     outP++;
3817                 }
3818                 lineOutP += rasterP->scanlineStride;
3819             }
3820         }
3821     }
3822     else {
3823         c = component;
3824         loff[0] = rasterP->sppsm.offsets[c] + (rasterP->sppsm.nBits[c]-8);
3825         if (loff[0] < 0) {
3826             roff[0] = -loff[0];
3827             loff[0] = 0;
3828         }
3829         else roff[c] = 0;
3830 
3831         for (y=0; y < rasterP->height; y++) {
3832             outP = lineOutP;
3833             for (x=0; x < rasterP->width; x++, inP++) {
3834                 *outP |= (*inP<<loff[0]>>roff[0])&rasterP->sppsm.maskArray[c];
3835                 outP++;
3836             }
3837             lineOutP += rasterP->scanlineStride;
3838         }
3839     }
3840 
3841     (*env)->ReleasePrimitiveArrayCritical(env, jOutDataP, outDataP, JNI_ABORT);
3842 
3843     return 0;
3844 }
3845 
3846 /* This is temporary code.  Should go away when there is better color
3847  * conversion code available.
3848  * REMIND:  Ignoring alpha
3849  */
3850 /* returns the absolute value x */
3851 #define ABS(x) ((x) < 0 ? -(x) : (x))
3852 #define CLIP(val,min,max)       ((val < min) ? min : ((val > max) ? max : val))
3853 
3854 static int
3855 colorMatch(int r, int g, int b, int a, unsigned char *argb, int numColors) {
3856     int besti = 0;
3857     int mindist, i, t, d;
3858     unsigned char red, green, blue;
3859 
3860     r = CLIP(r, 0, 255);
3861     g = CLIP(g, 0, 255);
3862     b = CLIP(b, 0, 255);
3863 
3864     /* look for pure gray match */
3865     if ((r == g) && (g == b)) {
3866         mindist = 256;
3867         for (i = 0 ; i < numColors ; i++, argb+=4) {
3868             red = argb[1];
3869             green = argb[2];
3870             blue = argb[3];
3871             if (! ((red == green) && (green == blue)) ) {
3872                 continue;
3873             }
3874             d = ABS(red - r);
3875             if (d == 0)
3876                 return i;
3877             if (d < mindist) {
3878                 besti = i;
3879                 mindist = d;
3880             }
3881         }
3882         return besti;
3883     }
3884 
3885     /* look for non-pure gray match */
3886     mindist = 256 * 256 * 256;
3887     for (i = 0 ; i < numColors ; i++, argb+=4) {
3888         red = argb[1];
3889         green = argb[2];
3890         blue = argb[3];
3891         t = red - r;
3892         d = t * t;
3893         if (d >= mindist) {
3894             continue;
3895         }
3896         t = green - g;
3897         d += t * t;
3898         if (d >= mindist) {
3899             continue;
3900         }
3901         t = blue - b;
3902         d += t * t;
3903         if (d >= mindist) {
3904             continue;
3905         }
3906         if (d == 0)
3907             return i;
3908         if (d < mindist) {
3909             besti = i;
3910             mindist = d;
3911         }
3912     }
3913 
3914     return besti;
3915 }