1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44: import ;
45: import ;
46: import ;
47: import ;
48: import ;
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57:
58:
85: public class ICC_Profile implements Serializable
86: {
87:
90: private static final long serialVersionUID = -3938515861990936766L;
91:
92:
95: public static final int CLASS_INPUT = 0;
96: public static final int CLASS_DISPLAY = 1;
97: public static final int CLASS_OUTPUT = 2;
98: public static final int CLASS_DEVICELINK = 3;
99: public static final int CLASS_COLORSPACECONVERSION = 4;
100: public static final int CLASS_ABSTRACT = 5;
101: public static final int CLASS_NAMEDCOLOR = 6;
102:
103:
106: public static final int icSigInputClass = 0x73636e72;
107: public static final int icSigDisplayClass = 0x6d6e7472;
108: public static final int icSigOutputClass = 0x70727472;
109: public static final int icSigLinkClass = 0x6c696e6b;
110: public static final int icSigColorSpaceClass = 0x73706163;
111: public static final int icSigAbstractClass = 0x61627374;
112: public static final int icSigNamedColorClass = 0x6e6d636c;
113:
114:
117: public static final int icSigXYZData = 0x58595A20;
118: public static final int icSigLabData = 0x4C616220;
119: public static final int icSigLuvData = 0x4C757620;
120: public static final int icSigYCbCrData = 0x59436272;
121: public static final int icSigYxyData = 0x59787920;
122: public static final int icSigRgbData = 0x52474220;
123: public static final int icSigGrayData = 0x47524159;
124: public static final int icSigHsvData = 0x48535620;
125: public static final int icSigHlsData = 0x484C5320;
126: public static final int icSigCmykData = 0x434D594B;
127: public static final int icSigCmyData = 0x434D5920;
128: public static final int icSigSpace2CLR = 0x32434C52;
129: public static final int icSigSpace3CLR = 0x33434C52;
130: public static final int icSigSpace4CLR = 0x34434C52;
131: public static final int icSigSpace5CLR = 0x35434C52;
132: public static final int icSigSpace6CLR = 0x36434C52;
133: public static final int icSigSpace7CLR = 0x37434C52;
134: public static final int icSigSpace8CLR = 0x38434C52;
135: public static final int icSigSpace9CLR = 0x39434C52;
136: public static final int icSigSpaceACLR = 0x41434C52;
137: public static final int icSigSpaceBCLR = 0x42434C52;
138: public static final int icSigSpaceCCLR = 0x43434C52;
139: public static final int icSigSpaceDCLR = 0x44434C52;
140: public static final int icSigSpaceECLR = 0x45434C52;
141: public static final int icSigSpaceFCLR = 0x46434C52;
142:
143:
146: public static final int icPerceptual = 0;
147: public static final int icRelativeColorimetric = 1;
148: public static final int icSaturation = 2;
149: public static final int icAbsoluteColorimetric = 3;
150:
151:
154: public static final int icSigAToB0Tag = 0x41324230;
155: public static final int icSigAToB1Tag = 0x41324231;
156: public static final int icSigAToB2Tag = 0x41324232;
157: public static final int icSigBlueColorantTag = 0x6258595A;
158: public static final int icSigBlueTRCTag = 0x62545243;
159: public static final int icSigBToA0Tag = 0x42324130;
160: public static final int icSigBToA1Tag = 0x42324131;
161: public static final int icSigBToA2Tag = 0x42324132;
162: public static final int icSigCalibrationDateTimeTag = 0x63616C74;
163: public static final int icSigCharTargetTag = 0x74617267;
164: public static final int icSigCopyrightTag = 0x63707274;
165: public static final int icSigCrdInfoTag = 0x63726469;
166: public static final int icSigDeviceMfgDescTag = 0x646D6E64;
167: public static final int icSigDeviceModelDescTag = 0x646D6464;
168: public static final int icSigDeviceSettingsTag = 0x64657673;
169: public static final int icSigGamutTag = 0x67616D74;
170: public static final int icSigGrayTRCTag = 0x6b545243;
171: public static final int icSigGreenColorantTag = 0x6758595A;
172: public static final int icSigGreenTRCTag = 0x67545243;
173: public static final int icSigLuminanceTag = 0x6C756d69;
174: public static final int icSigMeasurementTag = 0x6D656173;
175: public static final int icSigMediaBlackPointTag = 0x626B7074;
176: public static final int icSigMediaWhitePointTag = 0x77747074;
177: public static final int icSigNamedColor2Tag = 0x6E636C32;
178: public static final int icSigOutputResponseTag = 0x72657370;
179: public static final int icSigPreview0Tag = 0x70726530;
180: public static final int icSigPreview1Tag = 0x70726531;
181: public static final int icSigPreview2Tag = 0x70726532;
182: public static final int icSigProfileDescriptionTag = 0x64657363;
183: public static final int icSigProfileSequenceDescTag = 0x70736571;
184: public static final int icSigPs2CRD0Tag = 0x70736430;
185: public static final int icSigPs2CRD1Tag = 0x70736431;
186: public static final int icSigPs2CRD2Tag = 0x70736432;
187: public static final int icSigPs2CRD3Tag = 0x70736433;
188: public static final int icSigPs2CSATag = 0x70733273;
189: public static final int icSigPs2RenderingIntentTag = 0x70733269;
190: public static final int icSigRedColorantTag = 0x7258595A;
191: public static final int icSigRedTRCTag = 0x72545243;
192: public static final int icSigScreeningDescTag = 0x73637264;
193: public static final int icSigScreeningTag = 0x7363726E;
194: public static final int icSigTechnologyTag = 0x74656368;
195: public static final int icSigUcrBgTag = 0x62666420;
196: public static final int icSigViewingCondDescTag = 0x76756564;
197: public static final int icSigViewingConditionsTag = 0x76696577;
198: public static final int icSigChromaticityTag = 0x6368726D;
199:
200:
203: public static final int icSigHead = 0x68656164;
204:
205:
208: public static final int icHdrSize = 0;
209: public static final int icHdrCmmId = 4;
210: public static final int icHdrVersion = 8;
211: public static final int icHdrDeviceClass = 12;
212: public static final int icHdrColorSpace = 16;
213: public static final int icHdrPcs = 20;
214: public static final int icHdrDate = 24;
215: public static final int icHdrMagic = 36;
216: public static final int icHdrPlatform = 40;
217: public static final int icHdrFlags = 44;
218: public static final int icHdrManufacturer = 48;
219: public static final int icHdrModel = 52;
220: public static final int icHdrAttributes = 56;
221: public static final int icHdrRenderingIntent = 64;
222: public static final int icHdrIlluminant = 68;
223: public static final int icHdrCreator = 80;
224:
225:
228: public static final int icTagType = 0;
229: public static final int icTagReserved = 4;
230: public static final int icCurveCount = 8;
231: public static final int icCurveData = 12;
232: public static final int icXYZNumberX = 8;
233:
234:
237: private static final int tagTableOffset = 128;
238:
239:
242: private static final int iccProfileSerializedDataVersion = 1;
243:
244:
248:
251: private static final String copyrightNotice = "Generated by GNU Classpath.";
252:
253:
257: private static final int TRC_POINTS = 1024;
258:
259:
262: private static final float[] D50 = { 0.96422f, 1.00f, 0.82521f };
263:
264:
270: private transient int profileID;
271:
272:
275: private transient ProfileHeader header;
276:
277:
280: private transient Hashtable tagTable;
281:
282:
285: ICC_Profile(int profileID)
286: {
287: header = null;
288: tagTable = null;
289: createProfile(profileID);
290: }
291:
292:
295: ICC_Profile(ProfileHeader h, Hashtable tags) throws IllegalArgumentException
296: {
297: header = h;
298: tagTable = tags;
299: profileID = -1;
300: }
301:
302:
305: ICC_Profile(byte[] data) throws IllegalArgumentException
306: {
307:
308: header = new ProfileHeader(data);
309: header.verifyHeader(data.length);
310: tagTable = createTagTable(data);
311: profileID = -1;
312: }
313:
314:
317: protected void finalize()
318: {
319: }
320:
321:
333: public static ICC_Profile getInstance(byte[] data)
334: {
335: ProfileHeader header = new ProfileHeader(data);
336:
337:
338: header.verifyHeader(data.length);
339:
340: Hashtable tags = createTagTable(data);
341:
342: if (isRGBProfile(header, tags))
343: return new ICC_ProfileRGB(data);
344: if (isGrayProfile(header, tags))
345: return new ICC_ProfileGray(data);
346:
347: return new ICC_Profile(header, tags);
348: }
349:
350:
361: public static ICC_Profile getInstance(int cspace)
362: {
363: if (cspace == ColorSpace.CS_sRGB || cspace == ColorSpace.CS_LINEAR_RGB)
364: return new ICC_ProfileRGB(cspace);
365: if (cspace == ColorSpace.CS_GRAY)
366: return new ICC_ProfileGray(cspace);
367: return new ICC_Profile(cspace);
368: }
369:
370:
383: public static ICC_Profile getInstance(String filename)
384: throws IOException
385: {
386: return getInstance(new FileInputStream(filename));
387: }
388:
389:
410: public static ICC_Profile getInstance(InputStream in)
411: throws IOException
412: {
413:
414: byte[] headerData = new byte[ProfileHeader.HEADERSIZE];
415: if (in.read(headerData) != ProfileHeader.HEADERSIZE)
416: throw new IllegalArgumentException("Invalid profile header");
417:
418: ProfileHeader header = new ProfileHeader(headerData);
419:
420:
421:
422: header.verifyHeader(-1);
423:
424:
425: byte[] data = new byte[header.getSize()];
426: System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE);
427:
428:
429: int totalBytes = header.getSize() - ProfileHeader.HEADERSIZE;
430: int bytesLeft = totalBytes;
431: while (bytesLeft > 0)
432: {
433: int read = in.read(data,
434: ProfileHeader.HEADERSIZE + (totalBytes - bytesLeft),
435: bytesLeft);
436: bytesLeft -= read;
437: }
438:
439: return getInstance(data);
440: }
441:
442:
445: public int getMajorVersion()
446: {
447: return header.getMajorVersion();
448: }
449:
450:
459: public int getMinorVersion()
460: {
461: return header.getMinorVersion();
462: }
463:
464:
470: public int getProfileClass()
471: {
472: return header.getProfileClass();
473: }
474:
475:
480: public int getColorSpaceType()
481: {
482: return header.getColorSpace();
483: }
484:
485:
491: public int getPCSType()
492: {
493: return header.getProfileColorSpace();
494: }
495:
496:
501: public void write(String filename) throws IOException
502: {
503: FileOutputStream out = new FileOutputStream(filename);
504: write(out);
505: out.flush();
506: out.close();
507: }
508:
509:
518: public void write(OutputStream out) throws IOException
519: {
520: out.write(getData());
521: }
522:
523:
529: public byte[] getData()
530: {
531: int size = getSize();
532: byte[] data = new byte[size];
533:
534:
535: System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
536:
537: byte[] tt = getTagTable();
538: System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
539:
540: Enumeration e = tagTable.elements();
541: while (e.hasMoreElements())
542: {
543: TagEntry tag = (TagEntry) e.nextElement();
544: System.arraycopy(tag.getData(), 0,
545: data, tag.getOffset(), tag.getSize());
546: }
547: return data;
548: }
549:
550:
557: public byte[] getData(int tagSignature)
558: {
559: if (tagSignature == icSigHead)
560: return header.getData(getSize());
561:
562: TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
563: if (t == null)
564: return null;
565: return t.getData();
566: }
567:
568:
577: public void setData(int tagSignature, byte[] data)
578: {
579: profileID = -1;
580:
581: if (tagSignature == icSigHead)
582: header = new ProfileHeader(data);
583: else
584: {
585: TagEntry t = new TagEntry(tagSignature, data);
586: tagTable.put(t.hashKey(), t);
587: }
588: }
589:
590:
593: public int getNumComponents()
594: {
595: int[] lookup =
596: {
597: ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
598: ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
599: ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
600: ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
601: ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
602: ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
603: ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
604: ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
605: ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
606: ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
607: ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
608: ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
609: ColorSpace.TYPE_FCLR, 15
610: };
611: for (int i = 0; i < lookup.length; i += 2)
612: if (header.getColorSpace() == lookup[i])
613: return lookup[i + 1];
614: return 3;
615: }
616:
617:
622: protected Object readResolve() throws ObjectStreamException
623: {
624: if (isRGBProfile(header, tagTable))
625: return new ICC_ProfileRGB(getData());
626: if (isGrayProfile(header, tagTable))
627: return new ICC_ProfileGray(getData());
628: return this;
629: }
630:
631:
634: private void readObject(ObjectInputStream s)
635: throws IOException, ClassNotFoundException
636: {
637: s.defaultReadObject();
638: String predef = (String) s.readObject();
639: byte[] data = (byte[]) s.readObject();
640:
641: if (data != null)
642: {
643: header = new ProfileHeader(data);
644: tagTable = createTagTable(data);
645: profileID = -1;
646: }
647:
648: if (predef != null)
649: {
650: predef = predef.intern();
651: if (predef.equals("CS_sRGB"))
652: createProfile(ColorSpace.CS_sRGB);
653: if (predef.equals("CS_LINEAR_RGB"))
654: createProfile(ColorSpace.CS_LINEAR_RGB);
655: if (predef.equals("CS_CIEXYZ"))
656: createProfile(ColorSpace.CS_CIEXYZ);
657: if (predef.equals("CS_GRAY"))
658: createProfile(ColorSpace.CS_GRAY);
659: if (predef.equals("CS_PYCC"))
660: createProfile(ColorSpace.CS_PYCC);
661: }
662: }
663:
664:
670: private void writeObject(ObjectOutputStream s) throws IOException
671: {
672: s.defaultWriteObject();
673: if (profileID == ColorSpace.CS_sRGB)
674: s.writeObject("CS_sRGB");
675: else if (profileID == ColorSpace.CS_LINEAR_RGB)
676: s.writeObject("CS_LINEAR_RGB");
677: else if (profileID == ColorSpace.CS_CIEXYZ)
678: s.writeObject("CS_CIEXYZ");
679: else if (profileID == ColorSpace.CS_GRAY)
680: s.writeObject("CS_GRAY");
681: else if (profileID == ColorSpace.CS_PYCC)
682: s.writeObject("CS_PYCC");
683: else
684: {
685: s.writeObject(null);
686: s.writeObject(getData());
687: return;
688: }
689: s.writeObject(null);
690: }
691:
692:
696: private static Hashtable createTagTable(byte[] data)
697: throws IllegalArgumentException
698: {
699: ByteBuffer buf = ByteBuffer.wrap(data);
700: int nTags = buf.getInt(tagTableOffset);
701:
702: Hashtable tagTable = new Hashtable();
703: for (int i = 0; i < nTags; i++)
704: {
705: TagEntry te = new TagEntry(buf.getInt(tagTableOffset
706: + i * TagEntry.entrySize + 4),
707: buf.getInt(tagTableOffset
708: + i * TagEntry.entrySize + 8),
709: buf.getInt(tagTableOffset
710: + i * TagEntry.entrySize + 12),
711: data);
712:
713: if (tagTable.put(te.hashKey(), te) != null)
714: throw new IllegalArgumentException("Duplicate tag in profile:" + te);
715: }
716: return tagTable;
717: }
718:
719:
723: private int getSize()
724: {
725: int totalSize = ProfileHeader.HEADERSIZE;
726:
727: int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
728: if ((tagTableSize & 0x0003) != 0)
729: tagTableSize += 4 - (tagTableSize & 0x0003);
730: totalSize += tagTableSize;
731:
732: Enumeration e = tagTable.elements();
733: while (e.hasMoreElements())
734: {
735: int tagSize = ((TagEntry) e.nextElement()).getSize();
736: if ((tagSize & 0x0003) != 0)
737: tagSize += 4 - (tagSize & 0x0003);
738: totalSize += tagSize;
739: }
740: return totalSize;
741: }
742:
743:
746: private byte[] getTagTable()
747: {
748: int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
749: if ((tagTableSize & 0x0003) != 0)
750: tagTableSize += 4 - (tagTableSize & 0x0003);
751:
752: int offset = 4;
753: int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
754: ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
755: buf.putInt(tagTable.size());
756:
757: Enumeration e = tagTable.elements();
758: while (e.hasMoreElements())
759: {
760: TagEntry tag = (TagEntry) e.nextElement();
761: buf.putInt(offset, tag.getSignature());
762: buf.putInt(offset + 4, tagOffset);
763: buf.putInt(offset + 8, tag.getSize());
764: tag.setOffset(tagOffset);
765: int tagSize = tag.getSize();
766: if ((tagSize & 0x0003) != 0)
767: tagSize += 4 - (tagSize & 0x0003);
768: tagOffset += tagSize;
769: offset += 12;
770: }
771: return buf.array();
772: }
773:
774:
782: private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
783: {
784: if (header.getColorSpace() != ColorSpace.TYPE_RGB)
785: return false;
786: if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
787: return false;
788: if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
789: return false;
790: if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
791: return false;
792: if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
793: return false;
794: if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
795: return false;
796: if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
797: return false;
798: return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
799: }
800:
801:
808: private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
809: {
810: if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
811: return false;
812: if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
813: return false;
814: return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
815: }
816:
817:
825: short[] getCurve(int signature)
826: {
827: byte[] data = getData(signature);
828: short[] curve;
829:
830:
831: if (data == null)
832: return null;
833:
834:
835: ByteBuffer buf = ByteBuffer.wrap(data);
836: if (buf.getInt(0) != 0x63757276)
837: return null;
838: int count = buf.getInt(8);
839: if (count == 0)
840: {
841: curve = new short[1];
842: curve[0] = 0x0100;
843: return curve;
844: }
845: if (count == 1)
846: {
847: curve = new short[1];
848: curve[0] = buf.getShort(12);
849: return curve;
850: }
851: curve = new short[count];
852: for (int i = 0; i < count; i++)
853: curve[i] = buf.getShort(12 + i * 2);
854: return curve;
855: }
856:
857:
863: float[] getXYZData(int signature)
864: {
865: byte[] data = getData(signature);
866:
867:
868: if (data == null)
869: return null;
870:
871:
872: ByteBuffer buf = ByteBuffer.wrap(data);
873: if (buf.getInt(0) != icSigXYZData)
874: return null;
875:
876: float[] point = new float[3];
877:
878:
879: point[0] = ((float) buf.getInt(8)) / 65536f;
880: point[1] = ((float) buf.getInt(12)) / 65536f;
881: point[2] = ((float) buf.getInt(16)) / 65536f;
882: return point;
883: }
884:
885:
891: int isPredefined()
892: {
893: return profileID;
894: }
895:
896:
899: private byte[] makeXYZData(float[] values)
900: {
901: ByteBuffer buf = ByteBuffer.allocate(20);
902: buf.putInt(0, icSigXYZData);
903: buf.putInt(4, 0);
904: buf.putInt(8, (int) (values[0] * 65536.0));
905: buf.putInt(12, (int) (values[1] * 65536.0));
906: buf.putInt(16, (int) (values[2] * 65536.0));
907: return buf.array();
908: }
909:
910:
913: private byte[] makeTextTag(String text)
914: {
915: int length = text.length();
916: ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
917: byte[] data;
918: try
919: {
920: data = text.getBytes("US-ASCII");
921: }
922: catch (UnsupportedEncodingException e)
923: {
924: data = new byte[length];
925: }
926:
927: buf.putInt(0, (int) 0x74657874);
928: buf.putInt(4, 0);
929: for (int i = 0; i < length; i++)
930: buf.put(8 + i, data[i]);
931: buf.put(8 + length, (byte) 0);
932: return buf.array();
933: }
934:
935:
938: private byte[] makeDescTag(String text)
939: {
940: int length = text.length();
941: ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
942: buf.putInt(0, (int) 0x64657363);
943: buf.putInt(4, 0);
944: buf.putInt(8, length + 1);
945: byte[] data;
946:
947: try
948: {
949: data = text.getBytes("US-ASCII");
950: }
951: catch (UnsupportedEncodingException e)
952: {
953: data = new byte[length];
954: }
955:
956: for (int i = 0; i < length; i++)
957: buf.put(12 + i, data[i]);
958: buf.put(12 + length, (byte) 0);
959:
960: for (int i = 0; i < 39; i++)
961: buf.putShort(13 + length + (i * 2), (short) 0);
962:
963: return buf.array();
964: }
965:
966:
969: private byte[] makeTRC()
970: {
971: ByteBuffer buf = ByteBuffer.allocate(12);
972: buf.putInt(0, 0x63757276);
973: buf.putInt(4, 0);
974: buf.putInt(8, 0);
975: return buf.array();
976: }
977:
978:
981: private byte[] makeTRC(float gamma)
982: {
983: short gammaValue = (short) (gamma * 256f);
984: ByteBuffer buf = ByteBuffer.allocate(14);
985: buf.putInt(0, 0x63757276);
986: buf.putInt(4, 0);
987: buf.putInt(8, 1);
988: buf.putShort(12, gammaValue);
989: return buf.array();
990: }
991:
992:
995: private byte[] makeTRC(float[] trc)
996: {
997: ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
998: buf.putInt(0, 0x63757276);
999: buf.putInt(4, 0);
1000: buf.putInt(8, trc.length);
1001:
1002:
1003: for (int i = 0; i < trc.length; i++)
1004: buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
1005:
1006: return buf.array();
1007: }
1008:
1009:
1012: private byte[] makeIdentityClut()
1013: {
1014: final int nIn = 3;
1015: final int nOut = 3;
1016: final int nInEntries = 256;
1017: final int nOutEntries = 256;
1018: final int gridpoints = 16;
1019:
1020:
1021: final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
1022: final int totalSize = clutSize + 2 * nInEntries * nIn
1023: + 2 * nOutEntries * nOut + 52;
1024:
1025: ByteBuffer buf = ByteBuffer.allocate(totalSize);
1026: buf.putInt(0, 0x6D667432);
1027: buf.putInt(4, 0);
1028: buf.put(8, (byte) nIn);
1029: buf.put(9, (byte) nOut);
1030: buf.put(10, (byte) gridpoints);
1031: buf.put(11, (byte) 0);
1032:
1033:
1034: buf.putInt(12, 65536);
1035: buf.putInt(16, 0);
1036: buf.putInt(20, 0);
1037: buf.putInt(24, 0);
1038: buf.putInt(28, 65536);
1039: buf.putInt(32, 0);
1040: buf.putInt(36, 0);
1041: buf.putInt(40, 0);
1042: buf.putInt(44, 65536);
1043:
1044: buf.putShort(48, (short) nInEntries);
1045: buf.putShort(50, (short) nOutEntries);
1046:
1047:
1048:
1049: for (int channel = 0; channel < 3; channel++)
1050: for (int i = 0; i < nInEntries; i++)
1051: {
1052: short n = (short) ((i << 8) | i);
1053: buf.putShort(52 + (channel * nInEntries + i) * 2, n);
1054: }
1055: int clutOffset = 52 + nInEntries * nIn * 2;
1056:
1057: for (int x = 0; x < gridpoints; x++)
1058: for (int y = 0; y < gridpoints; y++)
1059: for (int z = 0; z < gridpoints; z++)
1060: {
1061: int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
1062: + x * gridpoints * gridpoints * 2 * nOut;
1063: double xf = ((double) x) / ((double) gridpoints - 1.0);
1064: double yf = ((double) y) / ((double) gridpoints - 1.0);
1065: double zf = ((double) z) / ((double) gridpoints - 1.0);
1066: buf.putShort(offset, (short) (xf * 65535.0));
1067: buf.putShort(offset + 2, (short) (yf * 65535.0));
1068: buf.putShort(offset + 4, (short) (zf * 65535.0));
1069: }
1070:
1071: for (int channel = 0; channel < 3; channel++)
1072: for (int i = 0; i < nOutEntries; i++)
1073: {
1074: short n = (short) ((i << 8) | i);
1075: buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
1076: n);
1077: }
1078:
1079: return buf.array();
1080: }
1081:
1082:
1085: private void createProfile(int colorSpace) throws IllegalArgumentException
1086: {
1087: this.profileID = colorSpace;
1088: header = new ProfileHeader();
1089: tagTable = new Hashtable();
1090:
1091: switch (colorSpace)
1092: {
1093: case ColorSpace.CS_sRGB:
1094: createRGBProfile();
1095: return;
1096: case ColorSpace.CS_LINEAR_RGB:
1097: createLinearRGBProfile();
1098: return;
1099: case ColorSpace.CS_CIEXYZ:
1100: createCIEProfile();
1101: return;
1102: case ColorSpace.CS_GRAY:
1103: createGrayProfile();
1104: return;
1105: case ColorSpace.CS_PYCC:
1106: createPyccProfile();
1107: return;
1108: default:
1109: throw new IllegalArgumentException("Not a predefined color space!");
1110: }
1111: }
1112:
1113:
1116: private void createRGBProfile()
1117: {
1118: header.setColorSpace( ColorSpace.TYPE_RGB );
1119: header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1120: ICC_ColorSpace cs = new ICC_ColorSpace(this);
1121:
1122: float[] r = { 1f, 0f, 0f };
1123: float[] g = { 0f, 1f, 0f };
1124: float[] b = { 0f, 0f, 1f };
1125: float[] black = { 0f, 0f, 0f };
1126:
1127:
1128: float[] white = D50;
1129:
1130:
1131: r = cs.toCIEXYZ(r);
1132: g = cs.toCIEXYZ(g);
1133: b = cs.toCIEXYZ(b);
1134:
1135:
1136:
1137: cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
1138: float[] points = new float[TRC_POINTS];
1139: float[] in = new float[3];
1140: for (int i = 0; i < TRC_POINTS; i++)
1141: {
1142: in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
1143: in = cs.fromRGB(in);
1144:
1145: points[i] = in[0];
1146: }
1147:
1148: setData(icSigRedColorantTag, makeXYZData(r));
1149: setData(icSigGreenColorantTag, makeXYZData(g));
1150: setData(icSigBlueColorantTag, makeXYZData(b));
1151: setData(icSigMediaWhitePointTag, makeXYZData(white));
1152: setData(icSigMediaBlackPointTag, makeXYZData(black));
1153: setData(icSigRedTRCTag, makeTRC(points));
1154: setData(icSigGreenTRCTag, makeTRC(points));
1155: setData(icSigBlueTRCTag, makeTRC(points));
1156: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1157: setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
1158: this.profileID = ColorSpace.CS_sRGB;
1159: }
1160:
1161:
1164: private void createLinearRGBProfile()
1165: {
1166: header.setColorSpace(ColorSpace.TYPE_RGB);
1167: header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1168: ICC_ColorSpace cs = new ICC_ColorSpace(this);
1169:
1170: float[] r = { 1f, 0f, 0f };
1171: float[] g = { 0f, 1f, 0f };
1172: float[] b = { 0f, 0f, 1f };
1173: float[] black = { 0f, 0f, 0f };
1174:
1175: float[] white = D50;
1176:
1177:
1178: r = cs.toCIEXYZ(r);
1179: g = cs.toCIEXYZ(g);
1180: b = cs.toCIEXYZ(b);
1181:
1182: setData(icSigRedColorantTag, makeXYZData(r));
1183: setData(icSigGreenColorantTag, makeXYZData(g));
1184: setData(icSigBlueColorantTag, makeXYZData(b));
1185:
1186: setData(icSigMediaWhitePointTag, makeXYZData(white));
1187: setData(icSigMediaBlackPointTag, makeXYZData(black));
1188:
1189: setData(icSigRedTRCTag, makeTRC());
1190: setData(icSigGreenTRCTag, makeTRC());
1191: setData(icSigBlueTRCTag, makeTRC());
1192: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1193: setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
1194: this.profileID = ColorSpace.CS_LINEAR_RGB;
1195: }
1196:
1197:
1200: private void createCIEProfile()
1201: {
1202: header.setColorSpace( ColorSpace.TYPE_XYZ );
1203: header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1204: header.setProfileClass( CLASS_COLORSPACECONVERSION );
1205: ICC_ColorSpace cs = new ICC_ColorSpace(this);
1206:
1207: float[] white = D50;
1208:
1209: setData(icSigMediaWhitePointTag, makeXYZData(white));
1210: setData(icSigAToB0Tag, makeIdentityClut());
1211: setData(icSigBToA0Tag, makeIdentityClut());
1212: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1213: setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
1214: this.profileID = ColorSpace.CS_CIEXYZ;
1215: }
1216:
1217:
1220: private void createGrayProfile()
1221: {
1222: header.setColorSpace(ColorSpace.TYPE_GRAY);
1223: header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1224:
1225:
1226: float[] white = D50;
1227:
1228: setData(icSigMediaWhitePointTag, makeXYZData(white));
1229: setData(icSigGrayTRCTag, makeTRC(1.0f));
1230: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1231: setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
1232: this.profileID = ColorSpace.CS_GRAY;
1233: }
1234:
1235:
1238: private void createPyccProfile()
1239: {
1240: header.setColorSpace(ColorSpace.TYPE_3CLR);
1241: header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1242:
1243:
1244:
1245: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1246: setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
1247: this.profileID = ColorSpace.CS_PYCC;
1248: }
1249: }