Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c
41159 views
1
/*
2
* Copyright (c) 1997, 2014, 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 "awt_parseImage.h"
29
#include "imageInitIDs.h"
30
#include "java_awt_Transparency.h"
31
#include "java_awt_image_BufferedImage.h"
32
#include "sun_awt_image_IntegerComponentRaster.h"
33
#include "sun_awt_image_ImagingLib.h"
34
#include "java_awt_color_ColorSpace.h"
35
#include "awt_Mlib.h"
36
#include "safe_alloc.h"
37
#include "safe_math.h"
38
39
static int setHints(JNIEnv *env, BufImageS_t *imageP);
40
41
42
43
/* Parse the buffered image. All of the raster information is returned in the
44
* imagePP structure.
45
*
46
* The handleCustom parameter specifies whether or not the caller
47
* can use custom channels. If it is false and a custom channel
48
* is encountered, the returned value will be 0 and all structures
49
* will be deallocated.
50
*
51
* Return value:
52
* -1: Exception
53
* 0: Can't do it.
54
* 1: Success
55
*/
56
int awt_parseImage(JNIEnv *env, jobject jimage, BufImageS_t **imagePP,
57
int handleCustom) {
58
BufImageS_t *imageP;
59
int status;
60
jobject jraster;
61
jobject jcmodel;
62
63
/* Make sure the image exists */
64
if (JNU_IsNull(env, jimage)) {
65
JNU_ThrowNullPointerException(env, "null BufferedImage object");
66
return -1;
67
}
68
69
if ((imageP = (BufImageS_t *) calloc(1, sizeof(BufImageS_t))) == NULL) {
70
JNU_ThrowOutOfMemoryError(env, "Out of memory");
71
return -1;
72
}
73
imageP->jimage = jimage;
74
75
/* Retrieve the raster */
76
if ((jraster = (*env)->GetObjectField(env, jimage,
77
g_BImgRasterID)) == NULL) {
78
free((void *) imageP);
79
JNU_ThrowNullPointerException(env, "null Raster object");
80
return 0;
81
}
82
83
/* Retrieve the image type */
84
imageP->imageType = (*env)->GetIntField(env, jimage, g_BImgTypeID);
85
86
/* Parse the raster */
87
if ((status = awt_parseRaster(env, jraster, &imageP->raster)) <= 0) {
88
free((void *)imageP);
89
return status;
90
}
91
92
/* Retrieve the color model */
93
if ((jcmodel = (*env)->GetObjectField(env, jimage, g_BImgCMID)) == NULL) {
94
free((void *) imageP);
95
JNU_ThrowNullPointerException(env, "null Raster object");
96
return 0;
97
}
98
99
/* Parse the color model */
100
if ((status = awt_parseColorModel(env, jcmodel, imageP->imageType,
101
&imageP->cmodel)) <= 0) {
102
awt_freeParsedRaster(&imageP->raster, FALSE);
103
free((void *)imageP);
104
return 0;
105
}
106
107
/* Set hints */
108
if ((status = setHints(env, imageP)) <= 0) {
109
awt_freeParsedImage(imageP, TRUE);
110
return 0;
111
}
112
113
*imagePP = imageP;
114
115
return status;
116
}
117
118
/* Verifies whether the channel offsets are sane and correspond to the type of
119
* the raster.
120
*
121
* Return value:
122
* 0: Failure: channel offsets are invalid
123
* 1: Success
124
*/
125
static int checkChannelOffsets(RasterS_t *rasterP, int dataArrayLength) {
126
int i, lastPixelOffset, lastScanOffset;
127
switch (rasterP->rasterType) {
128
case COMPONENT_RASTER_TYPE:
129
if (!SAFE_TO_MULT(rasterP->height, rasterP->scanlineStride)) {
130
return 0;
131
}
132
if (!SAFE_TO_MULT(rasterP->width, rasterP->pixelStride)) {
133
return 0;
134
}
135
136
lastScanOffset = (rasterP->height - 1) * rasterP->scanlineStride;
137
lastPixelOffset = (rasterP->width - 1) * rasterP->pixelStride;
138
139
140
if (!SAFE_TO_ADD(lastPixelOffset, lastScanOffset)) {
141
return 0;
142
}
143
144
lastPixelOffset += lastScanOffset;
145
146
for (i = 0; i < rasterP->numDataElements; i++) {
147
int off = rasterP->chanOffsets[i];
148
int size = lastPixelOffset + off;
149
150
if (off < 0 || !SAFE_TO_ADD(lastPixelOffset, off)) {
151
return 0;
152
}
153
154
if (size < lastPixelOffset || size >= dataArrayLength) {
155
// an overflow, or insufficient buffer capacity
156
return 0;
157
}
158
}
159
return 1;
160
case BANDED_RASTER_TYPE:
161
// NB:caller does not support the banded rasters yet,
162
// so this branch of the code must be re-defined in
163
// order to provide valid criteria for the data offsets
164
// verification, when/if banded rasters will be supported.
165
// At the moment, we prohibit banded rasters as well.
166
return 0;
167
default:
168
// PACKED_RASTER_TYPE: does not support channel offsets
169
// UNKNOWN_RASTER_TYPE: should not be used, likely indicates an error
170
return 0;
171
}
172
}
173
174
/* Parse the raster. All of the raster information is returned in the
175
* rasterP structure.
176
*
177
* Return value:
178
* -1: Exception
179
* 0: Can't do it (Custom channel)
180
* 1: Success
181
*/
182
int awt_parseRaster(JNIEnv *env, jobject jraster, RasterS_t *rasterP) {
183
jobject joffs = NULL;
184
/* int status;*/
185
jclass singlePixelPackedSampleModelClass = NULL;
186
jclass integerComponentRasterClass = NULL;
187
jclass byteComponentRasterClass = NULL;
188
jclass shortComponentRasterClass = NULL;
189
jclass bytePackedRasterClass = NULL;
190
191
if (JNU_IsNull(env, jraster)) {
192
JNU_ThrowNullPointerException(env, "null Raster object");
193
return -1;
194
}
195
196
rasterP->jraster = jraster;
197
rasterP->width = (*env)->GetIntField(env, jraster, g_RasterWidthID);
198
rasterP->height = (*env)->GetIntField(env, jraster, g_RasterHeightID);
199
rasterP->numDataElements = (*env)->GetIntField(env, jraster,
200
g_RasterNumDataElementsID);
201
rasterP->numBands = (*env)->GetIntField(env, jraster,
202
g_RasterNumBandsID);
203
204
rasterP->baseOriginX = (*env)->GetIntField(env, jraster,
205
g_RasterBaseOriginXID);
206
rasterP->baseOriginY = (*env)->GetIntField(env, jraster,
207
g_RasterBaseOriginYID);
208
rasterP->minX = (*env)->GetIntField(env, jraster, g_RasterMinXID);
209
rasterP->minY = (*env)->GetIntField(env, jraster, g_RasterMinYID);
210
211
rasterP->jsampleModel = (*env)->GetObjectField(env, jraster,
212
g_RasterSampleModelID);
213
214
if (JNU_IsNull(env, rasterP->jsampleModel)) {
215
JNU_ThrowNullPointerException(env, "null Raster object");
216
return -1;
217
}
218
219
// make sure that the raster type is initialized
220
rasterP->rasterType = UNKNOWN_RASTER_TYPE;
221
222
if (rasterP->numBands <= 0 ||
223
rasterP->numBands > MAX_NUMBANDS)
224
{
225
/*
226
* we can't handle such kind of rasters due to limitations
227
* of SPPSampleModelS_t structure and expand/set methods.
228
*/
229
return 0;
230
}
231
232
rasterP->sppsm.isUsed = 0;
233
234
singlePixelPackedSampleModelClass = (*env)->FindClass(env,
235
"java/awt/image/SinglePixelPackedSampleModel");
236
CHECK_NULL_RETURN(singlePixelPackedSampleModelClass, -1);
237
if ((*env)->IsInstanceOf(env, rasterP->jsampleModel,
238
singlePixelPackedSampleModelClass)) {
239
jobject jmask, joffs, jnbits;
240
241
rasterP->sppsm.isUsed = 1;
242
243
rasterP->sppsm.maxBitSize = (*env)->GetIntField(env,
244
rasterP->jsampleModel,
245
g_SPPSMmaxBitID);
246
jmask = (*env)->GetObjectField(env, rasterP->jsampleModel,
247
g_SPPSMmaskArrID);
248
joffs = (*env)->GetObjectField(env, rasterP->jsampleModel,
249
g_SPPSMmaskOffID);
250
jnbits = (*env)->GetObjectField(env, rasterP->jsampleModel,
251
g_SPPSMnBitsID);
252
if (jmask == NULL || joffs == NULL || jnbits == NULL ||
253
rasterP->sppsm.maxBitSize < 0)
254
{
255
JNU_ThrowInternalError(env, "Can't grab SPPSM fields");
256
return -1;
257
}
258
(*env)->GetIntArrayRegion(env, jmask, 0,
259
rasterP->numBands, rasterP->sppsm.maskArray);
260
(*env)->GetIntArrayRegion(env, joffs, 0,
261
rasterP->numBands, rasterP->sppsm.offsets);
262
(*env)->GetIntArrayRegion(env, jnbits, 0,
263
rasterP->numBands, rasterP->sppsm.nBits);
264
265
}
266
rasterP->baseRasterWidth = (*env)->GetIntField(env, rasterP->jsampleModel,
267
g_SMWidthID);
268
rasterP->baseRasterHeight = (*env)->GetIntField(env,
269
rasterP->jsampleModel,
270
g_SMHeightID);
271
272
integerComponentRasterClass = (*env)->FindClass(env, "sun/awt/image/IntegerComponentRaster");
273
CHECK_NULL_RETURN(integerComponentRasterClass, -1);
274
byteComponentRasterClass = (*env)->FindClass(env, "sun/awt/image/ByteComponentRaster");
275
CHECK_NULL_RETURN(byteComponentRasterClass, -1);
276
shortComponentRasterClass = (*env)->FindClass(env,"sun/awt/image/ShortComponentRaster");
277
CHECK_NULL_RETURN(shortComponentRasterClass, -1);
278
bytePackedRasterClass = (*env)->FindClass(env, "sun/awt/image/BytePackedRaster");
279
CHECK_NULL_RETURN(bytePackedRasterClass, -1);
280
if ((*env)->IsInstanceOf(env, jraster, integerComponentRasterClass)){
281
rasterP->jdata = (*env)->GetObjectField(env, jraster, g_ICRdataID);
282
rasterP->dataType = INT_DATA_TYPE;
283
rasterP->dataSize = 4;
284
rasterP->dataIsShared = TRUE;
285
rasterP->rasterType = COMPONENT_RASTER_TYPE;
286
rasterP->type = (*env)->GetIntField(env, jraster, g_ICRtypeID);
287
rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_ICRscanstrID);
288
rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_ICRpixstrID);
289
joffs = (*env)->GetObjectField(env, jraster, g_ICRdataOffsetsID);
290
}
291
else if ((*env)->IsInstanceOf(env, jraster, byteComponentRasterClass)){
292
rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BCRdataID);
293
rasterP->dataType = BYTE_DATA_TYPE;
294
rasterP->dataSize = 1;
295
rasterP->dataIsShared = TRUE;
296
rasterP->rasterType = COMPONENT_RASTER_TYPE;
297
rasterP->type = (*env)->GetIntField(env, jraster, g_BCRtypeID);
298
rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BCRscanstrID);
299
rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BCRpixstrID);
300
joffs = (*env)->GetObjectField(env, jraster, g_BCRdataOffsetsID);
301
}
302
else if ((*env)->IsInstanceOf(env, jraster, shortComponentRasterClass)){
303
rasterP->jdata = (*env)->GetObjectField(env, jraster, g_SCRdataID);
304
rasterP->dataType = SHORT_DATA_TYPE;
305
rasterP->dataSize = 2;
306
rasterP->dataIsShared = TRUE;
307
rasterP->rasterType = COMPONENT_RASTER_TYPE;
308
rasterP->type = (*env)->GetIntField(env, jraster, g_SCRtypeID);
309
rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_SCRscanstrID);
310
rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_SCRpixstrID);
311
joffs = (*env)->GetObjectField(env, jraster, g_SCRdataOffsetsID);
312
}
313
else if ((*env)->IsInstanceOf(env, jraster, bytePackedRasterClass)){
314
rasterP->rasterType = PACKED_RASTER_TYPE;
315
rasterP->dataType = BYTE_DATA_TYPE;
316
rasterP->dataSize = 1;
317
rasterP->scanlineStride = (*env)->GetIntField(env, jraster, g_BPRscanstrID);
318
rasterP->pixelStride = (*env)->GetIntField(env, jraster, g_BPRpixstrID);
319
rasterP->jdata = (*env)->GetObjectField(env, jraster, g_BPRdataID);
320
rasterP->type = (*env)->GetIntField(env, jraster, g_BPRtypeID);
321
rasterP->chanOffsets = NULL;
322
if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {
323
rasterP->chanOffsets =
324
(jint *)malloc(rasterP->numDataElements * sizeof(jint));
325
}
326
if (rasterP->chanOffsets == NULL) {
327
/* Out of memory */
328
JNU_ThrowOutOfMemoryError(env, "Out of memory");
329
return -1;
330
}
331
rasterP->chanOffsets[0] = (*env)->GetIntField(env, jraster, g_BPRdataBitOffsetID);
332
rasterP->dataType = BYTE_DATA_TYPE;
333
}
334
else {
335
rasterP->type = sun_awt_image_IntegerComponentRaster_TYPE_CUSTOM;
336
rasterP->dataType = UNKNOWN_DATA_TYPE;
337
rasterP->rasterType = UNKNOWN_RASTER_TYPE;
338
rasterP->chanOffsets = NULL;
339
/* Custom raster */
340
return 0;
341
}
342
343
// do basic validation of the raster structure
344
if (rasterP->width <= 0 || rasterP->height <= 0 ||
345
rasterP->pixelStride <= 0 || rasterP->scanlineStride <= 0)
346
{
347
// invalid raster
348
return -1;
349
}
350
351
// channel (data) offsets
352
switch (rasterP->rasterType) {
353
case COMPONENT_RASTER_TYPE:
354
case BANDED_RASTER_TYPE: // note that this routine does not support banded rasters at the moment
355
// get channel (data) offsets
356
rasterP->chanOffsets = NULL;
357
if (SAFE_TO_ALLOC_2(rasterP->numDataElements, sizeof(jint))) {
358
rasterP->chanOffsets =
359
(jint *)malloc(rasterP->numDataElements * sizeof(jint));
360
}
361
if (rasterP->chanOffsets == NULL) {
362
/* Out of memory */
363
JNU_ThrowOutOfMemoryError(env, "Out of memory");
364
return -1;
365
}
366
(*env)->GetIntArrayRegion(env, joffs, 0, rasterP->numDataElements,
367
rasterP->chanOffsets);
368
if (rasterP->jdata == NULL) {
369
// unable to verify the raster
370
return -1;
371
}
372
// verify whether channel offsets look sane
373
if (!checkChannelOffsets(rasterP, (*env)->GetArrayLength(env, rasterP->jdata))) {
374
return -1;
375
}
376
break;
377
default:
378
; // PACKED_RASTER_TYPE does not use the channel offsets.
379
}
380
381
/* additional check for sppsm fields validity: make sure that
382
* size of raster samples doesn't exceed the data type capacity.
383
*/
384
if (rasterP->dataType > UNKNOWN_DATA_TYPE && /* data type has been recognized */
385
rasterP->sppsm.maxBitSize > 0 && /* raster has SPP sample model */
386
rasterP->sppsm.maxBitSize > (rasterP->dataSize * 8))
387
{
388
JNU_ThrowInternalError(env, "Raster samples are too big");
389
return -1;
390
}
391
392
#if 0
393
fprintf(stderr,"---------------------\n");
394
fprintf(stderr,"Width : %d\n",rasterP->width);
395
fprintf(stderr,"Height : %d\n",rasterP->height);
396
fprintf(stderr,"X : %d\n",rasterP->x);
397
fprintf(stderr,"Y : %d\n",rasterP->y);
398
fprintf(stderr,"numC : %d\n",rasterP->numDataElements);
399
fprintf(stderr,"SS : %d\n",rasterP->scanlineStride);
400
fprintf(stderr,"PS : %d\n",rasterP->pixelStride);
401
fprintf(stderr,"CO : %d\n",rasterP->chanOffsets);
402
fprintf(stderr,"shared?: %d\n",rasterP->dataIsShared);
403
fprintf(stderr,"RasterT: %d\n",rasterP->rasterType);
404
fprintf(stderr,"DataT : %d\n",rasterP->dataType);
405
fprintf(stderr,"---------------------\n");
406
#endif
407
408
return 1;
409
}
410
411
static int getColorModelType(JNIEnv *env, jobject jcmodel) {
412
jclass colorModelClass;
413
414
colorModelClass = (*env)->FindClass(env,
415
"java/awt/image/IndexColorModel");
416
CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);
417
418
if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass))
419
{
420
return INDEX_CM_TYPE;
421
}
422
423
colorModelClass = (*env)->FindClass(env,
424
"java/awt/image/PackedColorModel");
425
CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);
426
if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass))
427
{
428
colorModelClass = (*env)->FindClass(env,
429
"java/awt/image/DirectColorModel");
430
CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);
431
if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass)) {
432
return DIRECT_CM_TYPE;
433
}
434
else {
435
return PACKED_CM_TYPE;
436
}
437
}
438
colorModelClass = (*env)->FindClass(env,
439
"java/awt/image/ComponentColorModel");
440
CHECK_NULL_RETURN(colorModelClass, UNKNOWN_CM_TYPE);
441
if ((*env)->IsInstanceOf(env, jcmodel, colorModelClass))
442
{
443
return COMPONENT_CM_TYPE;
444
}
445
446
return UNKNOWN_CM_TYPE;
447
}
448
449
int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType,
450
ColorModelS_t *cmP) {
451
/*jmethodID jID; */
452
jobject jnBits;
453
jsize nBitsLength;
454
455
int i;
456
static jobject s_jdefCM = NULL;
457
458
if (JNU_IsNull(env, jcmodel)) {
459
JNU_ThrowNullPointerException(env, "null ColorModel object");
460
return -1;
461
}
462
463
cmP->jcmodel = jcmodel;
464
465
cmP->jcspace = (*env)->GetObjectField(env, jcmodel, g_CMcspaceID);
466
467
cmP->numComponents = (*env)->GetIntField(env, jcmodel,
468
g_CMnumComponentsID);
469
cmP->supportsAlpha = (*env)->GetBooleanField(env, jcmodel,
470
g_CMsuppAlphaID);
471
cmP->isAlphaPre = (*env)->GetBooleanField(env,jcmodel,
472
g_CMisAlphaPreID);
473
cmP->transparency = (*env)->GetIntField(env, jcmodel,
474
g_CMtransparencyID);
475
476
jnBits = (*env)->GetObjectField(env, jcmodel, g_CMnBitsID);
477
if (jnBits == NULL) {
478
JNU_ThrowNullPointerException(env, "null nBits structure in CModel");
479
return -1;
480
}
481
482
nBitsLength = (*env)->GetArrayLength(env, jnBits);
483
if (nBitsLength != cmP->numComponents) {
484
// invalid number of components?
485
return -1;
486
}
487
488
cmP->nBits = NULL;
489
if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) {
490
cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint));
491
}
492
493
if (cmP->nBits == NULL){
494
JNU_ThrowOutOfMemoryError(env, "Out of memory");
495
return -1;
496
}
497
(*env)->GetIntArrayRegion(env, jnBits, 0, cmP->numComponents,
498
cmP->nBits);
499
cmP->maxNbits = 0;
500
for (i=0; i < cmP->numComponents; i++) {
501
if (cmP->maxNbits < cmP->nBits[i]) {
502
cmP->maxNbits = cmP->nBits[i];
503
}
504
}
505
506
cmP->is_sRGB = (*env)->GetBooleanField(env, cmP->jcmodel, g_CMis_sRGBID);
507
508
cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID);
509
510
cmP->cmType = getColorModelType(env, jcmodel);
511
JNU_CHECK_EXCEPTION_RETURN(env, -1);
512
513
cmP->isDefaultCM = FALSE;
514
cmP->isDefaultCompatCM = FALSE;
515
516
/* look for standard cases */
517
if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB) {
518
cmP->isDefaultCM = TRUE;
519
cmP->isDefaultCompatCM = TRUE;
520
} else if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
521
imageType == java_awt_image_BufferedImage_TYPE_INT_RGB ||
522
imageType == java_awt_image_BufferedImage_TYPE_INT_BGR ||
523
imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||
524
imageType == java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE)
525
{
526
cmP->isDefaultCompatCM = TRUE;
527
}
528
else {
529
/* Figure out if this is the default CM */
530
if (s_jdefCM == NULL) {
531
jobject defCM;
532
jclass jcm = (*env)->FindClass(env, "java/awt/image/ColorModel");
533
CHECK_NULL_RETURN(jcm, -1);
534
defCM = (*env)->CallStaticObjectMethod(env, jcm,
535
g_CMgetRGBdefaultMID, NULL);
536
s_jdefCM = (*env)->NewGlobalRef(env, defCM);
537
if (defCM == NULL || s_jdefCM == NULL) {
538
(*env)->ExceptionClear(env);
539
JNU_ThrowNullPointerException(env, "Unable to find default CM");
540
return -1;
541
}
542
}
543
cmP->isDefaultCM = ((*env)->IsSameObject(env, s_jdefCM, jcmodel));
544
cmP->isDefaultCompatCM = cmP->isDefaultCM;
545
}
546
547
/* check whether image attributes correspond to default cm */
548
if (cmP->isDefaultCompatCM) {
549
if (cmP->csType != java_awt_color_ColorSpace_TYPE_RGB ||
550
!cmP->is_sRGB)
551
{
552
return -1;
553
}
554
555
for (i = 0; i < cmP->numComponents; i++) {
556
if (cmP->nBits[i] != 8) {
557
return -1;
558
}
559
}
560
}
561
562
/* Get index color model attributes */
563
if (imageType == java_awt_image_BufferedImage_TYPE_BYTE_INDEXED ||
564
cmP->cmType == INDEX_CM_TYPE)
565
{
566
cmP->transIdx = (*env)->GetIntField(env, jcmodel, g_ICMtransIdxID);
567
cmP->mapSize = (*env)->GetIntField(env, jcmodel, g_ICMmapSizeID);
568
cmP->jrgb = (*env)->GetObjectField(env, jcmodel, g_ICMrgbID);
569
if (cmP->transIdx == -1) {
570
/* Need to find the transparent index */
571
int *rgb = (int *) (*env)->GetPrimitiveArrayCritical(env,
572
cmP->jrgb,
573
NULL);
574
if (rgb == NULL) {
575
return -1;
576
}
577
for (i=0; i < cmP->mapSize; i++) {
578
if ((rgb[i]&0xff000000) == 0) {
579
cmP->transIdx = i;
580
break;
581
}
582
}
583
(*env)->ReleasePrimitiveArrayCritical(env, cmP->jrgb, rgb,
584
JNI_ABORT);
585
if (cmP->transIdx == -1) {
586
/* Now what? No transparent pixel... */
587
cmP->transIdx = 0;
588
}
589
}
590
}
591
592
return 1;
593
}
594
595
void awt_freeParsedRaster(RasterS_t *rasterP, int freeRasterP) {
596
if (rasterP->chanOffsets) {
597
free((void *) rasterP->chanOffsets);
598
}
599
600
if (freeRasterP) {
601
free((void *) rasterP);
602
}
603
}
604
605
void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP) {
606
if (imageP->hints.colorOrder) {
607
free ((void *) imageP->hints.colorOrder);
608
}
609
610
if (imageP->cmodel.nBits) {
611
free ((void *) imageP->cmodel.nBits);
612
}
613
614
/* Free the raster */
615
awt_freeParsedRaster(&imageP->raster, FALSE);
616
617
if (freeImageP) {
618
free((void *) imageP);
619
}
620
}
621
622
static void
623
awt_getBIColorOrder(int type, int *colorOrder) {
624
switch(type) {
625
case java_awt_image_BufferedImage_TYPE_INT_ARGB:
626
case java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE:
627
#ifdef _LITTLE_ENDIAN
628
colorOrder[0] = 2;
629
colorOrder[1] = 1;
630
colorOrder[2] = 0;
631
colorOrder[3] = 3;
632
#else
633
colorOrder[0] = 1;
634
colorOrder[1] = 2;
635
colorOrder[2] = 3;
636
colorOrder[3] = 0;
637
#endif
638
break;
639
case java_awt_image_BufferedImage_TYPE_INT_BGR:
640
#ifdef _LITTLE_ENDIAN
641
colorOrder[0] = 0;
642
colorOrder[1] = 1;
643
colorOrder[2] = 2;
644
#else
645
colorOrder[0] = 3;
646
colorOrder[1] = 2;
647
colorOrder[2] = 1;
648
#endif
649
break;
650
case java_awt_image_BufferedImage_TYPE_INT_RGB:
651
#ifdef _LITTLE_ENDIAN
652
colorOrder[0] = 2;
653
colorOrder[1] = 1;
654
colorOrder[2] = 0;
655
#else
656
colorOrder[0] = 1;
657
colorOrder[1] = 2;
658
colorOrder[2] = 3;
659
#endif
660
break;
661
case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR:
662
case java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE:
663
colorOrder[0] = 3;
664
colorOrder[1] = 2;
665
colorOrder[2] = 1;
666
colorOrder[3] = 0;
667
break;
668
case java_awt_image_BufferedImage_TYPE_3BYTE_BGR:
669
colorOrder[0] = 2;
670
colorOrder[1] = 1;
671
colorOrder[2] = 0;
672
break;
673
case java_awt_image_BufferedImage_TYPE_USHORT_565_RGB:
674
case java_awt_image_BufferedImage_TYPE_USHORT_555_RGB:
675
colorOrder[0] = 0;
676
colorOrder[1] = 1;
677
colorOrder[2] = 2;
678
break;
679
case java_awt_image_BufferedImage_TYPE_BYTE_GRAY:
680
case java_awt_image_BufferedImage_TYPE_USHORT_GRAY:
681
case java_awt_image_BufferedImage_TYPE_BYTE_BINARY:
682
case java_awt_image_BufferedImage_TYPE_BYTE_INDEXED:
683
colorOrder[0] = 0;
684
break;
685
}
686
}
687
688
static int
689
setHints(JNIEnv *env, BufImageS_t *imageP) {
690
HintS_t *hintP = &imageP->hints;
691
RasterS_t *rasterP = &imageP->raster;
692
ColorModelS_t *cmodelP = &imageP->cmodel;
693
int imageType = imageP->imageType;
694
695
// check whether raster and color model are compatible
696
if (cmodelP->numComponents != rasterP->numBands) {
697
if (cmodelP->cmType != INDEX_CM_TYPE) {
698
return -1;
699
}
700
}
701
702
hintP->numChans = imageP->cmodel.numComponents;
703
hintP->colorOrder = NULL;
704
if (SAFE_TO_ALLOC_2(hintP->numChans, sizeof(int))) {
705
hintP->colorOrder = (int *)malloc(hintP->numChans * sizeof(int));
706
}
707
if (hintP->colorOrder == NULL) {
708
JNU_ThrowOutOfMemoryError(env, "Out of memory");
709
return -1;
710
}
711
if (imageType != java_awt_image_BufferedImage_TYPE_CUSTOM) {
712
awt_getBIColorOrder(imageType, hintP->colorOrder);
713
}
714
if (imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB ||
715
imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE ||
716
imageType == java_awt_image_BufferedImage_TYPE_INT_RGB)
717
{
718
hintP->channelOffset = rasterP->chanOffsets[0];
719
/* These hints are #bytes */
720
hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
721
hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
722
hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
723
hintP->packing = BYTE_INTERLEAVED;
724
} else if (imageType ==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR ||
725
imageType==java_awt_image_BufferedImage_TYPE_4BYTE_ABGR_PRE||
726
imageType == java_awt_image_BufferedImage_TYPE_3BYTE_BGR ||
727
imageType == java_awt_image_BufferedImage_TYPE_INT_BGR)
728
{
729
if (imageType == java_awt_image_BufferedImage_TYPE_INT_BGR) {
730
hintP->channelOffset = rasterP->chanOffsets[0];
731
}
732
else {
733
hintP->channelOffset = rasterP->chanOffsets[hintP->numChans-1];
734
}
735
hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
736
hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
737
hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
738
hintP->packing = BYTE_INTERLEAVED;
739
} else if (imageType==java_awt_image_BufferedImage_TYPE_USHORT_565_RGB ||
740
imageType==java_awt_image_BufferedImage_TYPE_USHORT_555_RGB) {
741
hintP->needToExpand = TRUE;
742
hintP->expandToNbits = 8;
743
hintP->packing = PACKED_SHORT_INTER;
744
} else if (cmodelP->cmType == INDEX_CM_TYPE) {
745
int i;
746
hintP->numChans = 1;
747
hintP->channelOffset = rasterP->chanOffsets[0];
748
hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
749
hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
750
hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
751
switch(rasterP->dataType ) {
752
case BYTE_DATA_TYPE:
753
if (rasterP->rasterType == PACKED_RASTER_TYPE) {
754
hintP->needToExpand = TRUE;
755
hintP->expandToNbits = 8;
756
hintP->packing = BYTE_PACKED_BAND;
757
}
758
else {
759
hintP->packing = BYTE_SINGLE_BAND;
760
}
761
break;
762
case SHORT_DATA_TYPE:
763
hintP->packing = SHORT_SINGLE_BAND;
764
break;
765
case INT_DATA_TYPE:
766
default:
767
hintP->packing = UNKNOWN_PACKING;
768
break;
769
}
770
for (i=0; i < hintP->numChans; i++) {
771
hintP->colorOrder[i] = i;
772
}
773
}
774
else if (cmodelP->cmType == COMPONENT_CM_TYPE) {
775
/* Figure out if it is interleaved */
776
int bits=1;
777
int i;
778
int low = rasterP->chanOffsets[0];
779
int diff;
780
int banded = 0;
781
for (i=1; i < hintP->numChans; i++) {
782
if (rasterP->chanOffsets[i] < low) {
783
low = rasterP->chanOffsets[i];
784
}
785
}
786
for (i=1; i < hintP->numChans; i++) {
787
diff = rasterP->chanOffsets[i]-low;
788
if (diff < hintP->numChans) {
789
if (bits & (1<<diff)) {
790
/* Overlapping samples */
791
/* Could just copy */
792
return -1;
793
}
794
bits |= (1<<diff);
795
}
796
else if (diff >= rasterP->width) {
797
banded = 1;
798
}
799
/* Ignore the case if bands are overlapping */
800
}
801
hintP->channelOffset = low;
802
hintP->dataOffset = low*rasterP->dataSize;
803
hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
804
hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
805
switch(rasterP->dataType) {
806
case BYTE_DATA_TYPE:
807
hintP->packing = BYTE_COMPONENTS;
808
break;
809
case SHORT_DATA_TYPE:
810
hintP->packing = SHORT_COMPONENTS;
811
break;
812
default:
813
/* Don't handle any other case */
814
return -1;
815
}
816
if (bits == ((1<<hintP->numChans)-1)) {
817
hintP->packing |= INTERLEAVED;
818
for (i=0; i < hintP->numChans; i++) {
819
hintP->colorOrder[rasterP->chanOffsets[i]-low] = i;
820
}
821
}
822
else if (banded == 1) {
823
int bandSize = rasterP->width*rasterP->height;
824
hintP->packing |= BANDED;
825
for (i=0; i < hintP->numChans; i++) {
826
/* REMIND: Not necessarily correct */
827
hintP->colorOrder[(rasterP->chanOffsets[i]-low)%bandSize] = i;
828
}
829
}
830
else {
831
return -1;
832
}
833
}
834
else if (cmodelP->cmType == DIRECT_CM_TYPE || cmodelP->cmType == PACKED_CM_TYPE) {
835
int i;
836
837
/* do some sanity check first: make sure that
838
* - sample model is SinglePixelPackedSampleModel
839
* - number of bands in the raster corresponds to the number
840
* of color components in the color model
841
*/
842
if (!rasterP->sppsm.isUsed ||
843
rasterP->numBands != cmodelP->numComponents)
844
{
845
/* given raster is not compatible with the color model,
846
* so the operation has to be aborted.
847
*/
848
return -1;
849
}
850
851
if (cmodelP->maxNbits > 8) {
852
hintP->needToExpand = TRUE;
853
hintP->expandToNbits = cmodelP->maxNbits;
854
}
855
else {
856
for (i=0; i < rasterP->numBands; i++) {
857
if (!(rasterP->sppsm.offsets[i] % 8)) {
858
hintP->needToExpand = TRUE;
859
hintP->expandToNbits = 8;
860
break;
861
}
862
else {
863
hintP->colorOrder[i] = rasterP->sppsm.offsets[i]>>3;
864
}
865
}
866
}
867
868
hintP->channelOffset = rasterP->chanOffsets[0];
869
hintP->dataOffset = hintP->channelOffset*rasterP->dataSize;
870
hintP->sStride = rasterP->scanlineStride*rasterP->dataSize;
871
hintP->pStride = rasterP->pixelStride*rasterP->dataSize;
872
if (hintP->needToExpand) {
873
switch(rasterP->dataType) {
874
case BYTE_DATA_TYPE:
875
hintP->packing = PACKED_BYTE_INTER;
876
break;
877
case SHORT_DATA_TYPE:
878
hintP->packing = PACKED_SHORT_INTER;
879
break;
880
case INT_DATA_TYPE:
881
hintP->packing = PACKED_INT_INTER;
882
break;
883
default:
884
/* Don't know what it is */
885
return -1;
886
}
887
}
888
else {
889
hintP->packing = BYTE_INTERLEAVED;
890
891
}
892
}
893
else {
894
/* REMIND: Need to handle more cases */
895
return -1;
896
}
897
898
return 1;
899
}
900
901
#define MAX_TO_GRAB (10240)
902
903
typedef union {
904
void *pv;
905
unsigned char *pb;
906
unsigned short *ps;
907
} PixelData_t;
908
909
910
int awt_getPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) {
911
const int w = rasterP->width;
912
const int h = rasterP->height;
913
const int numBands = rasterP->numBands;
914
int y;
915
int i;
916
int maxLines;
917
jobject jsm;
918
int off = 0;
919
jarray jdata = NULL;
920
jobject jdatabuffer;
921
int *dataP;
922
int maxSamples;
923
PixelData_t p;
924
925
if (bufferP == NULL) {
926
return -1;
927
}
928
929
if (rasterP->dataType != BYTE_DATA_TYPE &&
930
rasterP->dataType != SHORT_DATA_TYPE)
931
{
932
return -1;
933
}
934
935
p.pv = bufferP;
936
937
if (!SAFE_TO_MULT(w, numBands)) {
938
return -1;
939
}
940
maxSamples = w * numBands;
941
942
maxLines = maxSamples > MAX_TO_GRAB ? 1 : (MAX_TO_GRAB / maxSamples);
943
if (maxLines > h) {
944
maxLines = h;
945
}
946
947
if (!SAFE_TO_MULT(maxSamples, maxLines)) {
948
return -1;
949
}
950
951
maxSamples *= maxLines;
952
953
jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
954
jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
955
g_RasterDataBufferID);
956
957
jdata = (*env)->NewIntArray(env, maxSamples);
958
if (JNU_IsNull(env, jdata)) {
959
(*env)->ExceptionClear(env);
960
JNU_ThrowOutOfMemoryError(env, "Out of Memory");
961
return -1;
962
}
963
964
for (y = 0; y < h; y += maxLines) {
965
if (y + maxLines > h) {
966
maxLines = h - y;
967
maxSamples = w * numBands * maxLines;
968
}
969
970
(*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID,
971
0, y, w,
972
maxLines, jdata, jdatabuffer);
973
974
if ((*env)->ExceptionOccurred(env)) {
975
(*env)->DeleteLocalRef(env, jdata);
976
return -1;
977
}
978
979
dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
980
NULL);
981
if (dataP == NULL) {
982
(*env)->DeleteLocalRef(env, jdata);
983
return -1;
984
}
985
986
switch (rasterP->dataType) {
987
case BYTE_DATA_TYPE:
988
for (i = 0; i < maxSamples; i ++) {
989
p.pb[off++] = (unsigned char) dataP[i];
990
}
991
break;
992
case SHORT_DATA_TYPE:
993
for (i = 0; i < maxSamples; i ++) {
994
p.ps[off++] = (unsigned short) dataP[i];
995
}
996
break;
997
}
998
999
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
1000
JNI_ABORT);
1001
}
1002
(*env)->DeleteLocalRef(env, jdata);
1003
1004
return 1;
1005
}
1006
1007
int awt_setPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) {
1008
const int w = rasterP->width;
1009
const int h = rasterP->height;
1010
const int numBands = rasterP->numBands;
1011
1012
int y;
1013
int i;
1014
int maxLines;
1015
jobject jsm;
1016
int off = 0;
1017
jarray jdata = NULL;
1018
jobject jdatabuffer;
1019
int *dataP;
1020
int maxSamples;
1021
PixelData_t p;
1022
1023
if (bufferP == NULL) {
1024
return -1;
1025
}
1026
1027
if (rasterP->dataType != BYTE_DATA_TYPE &&
1028
rasterP->dataType != SHORT_DATA_TYPE)
1029
{
1030
return -1;
1031
}
1032
1033
p.pv = bufferP;
1034
1035
if (!SAFE_TO_MULT(w, numBands)) {
1036
return -1;
1037
}
1038
maxSamples = w * numBands;
1039
1040
maxLines = maxSamples > MAX_TO_GRAB ? 1 : (MAX_TO_GRAB / maxSamples);
1041
if (maxLines > h) {
1042
maxLines = h;
1043
}
1044
1045
if (!SAFE_TO_MULT(maxSamples, maxLines)) {
1046
return -1;
1047
}
1048
1049
maxSamples *= maxLines;
1050
1051
jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID);
1052
jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster,
1053
g_RasterDataBufferID);
1054
1055
jdata = (*env)->NewIntArray(env, maxSamples);
1056
if (JNU_IsNull(env, jdata)) {
1057
(*env)->ExceptionClear(env);
1058
JNU_ThrowOutOfMemoryError(env, "Out of Memory");
1059
return -1;
1060
}
1061
1062
for (y = 0; y < h; y += maxLines) {
1063
if (y + maxLines > h) {
1064
maxLines = h - y;
1065
maxSamples = w * numBands * maxLines;
1066
}
1067
dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata,
1068
NULL);
1069
if (dataP == NULL) {
1070
(*env)->DeleteLocalRef(env, jdata);
1071
return -1;
1072
}
1073
1074
switch (rasterP->dataType) {
1075
case BYTE_DATA_TYPE:
1076
for (i = 0; i < maxSamples; i ++) {
1077
dataP[i] = p.pb[off++];
1078
}
1079
break;
1080
case SHORT_DATA_TYPE:
1081
for (i = 0; i < maxSamples; i ++) {
1082
dataP[i] = p.ps[off++];
1083
}
1084
break;
1085
}
1086
1087
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP,
1088
JNI_ABORT);
1089
1090
(*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID,
1091
0, y, w,
1092
maxLines, jdata, jdatabuffer);
1093
1094
if ((*env)->ExceptionOccurred(env)) {
1095
(*env)->DeleteLocalRef(env, jdata);
1096
return -1;
1097
}
1098
}
1099
1100
(*env)->DeleteLocalRef(env, jdata);
1101
1102
return 1;
1103
}
1104
1105