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: if (in.read(data, ProfileHeader.HEADERSIZE,
430: header.getSize() - ProfileHeader.HEADERSIZE) != header.getSize()
431: - ProfileHeader.HEADERSIZE)
432: throw new IOException("Incorrect profile size");
433:
434: return getInstance(data);
435: }
436:
437:
440: public int getMajorVersion()
441: {
442: return header.getMajorVersion();
443: }
444:
445:
454: public int getMinorVersion()
455: {
456: return header.getMinorVersion();
457: }
458:
459:
465: public int getProfileClass()
466: {
467: return header.getProfileClass();
468: }
469:
470:
475: public int getColorSpaceType()
476: {
477: return header.getColorSpace();
478: }
479:
480:
486: public int getPCSType()
487: {
488: return header.getProfileColorSpace();
489: }
490:
491:
496: public void write(String filename) throws IOException
497: {
498: FileOutputStream out = new FileOutputStream(filename);
499: write(out);
500: out.flush();
501: out.close();
502: }
503:
504:
513: public void write(OutputStream out) throws IOException
514: {
515: out.write(getData());
516: }
517:
518:
524: public byte[] getData()
525: {
526: int size = getSize();
527: byte[] data = new byte[size];
528:
529:
530: System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
531:
532: byte[] tt = getTagTable();
533: System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
534:
535: Enumeration e = tagTable.elements();
536: while (e.hasMoreElements())
537: {
538: TagEntry tag = (TagEntry) e.nextElement();
539: System.arraycopy(tag.getData(), 0,
540: data, tag.getOffset(), tag.getSize());
541: }
542: return data;
543: }
544:
545:
552: public byte[] getData(int tagSignature)
553: {
554: if (tagSignature == icSigHead)
555: return header.getData(getSize());
556:
557: TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
558: if (t == null)
559: return null;
560: return t.getData();
561: }
562:
563:
572: public void setData(int tagSignature, byte[] data)
573: {
574: profileID = -1;
575:
576: if (tagSignature == icSigHead)
577: header = new ProfileHeader(data);
578: else
579: {
580: TagEntry t = new TagEntry(tagSignature, data);
581: tagTable.put(t.hashKey(), t);
582: }
583: }
584:
585:
588: public int getNumComponents()
589: {
590: int[] lookup =
591: {
592: ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
593: ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
594: ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
595: ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
596: ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
597: ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
598: ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
599: ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
600: ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
601: ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
602: ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
603: ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
604: ColorSpace.TYPE_FCLR, 15
605: };
606: for (int i = 0; i < lookup.length; i += 2)
607: if (header.getColorSpace() == lookup[i])
608: return lookup[i + 1];
609: return 3;
610: }
611:
612:
617: protected Object readResolve() throws ObjectStreamException
618: {
619: if (isRGBProfile(header, tagTable))
620: return new ICC_ProfileRGB(getData());
621: if (isGrayProfile(header, tagTable))
622: return new ICC_ProfileGray(getData());
623: return this;
624: }
625:
626:
629: private void readObject(ObjectInputStream s)
630: throws IOException, ClassNotFoundException
631: {
632: s.defaultReadObject();
633: String predef = (String) s.readObject();
634: byte[] data = (byte[]) s.readObject();
635:
636: if (data != null)
637: {
638: header = new ProfileHeader(data);
639: tagTable = createTagTable(data);
640: profileID = -1;
641: }
642:
643: if (predef != null)
644: {
645: predef = predef.intern();
646: if (predef.equals("CS_sRGB"))
647: createProfile(ColorSpace.CS_sRGB);
648: if (predef.equals("CS_LINEAR_RGB"))
649: createProfile(ColorSpace.CS_LINEAR_RGB);
650: if (predef.equals("CS_CIEXYZ"))
651: createProfile(ColorSpace.CS_CIEXYZ);
652: if (predef.equals("CS_GRAY"))
653: createProfile(ColorSpace.CS_GRAY);
654: if (predef.equals("CS_PYCC"))
655: createProfile(ColorSpace.CS_PYCC);
656: }
657: }
658:
659:
665: private void writeObject(ObjectOutputStream s) throws IOException
666: {
667: s.defaultWriteObject();
668: if (profileID == ColorSpace.CS_sRGB)
669: s.writeObject("CS_sRGB");
670: else if (profileID == ColorSpace.CS_LINEAR_RGB)
671: s.writeObject("CS_LINEAR_RGB");
672: else if (profileID == ColorSpace.CS_CIEXYZ)
673: s.writeObject("CS_CIEXYZ");
674: else if (profileID == ColorSpace.CS_GRAY)
675: s.writeObject("CS_GRAY");
676: else if (profileID == ColorSpace.CS_PYCC)
677: s.writeObject("CS_PYCC");
678: else
679: {
680: s.writeObject(null);
681: s.writeObject(getData());
682: return;
683: }
684: s.writeObject(null);
685: }
686:
687:
691: private static Hashtable createTagTable(byte[] data)
692: throws IllegalArgumentException
693: {
694: ByteBuffer buf = ByteBuffer.wrap(data);
695: int nTags = buf.getInt(tagTableOffset);
696:
697: Hashtable tagTable = new Hashtable();
698: for (int i = 0; i < nTags; i++)
699: {
700: TagEntry te = new TagEntry(buf.getInt(tagTableOffset
701: + i * TagEntry.entrySize + 4),
702: buf.getInt(tagTableOffset
703: + i * TagEntry.entrySize + 8),
704: buf.getInt(tagTableOffset
705: + i * TagEntry.entrySize + 12),
706: data);
707:
708: if (tagTable.put(te.hashKey(), te) != null)
709: throw new IllegalArgumentException("Duplicate tag in profile:" + te);
710: }
711: return tagTable;
712: }
713:
714:
718: private int getSize()
719: {
720: int totalSize = ProfileHeader.HEADERSIZE;
721:
722: int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
723: if ((tagTableSize & 0x0003) != 0)
724: tagTableSize += 4 - (tagTableSize & 0x0003);
725: totalSize += tagTableSize;
726:
727: Enumeration e = tagTable.elements();
728: while (e.hasMoreElements())
729: {
730: int tagSize = ((TagEntry) e.nextElement()).getSize();
731: if ((tagSize & 0x0003) != 0)
732: tagSize += 4 - (tagSize & 0x0003);
733: totalSize += tagSize;
734: }
735: return totalSize;
736: }
737:
738:
741: private byte[] getTagTable()
742: {
743: int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
744: if ((tagTableSize & 0x0003) != 0)
745: tagTableSize += 4 - (tagTableSize & 0x0003);
746:
747: int offset = 4;
748: int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
749: ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
750: buf.putInt(tagTable.size());
751:
752: Enumeration e = tagTable.elements();
753: while (e.hasMoreElements())
754: {
755: TagEntry tag = (TagEntry) e.nextElement();
756: buf.putInt(offset, tag.getSignature());
757: buf.putInt(offset + 4, tagOffset);
758: buf.putInt(offset + 8, tag.getSize());
759: tag.setOffset(tagOffset);
760: int tagSize = tag.getSize();
761: if ((tagSize & 0x0003) != 0)
762: tagSize += 4 - (tagSize & 0x0003);
763: tagOffset += tagSize;
764: offset += 12;
765: }
766: return buf.array();
767: }
768:
769:
777: private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
778: {
779: if (header.getColorSpace() != ColorSpace.TYPE_RGB)
780: return false;
781: if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
782: return false;
783: if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
784: return false;
785: if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
786: return false;
787: if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
788: return false;
789: if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
790: return false;
791: if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
792: return false;
793: return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
794: }
795:
796:
803: private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
804: {
805: if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
806: return false;
807: if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
808: return false;
809: return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
810: }
811:
812:
820: short[] getCurve(int signature)
821: {
822: byte[] data = getData(signature);
823: short[] curve;
824:
825:
826: if (data == null)
827: return null;
828:
829:
830: ByteBuffer buf = ByteBuffer.wrap(data);
831: if (buf.getInt(0) != 0x63757276)
832: return null;
833: int count = buf.getInt(8);
834: if (count == 0)
835: {
836: curve = new short[1];
837: curve[0] = 0x0100;
838: return curve;
839: }
840: if (count == 1)
841: {
842: curve = new short[1];
843: curve[0] = buf.getShort(12);
844: return curve;
845: }
846: curve = new short[count];
847: for (int i = 0; i < count; i++)
848: curve[i] = buf.getShort(12 + i * 2);
849: return curve;
850: }
851:
852:
858: float[] getXYZData(int signature)
859: {
860: byte[] data = getData(signature);
861:
862:
863: if (data == null)
864: return null;
865:
866:
867: ByteBuffer buf = ByteBuffer.wrap(data);
868: if (buf.getInt(0) != icSigXYZData)
869: return null;
870:
871: float[] point = new float[3];
872:
873:
874: point[0] = ((float) buf.getInt(8)) / 65536f;
875: point[1] = ((float) buf.getInt(12)) / 65536f;
876: point[2] = ((float) buf.getInt(16)) / 65536f;
877: return point;
878: }
879:
880:
886: int isPredefined()
887: {
888: return profileID;
889: }
890:
891:
894: private byte[] makeXYZData(float[] values)
895: {
896: ByteBuffer buf = ByteBuffer.allocate(20);
897: buf.putInt(0, icSigXYZData);
898: buf.putInt(4, 0);
899: buf.putInt(8, (int) (values[0] * 65536.0));
900: buf.putInt(12, (int) (values[1] * 65536.0));
901: buf.putInt(16, (int) (values[2] * 65536.0));
902: return buf.array();
903: }
904:
905:
908: private byte[] makeTextTag(String text)
909: {
910: int length = text.length();
911: ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
912: byte[] data;
913: try
914: {
915: data = text.getBytes("US-ASCII");
916: }
917: catch (UnsupportedEncodingException e)
918: {
919: data = new byte[length];
920: }
921:
922: buf.putInt(0, (int) 0x74657874);
923: buf.putInt(4, 0);
924: for (int i = 0; i < length; i++)
925: buf.put(8 + i, data[i]);
926: buf.put(8 + length, (byte) 0);
927: return buf.array();
928: }
929:
930:
933: private byte[] makeDescTag(String text)
934: {
935: int length = text.length();
936: ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
937: buf.putInt(0, (int) 0x64657363);
938: buf.putInt(4, 0);
939: buf.putInt(8, length + 1);
940: byte[] data;
941:
942: try
943: {
944: data = text.getBytes("US-ASCII");
945: }
946: catch (UnsupportedEncodingException e)
947: {
948: data = new byte[length];
949: }
950:
951: for (int i = 0; i < length; i++)
952: buf.put(12 + i, data[i]);
953: buf.put(12 + length, (byte) 0);
954:
955: for (int i = 0; i < 39; i++)
956: buf.putShort(13 + length + (i * 2), (short) 0);
957:
958: return buf.array();
959: }
960:
961:
964: private byte[] makeTRC()
965: {
966: ByteBuffer buf = ByteBuffer.allocate(12);
967: buf.putInt(0, 0x63757276);
968: buf.putInt(4, 0);
969: buf.putInt(8, 0);
970: return buf.array();
971: }
972:
973:
976: private byte[] makeTRC(float gamma)
977: {
978: short gammaValue = (short) (gamma * 256f);
979: ByteBuffer buf = ByteBuffer.allocate(14);
980: buf.putInt(0, 0x63757276);
981: buf.putInt(4, 0);
982: buf.putInt(8, 1);
983: buf.putShort(12, gammaValue);
984: return buf.array();
985: }
986:
987:
990: private byte[] makeTRC(float[] trc)
991: {
992: ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
993: buf.putInt(0, 0x63757276);
994: buf.putInt(4, 0);
995: buf.putInt(8, trc.length);
996:
997:
998: for (int i = 0; i < trc.length; i++)
999: buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
1000:
1001: return buf.array();
1002: }
1003:
1004:
1007: private byte[] makeIdentityClut()
1008: {
1009: final int nIn = 3;
1010: final int nOut = 3;
1011: final int nInEntries = 256;
1012: final int nOutEntries = 256;
1013: final int gridpoints = 16;
1014:
1015:
1016: final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
1017: final int totalSize = clutSize + 2 * nInEntries * nIn
1018: + 2 * nOutEntries * nOut + 52;
1019:
1020: ByteBuffer buf = ByteBuffer.allocate(totalSize);
1021: buf.putInt(0, 0x6D667432);
1022: buf.putInt(4, 0);
1023: buf.put(8, (byte) nIn);
1024: buf.put(9, (byte) nOut);
1025: buf.put(10, (byte) gridpoints);
1026: buf.put(11, (byte) 0);
1027:
1028:
1029: buf.putInt(12, 65536);
1030: buf.putInt(16, 0);
1031: buf.putInt(20, 0);
1032: buf.putInt(24, 0);
1033: buf.putInt(28, 65536);
1034: buf.putInt(32, 0);
1035: buf.putInt(36, 0);
1036: buf.putInt(40, 0);
1037: buf.putInt(44, 65536);
1038:
1039: buf.putShort(48, (short) nInEntries);
1040: buf.putShort(50, (short) nOutEntries);
1041:
1042:
1043:
1044: for (int channel = 0; channel < 3; channel++)
1045: for (int i = 0; i < nInEntries; i++)
1046: {
1047: short n = (short) ((i << 8) | i);
1048: buf.putShort(52 + (channel * nInEntries + i) * 2, n);
1049: }
1050: int clutOffset = 52 + nInEntries * nIn * 2;
1051:
1052: for (int x = 0; x < gridpoints; x++)
1053: for (int y = 0; y < gridpoints; y++)
1054: for (int z = 0; z < gridpoints; z++)
1055: {
1056: int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
1057: + x * gridpoints * gridpoints * 2 * nOut;
1058: double xf = ((double) x) / ((double) gridpoints - 1.0);
1059: double yf = ((double) y) / ((double) gridpoints - 1.0);
1060: double zf = ((double) z) / ((double) gridpoints - 1.0);
1061: buf.putShort(offset, (short) (xf * 65535.0));
1062: buf.putShort(offset + 2, (short) (yf * 65535.0));
1063: buf.putShort(offset + 4, (short) (zf * 65535.0));
1064: }
1065:
1066: for (int channel = 0; channel < 3; channel++)
1067: for (int i = 0; i < nOutEntries; i++)
1068: {
1069: short n = (short) ((i << 8) | i);
1070: buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
1071: n);
1072: }
1073:
1074: return buf.array();
1075: }
1076:
1077:
1080: private void createProfile(int colorSpace) throws IllegalArgumentException
1081: {
1082: this.profileID = colorSpace;
1083: header = new ProfileHeader();
1084: tagTable = new Hashtable();
1085:
1086: switch (colorSpace)
1087: {
1088: case ColorSpace.CS_sRGB:
1089: createRGBProfile();
1090: return;
1091: case ColorSpace.CS_LINEAR_RGB:
1092: createLinearRGBProfile();
1093: return;
1094: case ColorSpace.CS_CIEXYZ:
1095: createCIEProfile();
1096: return;
1097: case ColorSpace.CS_GRAY:
1098: createGrayProfile();
1099: return;
1100: case ColorSpace.CS_PYCC:
1101: createPyccProfile();
1102: return;
1103: default:
1104: throw new IllegalArgumentException("Not a predefined color space!");
1105: }
1106: }
1107:
1108:
1111: private void createRGBProfile()
1112: {
1113: header.setColorSpace( ColorSpace.TYPE_RGB );
1114: header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1115: ICC_ColorSpace cs = new ICC_ColorSpace(this);
1116:
1117: float[] r = { 1f, 0f, 0f };
1118: float[] g = { 0f, 1f, 0f };
1119: float[] b = { 0f, 0f, 1f };
1120: float[] black = { 0f, 0f, 0f };
1121:
1122:
1123: float[] white = D50;
1124:
1125:
1126: r = cs.toCIEXYZ(r);
1127: g = cs.toCIEXYZ(g);
1128: b = cs.toCIEXYZ(b);
1129:
1130:
1131:
1132: cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
1133: float[] points = new float[TRC_POINTS];
1134: float[] in = new float[3];
1135: for (int i = 0; i < TRC_POINTS; i++)
1136: {
1137: in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
1138: in = cs.fromRGB(in);
1139:
1140: points[i] = in[0];
1141: }
1142:
1143: setData(icSigRedColorantTag, makeXYZData(r));
1144: setData(icSigGreenColorantTag, makeXYZData(g));
1145: setData(icSigBlueColorantTag, makeXYZData(b));
1146: setData(icSigMediaWhitePointTag, makeXYZData(white));
1147: setData(icSigMediaBlackPointTag, makeXYZData(black));
1148: setData(icSigRedTRCTag, makeTRC(points));
1149: setData(icSigGreenTRCTag, makeTRC(points));
1150: setData(icSigBlueTRCTag, makeTRC(points));
1151: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1152: setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
1153: this.profileID = ColorSpace.CS_sRGB;
1154: }
1155:
1156:
1159: private void createLinearRGBProfile()
1160: {
1161: header.setColorSpace(ColorSpace.TYPE_RGB);
1162: header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1163: ICC_ColorSpace cs = new ICC_ColorSpace(this);
1164:
1165: float[] r = { 1f, 0f, 0f };
1166: float[] g = { 0f, 1f, 0f };
1167: float[] b = { 0f, 0f, 1f };
1168: float[] black = { 0f, 0f, 0f };
1169:
1170: float[] white = D50;
1171:
1172:
1173: r = cs.toCIEXYZ(r);
1174: g = cs.toCIEXYZ(g);
1175: b = cs.toCIEXYZ(b);
1176:
1177: setData(icSigRedColorantTag, makeXYZData(r));
1178: setData(icSigGreenColorantTag, makeXYZData(g));
1179: setData(icSigBlueColorantTag, makeXYZData(b));
1180:
1181: setData(icSigMediaWhitePointTag, makeXYZData(white));
1182: setData(icSigMediaBlackPointTag, makeXYZData(black));
1183:
1184: setData(icSigRedTRCTag, makeTRC());
1185: setData(icSigGreenTRCTag, makeTRC());
1186: setData(icSigBlueTRCTag, makeTRC());
1187: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1188: setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
1189: this.profileID = ColorSpace.CS_LINEAR_RGB;
1190: }
1191:
1192:
1195: private void createCIEProfile()
1196: {
1197: header.setColorSpace( ColorSpace.TYPE_XYZ );
1198: header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1199: header.setProfileClass( CLASS_COLORSPACECONVERSION );
1200: ICC_ColorSpace cs = new ICC_ColorSpace(this);
1201:
1202: float[] white = D50;
1203:
1204: setData(icSigMediaWhitePointTag, makeXYZData(white));
1205: setData(icSigAToB0Tag, makeIdentityClut());
1206: setData(icSigBToA0Tag, makeIdentityClut());
1207: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1208: setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
1209: this.profileID = ColorSpace.CS_CIEXYZ;
1210: }
1211:
1212:
1215: private void createGrayProfile()
1216: {
1217: header.setColorSpace(ColorSpace.TYPE_GRAY);
1218: header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1219:
1220:
1221: float[] white = D50;
1222:
1223: setData(icSigMediaWhitePointTag, makeXYZData(white));
1224: setData(icSigGrayTRCTag, makeTRC(1.0f));
1225: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1226: setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
1227: this.profileID = ColorSpace.CS_GRAY;
1228: }
1229:
1230:
1233: private void createPyccProfile()
1234: {
1235: header.setColorSpace(ColorSpace.TYPE_3CLR);
1236: header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1237:
1238:
1239:
1240: setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1241: setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
1242: this.profileID = ColorSpace.CS_PYCC;
1243: }
1244: }