History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/java2d/cmm/lcms/LCMSTransform.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/java2d/cmm/lcms/LCMSTransform.java+609−0
@@ -0,0 +1,609 @@
1/*
2 * Copyright (c) 2007, 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/**********************************************************************
27 **********************************************************************
28 **********************************************************************
29 *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
30 *** As an unpublished work pursuant to Title 17 of the United ***
31 *** States Code. All rights reserved. ***
32 **********************************************************************
33 **********************************************************************
34 **********************************************************************/
35
36package sun.java2d.cmm.lcms;
37
38import java.awt.color.ICC_Profile;
39import java.awt.color.ProfileDataException;
40import java.awt.color.CMMException;
41import java.awt.color.ColorSpace;
42import java.awt.image.BufferedImage;
43import java.awt.image.Raster;
44import java.awt.image.WritableRaster;
45import java.awt.image.ColorModel;
46import java.awt.image.DirectColorModel;
47import java.awt.image.ComponentColorModel;
48import java.awt.image.SampleModel;
49import java.awt.image.DataBuffer;
50import java.awt.image.SinglePixelPackedSampleModel;
51import java.awt.image.ComponentSampleModel;
52import sun.java2d.cmm.*;
53import sun.java2d.cmm.lcms.*;
54
55
56public class LCMSTransform implements ColorTransform {
57 long ID;
58 private int inFormatter;
59 private int outFormatter;
60
61 ICC_Profile[] profiles;
62 long [] profileIDs;
63 int renderType;
64 int transformType;
65
66 private int numInComponents = -1;
67 private int numOutComponents = -1;
68
69 private Object disposerReferent = new Object();
70
71 /* the class initializer */
72 static {
73 if (ProfileDeferralMgr.deferring) {
74 ProfileDeferralMgr.activateProfiles();
75 }
76 }
77
78 public LCMSTransform(ICC_Profile profile, int renderType,
79 int transformType)
80 {
81 /* Actually, it is not a complete transform but just part of it */
82 profiles = new ICC_Profile[1];
83 profiles[0] = profile;
84 profileIDs = new long[1];
85 profileIDs[0] = LCMS.getProfileID(profile);
86 this.renderType = (renderType == ColorTransform.Any)?
87 ICC_Profile.icPerceptual : renderType;
88 this.transformType = transformType;
89
90 /* Note that ICC_Profile.getNumComponents() is quite expensive
91 * (it may results in a reading of the profile header).
92 * So, here we cache the number of components of input and
93 * output profiles for further usage.
94 */
95 numInComponents = profiles[0].getNumComponents();
96 numOutComponents = profiles[profiles.length - 1].getNumComponents();
97 }
98
99 public LCMSTransform (ColorTransform[] transforms) {
100 int size = 0;
101 for (int i=0; i < transforms.length; i++) {
102 size+=((LCMSTransform)transforms[i]).profiles.length;
103 }
104 profiles = new ICC_Profile[size];
105 profileIDs = new long[size];
106 int j = 0;
107 for (int i=0; i < transforms.length; i++) {
108 LCMSTransform curTrans = (LCMSTransform)transforms[i];
109 System.arraycopy(curTrans.profiles, 0, profiles, j,
110 curTrans.profiles.length);
111 System.arraycopy(curTrans.profileIDs, 0, profileIDs, j,
112 curTrans.profileIDs.length);
113 j += curTrans.profiles.length;
114 }
115 renderType = ((LCMSTransform)transforms[0]).renderType;
116
117 /* Note that ICC_Profile.getNumComponents() is quite expensive
118 * (it may results in a reading of the profile header).
119 * So, here we cache the number of components of input and
120 * output profiles for further usage.
121 */
122 numInComponents = profiles[0].getNumComponents();
123 numOutComponents = profiles[profiles.length - 1].getNumComponents();
124 }
125
126 public int getNumInComponents() {
127 return numInComponents;
128 }
129
130 public int getNumOutComponents() {
131 return numOutComponents;
132 }
133
134 private synchronized void doTransform(LCMSImageLayout in,
135 LCMSImageLayout out) {
136 // update native transfrom if needed
137 if (ID == 0L ||
138 inFormatter != in.pixelType ||
139 outFormatter != out.pixelType) {
140
141 if (ID != 0L) {
142 // Disposer will destroy forgotten transform
143 disposerReferent = new Object();
144 }
145 inFormatter = in.pixelType;
146 outFormatter = out.pixelType;
147
148 ID = LCMS.createNativeTransform(profileIDs, renderType,
149 inFormatter, outFormatter,
150 disposerReferent);
151 }
152
153 LCMS.colorConvert(this, in, out);
154 }
155
156 public void colorConvert(BufferedImage src, BufferedImage dst) {
157 if (LCMSImageLayout.isSupported(src) &&
158 LCMSImageLayout.isSupported(dst))
159 {
160 doTransform(new LCMSImageLayout(src), new LCMSImageLayout(dst));
161 return;
162 }
163 LCMSImageLayout srcIL, dstIL;
164 Raster srcRas = src.getRaster();
165 WritableRaster dstRas = dst.getRaster();
166 ColorModel srcCM = src.getColorModel();
167 ColorModel dstCM = dst.getColorModel();
168 int w = src.getWidth();
169 int h = src.getHeight();
170 int srcNumComp = srcCM.getNumColorComponents();
171 int dstNumComp = dstCM.getNumColorComponents();
172 int precision = 8;
173 float maxNum = 255.0f;
174 for (int i = 0; i < srcNumComp; i++) {
175 if (srcCM.getComponentSize(i) > 8) {
176 precision = 16;
177 maxNum = 65535.0f;
178 }
179 }
180 for (int i = 0; i < dstNumComp; i++) {
181 if (dstCM.getComponentSize(i) > 8) {
182 precision = 16;
183 maxNum = 65535.0f;
184 }
185 }
186 float[] srcMinVal = new float[srcNumComp];
187 float[] srcInvDiffMinMax = new float[srcNumComp];
188 ColorSpace cs = srcCM.getColorSpace();
189 for (int i = 0; i < srcNumComp; i++) {
190 srcMinVal[i] = cs.getMinValue(i);
191 srcInvDiffMinMax[i] = maxNum / (cs.getMaxValue(i) - srcMinVal[i]);
192 }
193 cs = dstCM.getColorSpace();
194 float[] dstMinVal = new float[dstNumComp];
195 float[] dstDiffMinMax = new float[dstNumComp];
196 for (int i = 0; i < dstNumComp; i++) {
197 dstMinVal[i] = cs.getMinValue(i);
198 dstDiffMinMax[i] = (cs.getMaxValue(i) - dstMinVal[i]) / maxNum;
199 }
200 boolean dstHasAlpha = dstCM.hasAlpha();
201 boolean needSrcAlpha = srcCM.hasAlpha() && dstHasAlpha;
202 float[] dstColor;
203 if (dstHasAlpha) {
204 dstColor = new float[dstNumComp + 1];
205 } else {
206 dstColor = new float[dstNumComp];
207 }
208 if (precision == 8) {
209 byte[] srcLine = new byte[w * srcNumComp];
210 byte[] dstLine = new byte[w * dstNumComp];
211 Object pixel;
212 float[] color;
213 float[] alpha = null;
214 if (needSrcAlpha) {
215 alpha = new float[w];
216 }
217 int idx;
218 // TODO check for src npixels = dst npixels
219 srcIL = new LCMSImageLayout(
220 srcLine, srcLine.length/getNumInComponents(),
221 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
222 LCMSImageLayout.BYTES_SH(1), getNumInComponents());
223 dstIL = new LCMSImageLayout(
224 dstLine, dstLine.length/getNumOutComponents(),
225 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
226 LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
227 // process each scanline
228 for (int y = 0; y < h; y++) {
229 // convert src scanline
230 pixel = null;
231 color = null;
232 idx = 0;
233 for (int x = 0; x < w; x++) {
234 pixel = srcRas.getDataElements(x, y, pixel);
235 color = srcCM.getNormalizedComponents(pixel, color, 0);
236 for (int i = 0; i < srcNumComp; i++) {
237 srcLine[idx++] = (byte)
238 ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
239 0.5f);
240 }
241 if (needSrcAlpha) {
242 alpha[x] = color[srcNumComp];
243 }
244 }
245 // color convert srcLine to dstLine
246 doTransform(srcIL, dstIL);
247
248 // convert dst scanline
249 pixel = null;
250 idx = 0;
251 for (int x = 0; x < w; x++) {
252 for (int i = 0; i < dstNumComp; i++) {
253 dstColor[i] = ((float) (dstLine[idx++] & 0xff)) *
254 dstDiffMinMax[i] + dstMinVal[i];
255 }
256 if (needSrcAlpha) {
257 dstColor[dstNumComp] = alpha[x];
258 } else if (dstHasAlpha) {
259 dstColor[dstNumComp] = 1.0f;
260 }
261 pixel = dstCM.getDataElements(dstColor, 0, pixel);
262 dstRas.setDataElements(x, y, pixel);
263 }
264 }
265 } else {
266 short[] srcLine = new short[w * srcNumComp];
267 short[] dstLine = new short[w * dstNumComp];
268 Object pixel;
269 float[] color;
270 float[] alpha = null;
271 if (needSrcAlpha) {
272 alpha = new float[w];
273 }
274 int idx;
275 srcIL = new LCMSImageLayout(
276 srcLine, srcLine.length/getNumInComponents(),
277 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
278 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
279
280 dstIL = new LCMSImageLayout(
281 dstLine, dstLine.length/getNumOutComponents(),
282 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
283 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
284
285 // process each scanline
286 for (int y = 0; y < h; y++) {
287 // convert src scanline
288 pixel = null;
289 color = null;
290 idx = 0;
291 for (int x = 0; x < w; x++) {
292 pixel = srcRas.getDataElements(x, y, pixel);
293 color = srcCM.getNormalizedComponents(pixel, color, 0);
294 for (int i = 0; i < srcNumComp; i++) {
295 srcLine[idx++] = (short)
296 ((color[i] - srcMinVal[i]) * srcInvDiffMinMax[i] +
297 0.5f);
298 }
299 if (needSrcAlpha) {
300 alpha[x] = color[srcNumComp];
301 }
302 }
303 // color convert srcLine to dstLine
304 doTransform(srcIL, dstIL);
305
306 // convert dst scanline
307 pixel = null;
308 idx = 0;
309 for (int x = 0; x < w; x++) {
310 for (int i = 0; i < dstNumComp; i++) {
311 dstColor[i] = ((float) (dstLine[idx++] & 0xffff)) *
312 dstDiffMinMax[i] + dstMinVal[i];
313 }
314 if (needSrcAlpha) {
315 dstColor[dstNumComp] = alpha[x];
316 } else if (dstHasAlpha) {
317 dstColor[dstNumComp] = 1.0f;
318 }
319 pixel = dstCM.getDataElements(dstColor, 0, pixel);
320 dstRas.setDataElements(x, y, pixel);
321 }
322 }
323 }
324 }
325
326 public void colorConvert(Raster src, WritableRaster dst,
327 float[] srcMinVal, float[]srcMaxVal,
328 float[] dstMinVal, float[]dstMaxVal) {
329 LCMSImageLayout srcIL, dstIL;
330
331 // Can't pass src and dst directly to CMM, so process per scanline
332 SampleModel srcSM = src.getSampleModel();
333 SampleModel dstSM = dst.getSampleModel();
334 int srcTransferType = src.getTransferType();
335 int dstTransferType = dst.getTransferType();
336 boolean srcIsFloat, dstIsFloat;
337 if ((srcTransferType == DataBuffer.TYPE_FLOAT) ||
338 (srcTransferType == DataBuffer.TYPE_DOUBLE)) {
339 srcIsFloat = true;
340 } else {
341 srcIsFloat = false;
342 }
343 if ((dstTransferType == DataBuffer.TYPE_FLOAT) ||
344 (dstTransferType == DataBuffer.TYPE_DOUBLE)) {
345 dstIsFloat = true;
346 } else {
347 dstIsFloat = false;
348 }
349 int w = src.getWidth();
350 int h = src.getHeight();
351 int srcNumBands = src.getNumBands();
352 int dstNumBands = dst.getNumBands();
353 float[] srcScaleFactor = new float[srcNumBands];
354 float[] dstScaleFactor = new float[dstNumBands];
355 float[] srcUseMinVal = new float[srcNumBands];
356 float[] dstUseMinVal = new float[dstNumBands];
357 for (int i = 0; i < srcNumBands; i++) {
358 if (srcIsFloat) {
359 srcScaleFactor[i] = 65535.0f / (srcMaxVal[i] - srcMinVal[i]);
360 srcUseMinVal[i] = srcMinVal[i];
361 } else {
362 if (srcTransferType == DataBuffer.TYPE_SHORT) {
363 srcScaleFactor[i] = 65535.0f / 32767.0f;
364 } else {
365 srcScaleFactor[i] = 65535.0f /
366 ((float) ((1 << srcSM.getSampleSize(i)) - 1));
367 }
368 srcUseMinVal[i] = 0.0f;
369 }
370 }
371 for (int i = 0; i < dstNumBands; i++) {
372 if (dstIsFloat) {
373 dstScaleFactor[i] = (dstMaxVal[i] - dstMinVal[i]) / 65535.0f;
374 dstUseMinVal[i] = dstMinVal[i];
375 } else {
376 if (dstTransferType == DataBuffer.TYPE_SHORT) {
377 dstScaleFactor[i] = 32767.0f / 65535.0f;
378 } else {
379 dstScaleFactor[i] =
380 ((float) ((1 << dstSM.getSampleSize(i)) - 1)) /
381 65535.0f;
382 }
383 dstUseMinVal[i] = 0.0f;
384 }
385 }
386 int ys = src.getMinY();
387 int yd = dst.getMinY();
388 int xs, xd;
389 float sample;
390 short[] srcLine = new short[w * srcNumBands];
391 short[] dstLine = new short[w * dstNumBands];
392 int idx;
393 srcIL = new LCMSImageLayout(
394 srcLine, srcLine.length/getNumInComponents(),
395 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
396 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
397
398 dstIL = new LCMSImageLayout(
399 dstLine, dstLine.length/getNumOutComponents(),
400 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
401 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
402
403 // process each scanline
404 for (int y = 0; y < h; y++, ys++, yd++) {
405 // get src scanline
406 xs = src.getMinX();
407 idx = 0;
408 for (int x = 0; x < w; x++, xs++) {
409 for (int i = 0; i < srcNumBands; i++) {
410 sample = src.getSampleFloat(xs, ys, i);
411 srcLine[idx++] = (short)
412 ((sample - srcUseMinVal[i]) * srcScaleFactor[i] + 0.5f);
413 }
414 }
415
416 // color convert srcLine to dstLine
417 doTransform(srcIL, dstIL);
418
419 // store dst scanline
420 xd = dst.getMinX();
421 idx = 0;
422 for (int x = 0; x < w; x++, xd++) {
423 for (int i = 0; i < dstNumBands; i++) {
424 sample = ((dstLine[idx++] & 0xffff) * dstScaleFactor[i]) +
425 dstUseMinVal[i];
426 dst.setSample(xd, yd, i, sample);
427 }
428 }
429 }
430 }
431
432 public void colorConvert(Raster src, WritableRaster dst) {
433
434 LCMSImageLayout srcIL, dstIL;
435 // Can't pass src and dst directly to CMM, so process per scanline
436 SampleModel srcSM = src.getSampleModel();
437 SampleModel dstSM = dst.getSampleModel();
438 int srcTransferType = src.getTransferType();
439 int dstTransferType = dst.getTransferType();
440 int w = src.getWidth();
441 int h = src.getHeight();
442 int srcNumBands = src.getNumBands();
443 int dstNumBands = dst.getNumBands();
444 int precision = 8;
445 float maxNum = 255.0f;
446 for (int i = 0; i < srcNumBands; i++) {
447 if (srcSM.getSampleSize(i) > 8) {
448 precision = 16;
449 maxNum = 65535.0f;
450 }
451 }
452 for (int i = 0; i < dstNumBands; i++) {
453 if (dstSM.getSampleSize(i) > 8) {
454 precision = 16;
455 maxNum = 65535.0f;
456 }
457 }
458 float[] srcScaleFactor = new float[srcNumBands];
459 float[] dstScaleFactor = new float[dstNumBands];
460 for (int i = 0; i < srcNumBands; i++) {
461 if (srcTransferType == DataBuffer.TYPE_SHORT) {
462 srcScaleFactor[i] = maxNum / 32767.0f;
463 } else {
464 srcScaleFactor[i] = maxNum /
465 ((float) ((1 << srcSM.getSampleSize(i)) - 1));
466 }
467 }
468 for (int i = 0; i < dstNumBands; i++) {
469 if (dstTransferType == DataBuffer.TYPE_SHORT) {
470 dstScaleFactor[i] = 32767.0f / maxNum;
471 } else {
472 dstScaleFactor[i] =
473 ((float) ((1 << dstSM.getSampleSize(i)) - 1)) / maxNum;
474 }
475 }
476 int ys = src.getMinY();
477 int yd = dst.getMinY();
478 int xs, xd;
479 int sample;
480 if (precision == 8) {
481 byte[] srcLine = new byte[w * srcNumBands];
482 byte[] dstLine = new byte[w * dstNumBands];
483 int idx;
484 // TODO check for src npixels = dst npixels
485 srcIL = new LCMSImageLayout(
486 srcLine, srcLine.length/getNumInComponents(),
487 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
488 LCMSImageLayout.BYTES_SH(1), getNumInComponents());
489 dstIL = new LCMSImageLayout(
490 dstLine, dstLine.length/getNumOutComponents(),
491 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
492 LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
493
494 // process each scanline
495 for (int y = 0; y < h; y++, ys++, yd++) {
496 // get src scanline
497 xs = src.getMinX();
498 idx = 0;
499 for (int x = 0; x < w; x++, xs++) {
500 for (int i = 0; i < srcNumBands; i++) {
501 sample = src.getSample(xs, ys, i);
502 srcLine[idx++] = (byte)
503 ((sample * srcScaleFactor[i]) + 0.5f);
504 }
505 }
506
507 // color convert srcLine to dstLine
508 doTransform(srcIL, dstIL);
509
510 // store dst scanline
511 xd = dst.getMinX();
512 idx = 0;
513 for (int x = 0; x < w; x++, xd++) {
514 for (int i = 0; i < dstNumBands; i++) {
515 sample = (int) (((dstLine[idx++] & 0xff) *
516 dstScaleFactor[i]) + 0.5f);
517 dst.setSample(xd, yd, i, sample);
518 }
519 }
520 }
521 } else {
522 short[] srcLine = new short[w * srcNumBands];
523 short[] dstLine = new short[w * dstNumBands];
524 int idx;
525 srcIL = new LCMSImageLayout(
526 srcLine, srcLine.length/getNumInComponents(),
527 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
528 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
529
530 dstIL = new LCMSImageLayout(
531 dstLine, dstLine.length/getNumOutComponents(),
532 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
533 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
534
535 // process each scanline
536 for (int y = 0; y < h; y++, ys++, yd++) {
537 // get src scanline
538 xs = src.getMinX();
539 idx = 0;
540 for (int x = 0; x < w; x++, xs++) {
541 for (int i = 0; i < srcNumBands; i++) {
542 sample = src.getSample(xs, ys, i);
543 srcLine[idx++] = (short)
544 ((sample * srcScaleFactor[i]) + 0.5f);
545 }
546 }
547
548 // color convert srcLine to dstLine
549 doTransform(srcIL, dstIL);
550
551 // store dst scanline
552 xd = dst.getMinX();
553 idx = 0;
554 for (int x = 0; x < w; x++, xd++) {
555 for (int i = 0; i < dstNumBands; i++) {
556 sample = (int) (((dstLine[idx++] & 0xffff) *
557 dstScaleFactor[i]) + 0.5f);
558 dst.setSample(xd, yd, i, sample);
559 }
560 }
561 }
562 }
563 }
564
565 /* convert an array of colors in short format */
566 /* each color is a contiguous set of array elements */
567 /* the number of colors is (size of the array) / (number of input/output
568 components */
569 public short[] colorConvert(short[] src, short[] dst) {
570
571 if (dst == null) {
572 dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
573 }
574
575 LCMSImageLayout srcIL = new LCMSImageLayout(
576 src, src.length/getNumInComponents(),
577 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
578 LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
579
580 LCMSImageLayout dstIL = new LCMSImageLayout(
581 dst, dst.length/getNumOutComponents(),
582 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
583 LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
584
585 doTransform(srcIL, dstIL);
586
587 return dst;
588 }
589
590 public byte[] colorConvert(byte[] src, byte[] dst) {
591 if (dst == null) {
592 dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
593 }
594
595 LCMSImageLayout srcIL = new LCMSImageLayout(
596 src, src.length/getNumInComponents(),
597 LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
598 LCMSImageLayout.BYTES_SH(1), getNumInComponents());
599
600 LCMSImageLayout dstIL = new LCMSImageLayout(
601 dst, dst.length/getNumOutComponents(),
602 LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
603 LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
604
605 doTransform(srcIL, dstIL);
606
607 return dst;
608 }
609}