Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c
38918 views
1
/*
2
* Copyright (c) 2007, 2013, 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 <memory.h>
29
#include "sun_java2d_cmm_lcms_LCMS.h"
30
#include "jni_util.h"
31
#include "Trace.h"
32
#include "Disposer.h"
33
#include "lcms2.h"
34
#include "jlong.h"
35
36
37
#define ALIGNLONG(x) (((x)+3) & ~(3)) // Aligns to DWORD boundary
38
39
#ifdef USE_BIG_ENDIAN
40
#define AdjustEndianess32(a)
41
#else
42
43
static
44
void AdjustEndianess32(cmsUInt8Number *pByte)
45
{
46
cmsUInt8Number temp1;
47
cmsUInt8Number temp2;
48
49
temp1 = *pByte++;
50
temp2 = *pByte++;
51
*(pByte-1) = *pByte;
52
*pByte++ = temp2;
53
*(pByte-3) = *pByte;
54
*pByte = temp1;
55
}
56
57
#endif
58
59
// Transports to properly encoded values - note that icc profiles does use
60
// big endian notation.
61
62
static
63
cmsInt32Number TransportValue32(cmsInt32Number Value)
64
{
65
cmsInt32Number Temp = Value;
66
67
AdjustEndianess32((cmsUInt8Number*) &Temp);
68
return Temp;
69
}
70
71
#define SigMake(a,b,c,d) \
72
( ( ((int) ((unsigned char) (a))) << 24) | \
73
( ((int) ((unsigned char) (b))) << 16) | \
74
( ((int) ((unsigned char) (c))) << 8) | \
75
(int) ((unsigned char) (d)))
76
77
#define TagIdConst(a, b, c, d) \
78
((int) SigMake ((a), (b), (c), (d)))
79
80
#define SigHead TagIdConst('h','e','a','d')
81
82
#define DT_BYTE 0
83
#define DT_SHORT 1
84
#define DT_INT 2
85
#define DT_DOUBLE 3
86
87
/* Default temp profile list size */
88
#define DF_ICC_BUF_SIZE 32
89
90
#define ERR_MSG_SIZE 256
91
92
#ifdef _MSC_VER
93
# ifndef snprintf
94
# define snprintf _snprintf
95
# endif
96
#endif
97
98
typedef struct lcmsProfile_s {
99
cmsHPROFILE pf;
100
} lcmsProfile_t, *lcmsProfile_p;
101
102
typedef union {
103
cmsTagSignature cms;
104
jint j;
105
} TagSignature_t, *TagSignature_p;
106
107
static jfieldID Trans_renderType_fID;
108
static jfieldID Trans_ID_fID;
109
static jfieldID IL_isIntPacked_fID;
110
static jfieldID IL_dataType_fID;
111
static jfieldID IL_pixelType_fID;
112
static jfieldID IL_dataArray_fID;
113
static jfieldID IL_offset_fID;
114
static jfieldID IL_nextRowOffset_fID;
115
static jfieldID IL_width_fID;
116
static jfieldID IL_height_fID;
117
static jfieldID IL_imageAtOnce_fID;
118
119
JavaVM *javaVM;
120
121
void errorHandler(cmsContext ContextID, cmsUInt32Number errorCode,
122
const char *errorText) {
123
JNIEnv *env;
124
char errMsg[ERR_MSG_SIZE];
125
126
int count = snprintf(errMsg, ERR_MSG_SIZE,
127
"LCMS error %d: %s", errorCode, errorText);
128
if (count < 0 || count >= ERR_MSG_SIZE) {
129
count = ERR_MSG_SIZE - 1;
130
}
131
errMsg[count] = 0;
132
133
(*javaVM)->AttachCurrentThread(javaVM, (void**)&env, NULL);
134
JNU_ThrowByName(env, "java/awt/color/CMMException", errMsg);
135
}
136
137
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
138
javaVM = jvm;
139
140
cmsSetLogErrorHandler(errorHandler);
141
return JNI_VERSION_1_6;
142
}
143
144
void LCMS_freeProfile(JNIEnv *env, jlong ptr) {
145
lcmsProfile_p p = (lcmsProfile_p)jlong_to_ptr(ptr);
146
147
if (p != NULL) {
148
if (p->pf != NULL) {
149
cmsCloseProfile(p->pf);
150
}
151
free(p);
152
}
153
}
154
155
void LCMS_freeTransform(JNIEnv *env, jlong ID)
156
{
157
cmsHTRANSFORM sTrans = jlong_to_ptr(ID);
158
/* Passed ID is always valid native ref so there is no check for zero */
159
cmsDeleteTransform(sTrans);
160
}
161
162
/*
163
* Class: sun_java2d_cmm_lcms_LCMS
164
* Method: createNativeTransform
165
* Signature: ([JI)J
166
*/
167
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform
168
(JNIEnv *env, jclass cls, jlongArray profileIDs, jint renderType,
169
jint inFormatter, jboolean isInIntPacked,
170
jint outFormatter, jboolean isOutIntPacked, jobject disposerRef)
171
{
172
cmsHPROFILE _iccArray[DF_ICC_BUF_SIZE];
173
cmsHPROFILE *iccArray = &_iccArray[0];
174
cmsHTRANSFORM sTrans = NULL;
175
int i, j, size;
176
jlong* ids;
177
178
size = (*env)->GetArrayLength (env, profileIDs);
179
ids = (*env)->GetLongArrayElements(env, profileIDs, 0);
180
if (ids == NULL) {
181
// An exception should have already been thrown.
182
return 0L;
183
}
184
185
#ifdef _LITTLE_ENDIAN
186
/* Reversing data packed into int for LE archs */
187
if (isInIntPacked) {
188
inFormatter ^= DOSWAP_SH(1);
189
}
190
if (isOutIntPacked) {
191
outFormatter ^= DOSWAP_SH(1);
192
}
193
#endif
194
195
if (DF_ICC_BUF_SIZE < size*2) {
196
iccArray = (cmsHPROFILE*) malloc(
197
size*2*sizeof(cmsHPROFILE));
198
if (iccArray == NULL) {
199
(*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
200
201
J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL");
202
return 0L;
203
}
204
}
205
206
j = 0;
207
for (i = 0; i < size; i++) {
208
cmsColorSpaceSignature cs;
209
lcmsProfile_p profilePtr = (lcmsProfile_p)jlong_to_ptr(ids[i]);
210
cmsHPROFILE icc = profilePtr->pf;
211
212
iccArray[j++] = icc;
213
214
/* Middle non-abstract profiles should be doubled before passing to
215
* the cmsCreateMultiprofileTransform function
216
*/
217
218
cs = cmsGetColorSpace(icc);
219
if (size > 2 && i != 0 && i != size - 1 &&
220
cs != cmsSigXYZData && cs != cmsSigLabData)
221
{
222
iccArray[j++] = icc;
223
}
224
}
225
226
sTrans = cmsCreateMultiprofileTransform(iccArray, j,
227
inFormatter, outFormatter, renderType, 0);
228
229
(*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
230
231
if (sTrans == NULL) {
232
J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: "
233
"sTrans == NULL");
234
if ((*env)->ExceptionOccurred(env) == NULL) {
235
JNU_ThrowByName(env, "java/awt/color/CMMException",
236
"Cannot get color transform");
237
}
238
} else {
239
Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, ptr_to_jlong(sTrans));
240
}
241
242
if (iccArray != &_iccArray[0]) {
243
free(iccArray);
244
}
245
return ptr_to_jlong(sTrans);
246
}
247
248
249
/*
250
* Class: sun_java2d_cmm_lcms_LCMS
251
* Method: loadProfile
252
* Signature: ([B,Lsun/java2d/cmm/lcms/LCMSProfile;)V
253
*/
254
JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
255
(JNIEnv *env, jobject obj, jbyteArray data, jobject disposerRef)
256
{
257
jbyte* dataArray;
258
jint dataSize;
259
lcmsProfile_p sProf = NULL;
260
cmsHPROFILE pf;
261
262
if (JNU_IsNull(env, data)) {
263
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
264
return 0L;
265
}
266
267
dataArray = (*env)->GetByteArrayElements (env, data, 0);
268
if (dataArray == NULL) {
269
// An exception should have already been thrown.
270
return 0L;
271
}
272
273
dataSize = (*env)->GetArrayLength (env, data);
274
275
pf = cmsOpenProfileFromMem((const void *)dataArray,
276
(cmsUInt32Number) dataSize);
277
278
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
279
280
if (pf == NULL) {
281
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
282
} else {
283
/* Sanity check: try to save the profile in order
284
* to force basic validation.
285
*/
286
cmsUInt32Number pfSize = 0;
287
if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
288
pfSize < sizeof(cmsICCHeader))
289
{
290
JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
291
292
cmsCloseProfile(pf);
293
pf = NULL;
294
}
295
}
296
297
if (pf != NULL) {
298
// create profile holder
299
sProf = (lcmsProfile_p)malloc(sizeof(lcmsProfile_t));
300
if (sProf != NULL) {
301
// register the disposer record
302
sProf->pf = pf;
303
Disposer_AddRecord(env, disposerRef, LCMS_freeProfile, ptr_to_jlong(sProf));
304
} else {
305
cmsCloseProfile(pf);
306
}
307
}
308
309
return ptr_to_jlong(sProf);
310
}
311
312
/*
313
* Class: sun_java2d_cmm_lcms_LCMS
314
* Method: getProfileSizeNative
315
* Signature: (J)I
316
*/
317
JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative
318
(JNIEnv *env, jobject obj, jlong id)
319
{
320
lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
321
cmsUInt32Number pfSize = 0;
322
323
if (cmsSaveProfileToMem(sProf->pf, NULL, &pfSize) && ((jint)pfSize > 0)) {
324
return (jint)pfSize;
325
} else {
326
JNU_ThrowByName(env, "java/awt/color/CMMException",
327
"Can not access specified profile.");
328
return -1;
329
}
330
}
331
332
/*
333
* Class: sun_java2d_cmm_lcms_LCMS
334
* Method: getProfileDataNative
335
* Signature: (J[B)V
336
*/
337
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative
338
(JNIEnv *env, jobject obj, jlong id, jbyteArray data)
339
{
340
lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
341
jint size;
342
jbyte* dataArray;
343
cmsUInt32Number pfSize = 0;
344
cmsBool status;
345
346
// determine actual profile size
347
if (!cmsSaveProfileToMem(sProf->pf, NULL, &pfSize)) {
348
JNU_ThrowByName(env, "java/awt/color/CMMException",
349
"Can not access specified profile.");
350
return;
351
}
352
353
// verify java buffer capacity
354
size = (*env)->GetArrayLength(env, data);
355
if (0 >= size || pfSize > (cmsUInt32Number)size) {
356
JNU_ThrowByName(env, "java/awt/color/CMMException",
357
"Insufficient buffer capacity.");
358
return;
359
}
360
361
dataArray = (*env)->GetByteArrayElements (env, data, 0);
362
if (dataArray == NULL) {
363
// An exception should have already been thrown.
364
return;
365
}
366
367
status = cmsSaveProfileToMem(sProf->pf, dataArray, &pfSize);
368
369
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
370
371
if (!status) {
372
JNU_ThrowByName(env, "java/awt/color/CMMException",
373
"Can not access specified profile.");
374
return;
375
}
376
}
377
378
/* Get profile header info */
379
static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
380
static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
381
static cmsHPROFILE _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
382
383
384
/*
385
* Class: sun_java2d_cmm_lcms_LCMS
386
* Method: getTagData
387
* Signature: (JI[B)V
388
*/
389
JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative
390
(JNIEnv *env, jobject obj, jlong id, jint tagSig)
391
{
392
lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
393
TagSignature_t sig;
394
cmsUInt32Number tagSize;
395
396
jbyte* dataArray = NULL;
397
jbyteArray data = NULL;
398
399
cmsUInt32Number bufSize;
400
401
sig.j = tagSig;
402
403
if (tagSig == SigHead) {
404
cmsBool status;
405
406
// allocate java array
407
bufSize = sizeof(cmsICCHeader);
408
data = (*env)->NewByteArray(env, bufSize);
409
410
if (data == NULL) {
411
// An exception should have already been thrown.
412
return NULL;
413
}
414
415
dataArray = (*env)->GetByteArrayElements (env, data, 0);
416
417
if (dataArray == NULL) {
418
// An exception should have already been thrown.
419
return NULL;
420
}
421
422
status = _getHeaderInfo(sProf->pf, dataArray, bufSize);
423
424
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
425
426
if (!status) {
427
JNU_ThrowByName(env, "java/awt/color/CMMException",
428
"ICC Profile header not found");
429
return NULL;
430
}
431
432
return data;
433
}
434
435
if (cmsIsTag(sProf->pf, sig.cms)) {
436
tagSize = cmsReadRawTag(sProf->pf, sig.cms, NULL, 0);
437
} else {
438
JNU_ThrowByName(env, "java/awt/color/CMMException",
439
"ICC profile tag not found");
440
return NULL;
441
}
442
443
// allocate java array
444
data = (*env)->NewByteArray(env, tagSize);
445
if (data == NULL) {
446
// An exception should have already been thrown.
447
return NULL;
448
}
449
450
dataArray = (*env)->GetByteArrayElements (env, data, 0);
451
452
if (dataArray == NULL) {
453
// An exception should have already been thrown.
454
return NULL;
455
}
456
457
bufSize = cmsReadRawTag(sProf->pf, sig.cms, dataArray, tagSize);
458
459
(*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
460
461
if (bufSize != tagSize) {
462
JNU_ThrowByName(env, "java/awt/color/CMMException",
463
"Can not get tag data.");
464
return NULL;
465
}
466
return data;
467
}
468
469
/*
470
* Class: sun_java2d_cmm_lcms_LCMS
471
* Method: setTagData
472
* Signature: (JI[B)V
473
*/
474
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative
475
(JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
476
{
477
lcmsProfile_p sProf = (lcmsProfile_p)jlong_to_ptr(id);
478
cmsHPROFILE pfReplace = NULL;
479
480
TagSignature_t sig;
481
cmsBool status = FALSE;
482
jbyte* dataArray;
483
int tagSize;
484
485
sig.j = tagSig;
486
487
if (JNU_IsNull(env, data)) {
488
JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
489
return;
490
}
491
492
tagSize =(*env)->GetArrayLength(env, data);
493
494
dataArray = (*env)->GetByteArrayElements(env, data, 0);
495
496
if (dataArray == NULL) {
497
// An exception should have already been thrown.
498
return;
499
}
500
501
if (tagSig == SigHead) {
502
status = _setHeaderInfo(sProf->pf, dataArray, tagSize);
503
} else {
504
/*
505
* New strategy for generic tags: create a place holder,
506
* dump all existing tags there, dump externally supplied
507
* tag, and return the new profile to the java.
508
*/
509
pfReplace = _writeCookedTag(sProf->pf, sig.cms, dataArray, tagSize);
510
status = (pfReplace != NULL);
511
}
512
513
(*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
514
515
if (!status) {
516
JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
517
} else if (pfReplace != NULL) {
518
cmsCloseProfile(sProf->pf);
519
sProf->pf = pfReplace;
520
}
521
}
522
523
void* getILData (JNIEnv *env, jobject img, jint* pDataType,
524
jobject* pDataObject) {
525
void* result = NULL;
526
*pDataType = (*env)->GetIntField (env, img, IL_dataType_fID);
527
*pDataObject = (*env)->GetObjectField(env, img, IL_dataArray_fID);
528
switch (*pDataType) {
529
case DT_BYTE:
530
result = (*env)->GetByteArrayElements (env, *pDataObject, 0);
531
break;
532
case DT_SHORT:
533
result = (*env)->GetShortArrayElements (env, *pDataObject, 0);
534
break;
535
case DT_INT:
536
result = (*env)->GetIntArrayElements (env, *pDataObject, 0);
537
break;
538
case DT_DOUBLE:
539
result = (*env)->GetDoubleArrayElements (env, *pDataObject, 0);
540
break;
541
}
542
543
return result;
544
}
545
546
void releaseILData (JNIEnv *env, void* pData, jint dataType,
547
jobject dataObject) {
548
switch (dataType) {
549
case DT_BYTE:
550
(*env)->ReleaseByteArrayElements(env,dataObject,(jbyte*)pData,0);
551
break;
552
case DT_SHORT:
553
(*env)->ReleaseShortArrayElements(env,dataObject,(jshort*)pData, 0);
554
break;
555
case DT_INT:
556
(*env)->ReleaseIntArrayElements(env,dataObject,(jint*)pData,0);
557
break;
558
case DT_DOUBLE:
559
(*env)->ReleaseDoubleArrayElements(env,dataObject,(jdouble*)pData,
560
0);
561
break;
562
}
563
}
564
565
/*
566
* Class: sun_java2d_cmm_lcms_LCMS
567
* Method: colorConvert
568
* Signature: (Lsun/java2d/cmm/lcms/LCMSTransform;Lsun/java2d/cmm/lcms/LCMSImageLayout;Lsun/java2d/cmm/lcms/LCMSImageLayout;)V
569
*/
570
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert
571
(JNIEnv *env, jclass obj, jobject trans, jobject src, jobject dst)
572
{
573
cmsHTRANSFORM sTrans = NULL;
574
int srcDType, dstDType;
575
int srcOffset, srcNextRowOffset, dstOffset, dstNextRowOffset;
576
int width, height, i;
577
void* inputBuffer;
578
void* outputBuffer;
579
char* inputRow;
580
char* outputRow;
581
jobject srcData, dstData;
582
jboolean srcAtOnce = JNI_FALSE, dstAtOnce = JNI_FALSE;
583
584
srcOffset = (*env)->GetIntField (env, src, IL_offset_fID);
585
srcNextRowOffset = (*env)->GetIntField (env, src, IL_nextRowOffset_fID);
586
dstOffset = (*env)->GetIntField (env, dst, IL_offset_fID);
587
dstNextRowOffset = (*env)->GetIntField (env, dst, IL_nextRowOffset_fID);
588
width = (*env)->GetIntField (env, src, IL_width_fID);
589
height = (*env)->GetIntField (env, src, IL_height_fID);
590
591
srcAtOnce = (*env)->GetBooleanField(env, src, IL_imageAtOnce_fID);
592
dstAtOnce = (*env)->GetBooleanField(env, dst, IL_imageAtOnce_fID);
593
594
sTrans = jlong_to_ptr((*env)->GetLongField (env, trans, Trans_ID_fID));
595
596
if (sTrans == NULL) {
597
J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_colorConvert: transform == NULL");
598
JNU_ThrowByName(env, "java/awt/color/CMMException",
599
"Cannot get color transform");
600
return;
601
}
602
603
604
inputBuffer = getILData (env, src, &srcDType, &srcData);
605
606
if (inputBuffer == NULL) {
607
J2dRlsTraceLn(J2D_TRACE_ERROR, "");
608
// An exception should have already been thrown.
609
return;
610
}
611
612
outputBuffer = getILData (env, dst, &dstDType, &dstData);
613
614
if (outputBuffer == NULL) {
615
releaseILData(env, inputBuffer, srcDType, srcData);
616
// An exception should have already been thrown.
617
return;
618
}
619
620
inputRow = (char*)inputBuffer + srcOffset;
621
outputRow = (char*)outputBuffer + dstOffset;
622
623
if (srcAtOnce && dstAtOnce) {
624
cmsDoTransform(sTrans, inputRow, outputRow, width * height);
625
} else {
626
for (i = 0; i < height; i++) {
627
cmsDoTransform(sTrans, inputRow, outputRow, width);
628
inputRow += srcNextRowOffset;
629
outputRow += dstNextRowOffset;
630
}
631
}
632
633
releaseILData(env, inputBuffer, srcDType, srcData);
634
releaseILData(env, outputBuffer, dstDType, dstData);
635
}
636
637
/*
638
* Class: sun_java2d_cmm_lcms_LCMS
639
* Method: getProfileID
640
* Signature: (Ljava/awt/color/ICC_Profile;)Lsun/java2d/cmm/lcms/LCMSProfile
641
*/
642
JNIEXPORT jobject JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID
643
(JNIEnv *env, jclass cls, jobject pf)
644
{
645
jclass clsLcmsProfile;
646
jobject cmmProfile;
647
jfieldID fid;
648
649
if (pf == NULL) {
650
return NULL;
651
}
652
fid = (*env)->GetFieldID (env,
653
(*env)->GetObjectClass(env, pf),
654
"cmmProfile", "Lsun/java2d/cmm/Profile;");
655
if (fid == NULL) {
656
return NULL;
657
}
658
659
clsLcmsProfile = (*env)->FindClass(env,
660
"sun/java2d/cmm/lcms/LCMSProfile");
661
if (clsLcmsProfile == NULL) {
662
return NULL;
663
}
664
665
cmmProfile = (*env)->GetObjectField (env, pf, fid);
666
667
if (JNU_IsNull(env, cmmProfile)) {
668
return NULL;
669
}
670
if ((*env)->IsInstanceOf(env, cmmProfile, clsLcmsProfile)) {
671
return cmmProfile;
672
}
673
return NULL;
674
}
675
676
/*
677
* Class: sun_java2d_cmm_lcms_LCMS
678
* Method: initLCMS
679
* Signature: (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;)V
680
*/
681
JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS
682
(JNIEnv *env, jclass cls, jclass Trans, jclass IL, jclass Pf)
683
{
684
/* TODO: move initialization of the IDs to the static blocks of
685
* corresponding classes to avoid problems with invalidating ids by class
686
* unloading
687
*/
688
Trans_renderType_fID = (*env)->GetFieldID (env, Trans, "renderType", "I");
689
if (Trans_renderType_fID == NULL) {
690
return;
691
}
692
Trans_ID_fID = (*env)->GetFieldID (env, Trans, "ID", "J");
693
if (Trans_ID_fID == NULL) {
694
return;
695
}
696
697
IL_isIntPacked_fID = (*env)->GetFieldID (env, IL, "isIntPacked", "Z");
698
if (IL_isIntPacked_fID == NULL) {
699
return;
700
}
701
IL_dataType_fID = (*env)->GetFieldID (env, IL, "dataType", "I");
702
if (IL_dataType_fID == NULL) {
703
return;
704
}
705
IL_pixelType_fID = (*env)->GetFieldID (env, IL, "pixelType", "I");
706
if (IL_pixelType_fID == NULL) {
707
return;
708
}
709
IL_dataArray_fID = (*env)->GetFieldID(env, IL, "dataArray",
710
"Ljava/lang/Object;");
711
if (IL_dataArray_fID == NULL) {
712
return;
713
}
714
IL_width_fID = (*env)->GetFieldID (env, IL, "width", "I");
715
if (IL_width_fID == NULL) {
716
return;
717
}
718
IL_height_fID = (*env)->GetFieldID (env, IL, "height", "I");
719
if (IL_height_fID == NULL) {
720
return;
721
}
722
IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I");
723
if (IL_offset_fID == NULL) {
724
return;
725
}
726
IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z");
727
if (IL_imageAtOnce_fID == NULL) {
728
return;
729
}
730
IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I");
731
if (IL_nextRowOffset_fID == NULL) {
732
return;
733
}
734
}
735
736
static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
737
{
738
cmsUInt32Number pfSize = 0;
739
cmsUInt8Number* pfBuffer = NULL;
740
cmsBool status = FALSE;
741
742
if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
743
pfSize < sizeof(cmsICCHeader) ||
744
bufferSize < (jint)sizeof(cmsICCHeader))
745
{
746
return FALSE;
747
}
748
749
pfBuffer = malloc(pfSize);
750
if (pfBuffer == NULL) {
751
return FALSE;
752
}
753
754
// load raw profile data into the buffer
755
if (cmsSaveProfileToMem(pf, pfBuffer, &pfSize)) {
756
memcpy(pBuffer, pfBuffer, sizeof(cmsICCHeader));
757
status = TRUE;
758
}
759
free(pfBuffer);
760
return status;
761
}
762
763
static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
764
{
765
cmsICCHeader pfHeader;
766
767
if (pBuffer == NULL || bufferSize < (jint)sizeof(cmsICCHeader)) {
768
return FALSE;
769
}
770
771
memcpy(&pfHeader, pBuffer, sizeof(cmsICCHeader));
772
773
// now set header fields, which we can access using the lcms2 public API
774
cmsSetHeaderFlags(pf, pfHeader.flags);
775
cmsSetHeaderManufacturer(pf, pfHeader.manufacturer);
776
cmsSetHeaderModel(pf, pfHeader.model);
777
cmsSetHeaderAttributes(pf, pfHeader.attributes);
778
cmsSetHeaderProfileID(pf, (cmsUInt8Number*)&(pfHeader.profileID));
779
cmsSetHeaderRenderingIntent(pf, pfHeader.renderingIntent);
780
cmsSetPCS(pf, pfHeader.pcs);
781
cmsSetColorSpace(pf, pfHeader.colorSpace);
782
cmsSetDeviceClass(pf, pfHeader.deviceClass);
783
cmsSetEncodedICCversion(pf, pfHeader.version);
784
785
return TRUE;
786
}
787
788
/* Returns new profile handler, if it was created successfully,
789
NULL otherwise.
790
*/
791
static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget,
792
const cmsTagSignature sig,
793
jbyte *pData, jint size)
794
{
795
cmsUInt32Number pfSize = 0;
796
const cmsInt32Number tagCount = cmsGetTagCount(pfTarget);
797
cmsInt32Number i;
798
cmsHPROFILE pfSanity = NULL;
799
800
cmsICCHeader hdr;
801
802
cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);
803
804
if (NULL == p) {
805
return NULL;
806
}
807
memset(&hdr, 0, sizeof(cmsICCHeader));
808
809
// Populate the placeholder's header according to target profile
810
hdr.flags = cmsGetHeaderFlags(pfTarget);
811
hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
812
hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
813
hdr.model = cmsGetHeaderModel(pfTarget);
814
hdr.pcs = cmsGetPCS(pfTarget);
815
hdr.colorSpace = cmsGetColorSpace(pfTarget);
816
hdr.deviceClass = cmsGetDeviceClass(pfTarget);
817
hdr.version = cmsGetEncodedICCversion(pfTarget);
818
cmsGetHeaderAttributes(pfTarget, &hdr.attributes);
819
cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID);
820
821
cmsSetHeaderFlags(p, hdr.flags);
822
cmsSetHeaderManufacturer(p, hdr.manufacturer);
823
cmsSetHeaderModel(p, hdr.model);
824
cmsSetHeaderAttributes(p, hdr.attributes);
825
cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID));
826
cmsSetHeaderRenderingIntent(p, hdr.renderingIntent);
827
cmsSetPCS(p, hdr.pcs);
828
cmsSetColorSpace(p, hdr.colorSpace);
829
cmsSetDeviceClass(p, hdr.deviceClass);
830
cmsSetEncodedICCversion(p, hdr.version);
831
832
// now write the user supplied tag
833
if (size <= 0 || !cmsWriteRawTag(p, sig, pData, size)) {
834
cmsCloseProfile(p);
835
return NULL;
836
}
837
838
// copy tags from the original profile
839
for (i = 0; i < tagCount; i++) {
840
cmsBool isTagReady = FALSE;
841
const cmsTagSignature s = cmsGetTagSignature(pfTarget, i);
842
const cmsUInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0);
843
844
if (s == sig) {
845
// skip the user supplied tag
846
continue;
847
}
848
849
// read raw tag from the original profile
850
if (tagSize > 0) {
851
cmsUInt8Number* buf = (cmsUInt8Number*)malloc(tagSize);
852
if (buf != NULL) {
853
if (tagSize == cmsReadRawTag(pfTarget, s, buf, tagSize)) {
854
// now we are ready to write the tag
855
isTagReady = cmsWriteRawTag(p, s, buf, tagSize);
856
}
857
free(buf);
858
}
859
}
860
861
if (!isTagReady) {
862
cmsCloseProfile(p);
863
return NULL;
864
}
865
}
866
867
// now we have all tags moved to the new profile.
868
// do some sanity checks: write it to a memory buffer and read again.
869
if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
870
void* buf = malloc(pfSize);
871
if (buf != NULL) {
872
// load raw profile data into the buffer
873
if (cmsSaveProfileToMem(p, buf, &pfSize)) {
874
pfSanity = cmsOpenProfileFromMem(buf, pfSize);
875
}
876
free(buf);
877
}
878
}
879
880
if (pfSanity == NULL) {
881
// for some reason, we failed to save and read the updated profile
882
// It likely indicates that the profile is not correct, so we report
883
// a failure here.
884
cmsCloseProfile(p);
885
p = NULL;
886
} else {
887
// do final check whether we can read and handle the the target tag.
888
const void* pTag = cmsReadTag(pfSanity, sig);
889
if (pTag == NULL) {
890
// the tag can not be cooked
891
cmsCloseProfile(p);
892
p = NULL;
893
}
894
cmsCloseProfile(pfSanity);
895
pfSanity = NULL;
896
}
897
898
return p;
899
}
900
901