KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > color > ICC_Profile


1 /*
2  * @(#)ICC_Profile.java 1.36 06/11/14
3  *
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 /**********************************************************************
9  **********************************************************************
10  **********************************************************************
11  *** COPYRIGHT (c) Eastman Kodak Company, 1997 ***
12  *** As an unpublished work pursuant to Title 17 of the United ***
13  *** States Code. All rights reserved. ***
14  **********************************************************************
15  **********************************************************************
16  **********************************************************************/

17
18 package java.awt.color;
19
20 import sun.awt.color.CMM;
21 import sun.awt.color.ProfileDeferralMgr;
22 import sun.awt.color.ProfileDeferralInfo;
23 import sun.awt.color.ProfileActivator;
24
25 import java.io.File JavaDoc;
26 import java.io.FileInputStream JavaDoc;
27 import java.io.FileNotFoundException JavaDoc;
28 import java.io.FileOutputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.InputStream JavaDoc;
31 import java.io.ObjectInputStream JavaDoc;
32 import java.io.ObjectOutputStream JavaDoc;
33 import java.io.ObjectStreamException JavaDoc;
34 import java.io.OutputStream JavaDoc;
35 import java.io.Serializable JavaDoc;
36
37 import java.util.StringTokenizer JavaDoc;
38
39 import java.security.AccessController JavaDoc;
40 import java.security.PrivilegedAction JavaDoc;
41
42 /**
43  * A representation of color profile data for device independent and
44  * device dependent color spaces based on the International Color
45  * Consortium Specification ICC.1:2001-12, File Format for Color Profiles,
46  * (see <A HREF="http://www.color.org"> http://www.color.org</A>).
47  * <p>
48  * An ICC_ColorSpace object can be constructed from an appropriate
49  * ICC_Profile.
50  * Typically, an ICC_ColorSpace would be associated with an ICC
51  * Profile which is either an input, display, or output profile (see
52  * the ICC specification). There are also device link, abstract,
53  * color space conversion, and named color profiles. These are less
54  * useful for tagging a color or image, but are useful for other
55  * purposes (in particular device link profiles can provide improved
56  * performance for converting from one device's color space to
57  * another's).
58  * <p>
59  * ICC Profiles represent transformations from the color space of
60  * the profile (e.g. a monitor) to a Profile Connection Space (PCS).
61  * Profiles of interest for tagging images or colors have a PCS
62  * which is one of the two specific device independent
63  * spaces (one CIEXYZ space and one CIELab space) defined in the
64  * ICC Profile Format Specification. Most profiles of interest
65  * either have invertible transformations or explicitly specify
66  * transformations going both directions.
67  * <p>
68  * @version 10 Feb 1997
69  * @see ICC_ColorSpace
70  */

71
72
73 public class ICC_Profile implements Serializable JavaDoc {
74
75     private static final long serialVersionUID = -3938515861990936766L;
76
77     transient long ID;
78
79     private transient ProfileDeferralInfo deferralInfo;
80     private transient ProfileActivator profileActivator;
81
82     // Registry of singleton profile objects for specific color spaces
83
// defined in the ColorSpace class (e.g. CS_sRGB), see
84
// getInstance(int cspace) factory method.
85
private static ICC_Profile JavaDoc sRGBprofile;
86     private static ICC_Profile JavaDoc XYZprofile;
87     private static ICC_Profile JavaDoc PYCCprofile;
88     private static ICC_Profile JavaDoc GRAYprofile;
89     private static ICC_Profile JavaDoc LINEAR_RGBprofile;
90
91
92     /**
93      * Profile class is input.
94      */

95     public static final int CLASS_INPUT = 0;
96
97     /**
98      * Profile class is display.
99      */

100     public static final int CLASS_DISPLAY = 1;
101
102     /**
103      * Profile class is output.
104      */

105     public static final int CLASS_OUTPUT = 2;
106
107     /**
108      * Profile class is device link.
109      */

110     public static final int CLASS_DEVICELINK = 3;
111
112     /**
113      * Profile class is color space conversion.
114      */

115     public static final int CLASS_COLORSPACECONVERSION = 4;
116
117     /**
118      * Profile class is abstract.
119      */

120     public static final int CLASS_ABSTRACT = 5;
121
122     /**
123      * Profile class is named color.
124      */

125     public static final int CLASS_NAMEDCOLOR = 6;
126
127
128     /**
129      * ICC Profile Color Space Type Signature: 'XYZ '.
130      */

131     public static final int icSigXYZData = 0x58595A20; /* 'XYZ ' */
132
133     /**
134      * ICC Profile Color Space Type Signature: 'Lab '.
135      */

136     public static final int icSigLabData = 0x4C616220; /* 'Lab ' */
137
138     /**
139      * ICC Profile Color Space Type Signature: 'Luv '.
140      */

141     public static final int icSigLuvData = 0x4C757620; /* 'Luv ' */
142
143     /**
144      * ICC Profile Color Space Type Signature: 'YCbr'.
145      */

146     public static final int icSigYCbCrData = 0x59436272; /* 'YCbr' */
147
148     /**
149      * ICC Profile Color Space Type Signature: 'Yxy '.
150      */

151     public static final int icSigYxyData = 0x59787920; /* 'Yxy ' */
152
153     /**
154      * ICC Profile Color Space Type Signature: 'RGB '.
155      */

156     public static final int icSigRgbData = 0x52474220; /* 'RGB ' */
157
158     /**
159      * ICC Profile Color Space Type Signature: 'GRAY'.
160      */

161     public static final int icSigGrayData = 0x47524159; /* 'GRAY' */
162
163     /**
164      * ICC Profile Color Space Type Signature: 'HSV'.
165      */

166     public static final int icSigHsvData = 0x48535620; /* 'HSV ' */
167
168     /**
169      * ICC Profile Color Space Type Signature: 'HLS'.
170      */

171     public static final int icSigHlsData = 0x484C5320; /* 'HLS ' */
172
173     /**
174      * ICC Profile Color Space Type Signature: 'CMYK'.
175      */

176     public static final int icSigCmykData = 0x434D594B; /* 'CMYK' */
177
178     /**
179      * ICC Profile Color Space Type Signature: 'CMY '.
180      */

181     public static final int icSigCmyData = 0x434D5920; /* 'CMY ' */
182
183     /**
184      * ICC Profile Color Space Type Signature: '2CLR'.
185      */

186     public static final int icSigSpace2CLR = 0x32434C52; /* '2CLR' */
187
188     /**
189      * ICC Profile Color Space Type Signature: '3CLR'.
190      */

191     public static final int icSigSpace3CLR = 0x33434C52; /* '3CLR' */
192
193     /**
194      * ICC Profile Color Space Type Signature: '4CLR'.
195      */

196     public static final int icSigSpace4CLR = 0x34434C52; /* '4CLR' */
197
198     /**
199      * ICC Profile Color Space Type Signature: '5CLR'.
200      */

201     public static final int icSigSpace5CLR = 0x35434C52; /* '5CLR' */
202
203     /**
204      * ICC Profile Color Space Type Signature: '6CLR'.
205      */

206     public static final int icSigSpace6CLR = 0x36434C52; /* '6CLR' */
207
208     /**
209      * ICC Profile Color Space Type Signature: '7CLR'.
210      */

211     public static final int icSigSpace7CLR = 0x37434C52; /* '7CLR' */
212
213     /**
214      * ICC Profile Color Space Type Signature: '8CLR'.
215      */

216     public static final int icSigSpace8CLR = 0x38434C52; /* '8CLR' */
217
218     /**
219      * ICC Profile Color Space Type Signature: '9CLR'.
220      */

221     public static final int icSigSpace9CLR = 0x39434C52; /* '9CLR' */
222
223     /**
224      * ICC Profile Color Space Type Signature: 'ACLR'.
225      */

226     public static final int icSigSpaceACLR = 0x41434C52; /* 'ACLR' */
227
228     /**
229      * ICC Profile Color Space Type Signature: 'BCLR'.
230      */

231     public static final int icSigSpaceBCLR = 0x42434C52; /* 'BCLR' */
232
233     /**
234      * ICC Profile Color Space Type Signature: 'CCLR'.
235      */

236     public static final int icSigSpaceCCLR = 0x43434C52; /* 'CCLR' */
237
238     /**
239      * ICC Profile Color Space Type Signature: 'DCLR'.
240      */

241     public static final int icSigSpaceDCLR = 0x44434C52; /* 'DCLR' */
242
243     /**
244      * ICC Profile Color Space Type Signature: 'ECLR'.
245      */

246     public static final int icSigSpaceECLR = 0x45434C52; /* 'ECLR' */
247
248     /**
249      * ICC Profile Color Space Type Signature: 'FCLR'.
250      */

251     public static final int icSigSpaceFCLR = 0x46434C52; /* 'FCLR' */
252
253
254     /**
255      * ICC Profile Class Signature: 'scnr'.
256      */

257     public static final int icSigInputClass = 0x73636E72; /* 'scnr' */
258
259     /**
260      * ICC Profile Class Signature: 'mntr'.
261      */

262     public static final int icSigDisplayClass = 0x6D6E7472; /* 'mntr' */
263
264     /**
265      * ICC Profile Class Signature: 'prtr'.
266      */

267     public static final int icSigOutputClass = 0x70727472; /* 'prtr' */
268
269     /**
270      * ICC Profile Class Signature: 'link'.
271      */

272     public static final int icSigLinkClass = 0x6C696E6B; /* 'link' */
273
274     /**
275      * ICC Profile Class Signature: 'abst'.
276      */

277     public static final int icSigAbstractClass = 0x61627374; /* 'abst' */
278
279     /**
280      * ICC Profile Class Signature: 'spac'.
281      */

282     public static final int icSigColorSpaceClass = 0x73706163; /* 'spac' */
283
284     /**
285      * ICC Profile Class Signature: 'nmcl'.
286      */

287     public static final int icSigNamedColorClass = 0x6e6d636c; /* 'nmcl' */
288
289
290     /**
291      * ICC Profile Rendering Intent: Perceptual.
292      */

293     public static final int icPerceptual = 0;
294
295     /**
296      * ICC Profile Rendering Intent: RelativeColorimetric.
297      */

298     public static final int icRelativeColorimetric = 1;
299
300     /**
301      * ICC Profile Rendering Intent: Media-RelativeColorimetric.
302      */

303     public static final int icMediaRelativeColorimetric = 1;
304
305     /**
306      * ICC Profile Rendering Intent: Saturation.
307      */

308     public static final int icSaturation = 2;
309
310     /**
311      * ICC Profile Rendering Intent: AbsoluteColorimetric.
312      */

313     public static final int icAbsoluteColorimetric = 3;
314
315     /**
316      * ICC Profile Rendering Intent: ICC-AbsoluteColorimetric.
317      */

318     public static final int icICCAbsoluteColorimetric = 3;
319
320
321     /**
322      * ICC Profile Tag Signature: 'head' - special.
323      */

324     public static final int icSigHead = 0x68656164; /* 'head' - special */
325
326     /**
327      * ICC Profile Tag Signature: 'A2B0'.
328      */

329     public static final int icSigAToB0Tag = 0x41324230; /* 'A2B0' */
330
331     /**
332      * ICC Profile Tag Signature: 'A2B1'.
333      */

334     public static final int icSigAToB1Tag = 0x41324231; /* 'A2B1' */
335
336     /**
337      * ICC Profile Tag Signature: 'A2B2'.
338      */

339     public static final int icSigAToB2Tag = 0x41324232; /* 'A2B2' */
340
341     /**
342      * ICC Profile Tag Signature: 'bXYZ'.
343      */

344     public static final int icSigBlueColorantTag = 0x6258595A; /* 'bXYZ' */
345
346     /**
347      * ICC Profile Tag Signature: 'bXYZ'.
348      */

349     public static final int icSigBlueMatrixColumnTag = 0x6258595A; /* 'bXYZ' */
350
351     /**
352      * ICC Profile Tag Signature: 'bTRC'.
353      */

354     public static final int icSigBlueTRCTag = 0x62545243; /* 'bTRC' */
355
356     /**
357      * ICC Profile Tag Signature: 'B2A0'.
358      */

359     public static final int icSigBToA0Tag = 0x42324130; /* 'B2A0' */
360
361     /**
362      * ICC Profile Tag Signature: 'B2A1'.
363      */

364     public static final int icSigBToA1Tag = 0x42324131; /* 'B2A1' */
365
366     /**
367      * ICC Profile Tag Signature: 'B2A2'.
368      */

369     public static final int icSigBToA2Tag = 0x42324132; /* 'B2A2' */
370
371     /**
372      * ICC Profile Tag Signature: 'calt'.
373      */

374     public static final int icSigCalibrationDateTimeTag = 0x63616C74;
375                                                                    /* 'calt' */
376
377     /**
378      * ICC Profile Tag Signature: 'targ'.
379      */

380     public static final int icSigCharTargetTag = 0x74617267; /* 'targ' */
381
382     /**
383      * ICC Profile Tag Signature: 'cprt'.
384      */

385     public static final int icSigCopyrightTag = 0x63707274; /* 'cprt' */
386
387     /**
388      * ICC Profile Tag Signature: 'crdi'.
389      */

390     public static final int icSigCrdInfoTag = 0x63726469; /* 'crdi' */
391
392     /**
393      * ICC Profile Tag Signature: 'dmnd'.
394      */

395     public static final int icSigDeviceMfgDescTag = 0x646D6E64; /* 'dmnd' */
396
397     /**
398      * ICC Profile Tag Signature: 'dmdd'.
399      */

400     public static final int icSigDeviceModelDescTag = 0x646D6464; /* 'dmdd' */
401
402     /**
403      * ICC Profile Tag Signature: 'devs'.
404      */

405     public static final int icSigDeviceSettingsTag = 0x64657673; /* 'devs' */
406
407     /**
408      * ICC Profile Tag Signature: 'gamt'.
409      */

410     public static final int icSigGamutTag = 0x67616D74; /* 'gamt' */
411
412     /**
413      * ICC Profile Tag Signature: 'kTRC'.
414      */

415     public static final int icSigGrayTRCTag = 0x6b545243; /* 'kTRC' */
416
417     /**
418      * ICC Profile Tag Signature: 'gXYZ'.
419      */

420     public static final int icSigGreenColorantTag = 0x6758595A; /* 'gXYZ' */
421
422     /**
423      * ICC Profile Tag Signature: 'gXYZ'.
424      */

425     public static final int icSigGreenMatrixColumnTag = 0x6758595A;/* 'gXYZ' */
426
427     /**
428      * ICC Profile Tag Signature: 'gTRC'.
429      */

430     public static final int icSigGreenTRCTag = 0x67545243; /* 'gTRC' */
431
432     /**
433      * ICC Profile Tag Signature: 'lumi'.
434      */

435     public static final int icSigLuminanceTag = 0x6C756d69; /* 'lumi' */
436
437     /**
438      * ICC Profile Tag Signature: 'meas'.
439      */

440     public static final int icSigMeasurementTag = 0x6D656173; /* 'meas' */
441
442     /**
443      * ICC Profile Tag Signature: 'bkpt'.
444      */

445     public static final int icSigMediaBlackPointTag = 0x626B7074; /* 'bkpt' */
446
447     /**
448      * ICC Profile Tag Signature: 'wtpt'.
449      */

450     public static final int icSigMediaWhitePointTag = 0x77747074; /* 'wtpt' */
451
452     /**
453      * ICC Profile Tag Signature: 'ncl2'.
454      */

455     public static final int icSigNamedColor2Tag = 0x6E636C32; /* 'ncl2' */
456
457     /**
458      * ICC Profile Tag Signature: 'resp'.
459      */

460     public static final int icSigOutputResponseTag = 0x72657370; /* 'resp' */
461
462     /**
463      * ICC Profile Tag Signature: 'pre0'.
464      */

465     public static final int icSigPreview0Tag = 0x70726530; /* 'pre0' */
466
467     /**
468      * ICC Profile Tag Signature: 'pre1'.
469      */

470     public static final int icSigPreview1Tag = 0x70726531; /* 'pre1' */
471
472     /**
473      * ICC Profile Tag Signature: 'pre2'.
474      */

475     public static final int icSigPreview2Tag = 0x70726532; /* 'pre2' */
476
477     /**
478      * ICC Profile Tag Signature: 'desc'.
479      */

480     public static final int icSigProfileDescriptionTag = 0x64657363;
481                                                                    /* 'desc' */
482
483     /**
484      * ICC Profile Tag Signature: 'pseq'.
485      */

486     public static final int icSigProfileSequenceDescTag = 0x70736571;
487                                                                    /* 'pseq' */
488
489     /**
490      * ICC Profile Tag Signature: 'psd0'.
491      */

492     public static final int icSigPs2CRD0Tag = 0x70736430; /* 'psd0' */
493
494     /**
495      * ICC Profile Tag Signature: 'psd1'.
496      */

497     public static final int icSigPs2CRD1Tag = 0x70736431; /* 'psd1' */
498
499     /**
500      * ICC Profile Tag Signature: 'psd2'.
501      */

502     public static final int icSigPs2CRD2Tag = 0x70736432; /* 'psd2' */
503
504     /**
505      * ICC Profile Tag Signature: 'psd3'.
506      */

507     public static final int icSigPs2CRD3Tag = 0x70736433; /* 'psd3' */
508
509     /**
510      * ICC Profile Tag Signature: 'ps2s'.
511      */

512     public static final int icSigPs2CSATag = 0x70733273; /* 'ps2s' */
513
514     /**
515      * ICC Profile Tag Signature: 'ps2i'.
516      */

517     public static final int icSigPs2RenderingIntentTag = 0x70733269;
518                                                                    /* 'ps2i' */
519
520     /**
521      * ICC Profile Tag Signature: 'rXYZ'.
522      */

523     public static final int icSigRedColorantTag = 0x7258595A; /* 'rXYZ' */
524
525     /**
526      * ICC Profile Tag Signature: 'rXYZ'.
527      */

528     public static final int icSigRedMatrixColumnTag = 0x7258595A; /* 'rXYZ' */
529
530     /**
531      * ICC Profile Tag Signature: 'rTRC'.
532      */

533     public static final int icSigRedTRCTag = 0x72545243; /* 'rTRC' */
534
535     /**
536      * ICC Profile Tag Signature: 'scrd'.
537      */

538     public static final int icSigScreeningDescTag = 0x73637264; /* 'scrd' */
539
540     /**
541      * ICC Profile Tag Signature: 'scrn'.
542      */

543     public static final int icSigScreeningTag = 0x7363726E; /* 'scrn' */
544
545     /**
546      * ICC Profile Tag Signature: 'tech'.
547      */

548     public static final int icSigTechnologyTag = 0x74656368; /* 'tech' */
549
550     /**
551      * ICC Profile Tag Signature: 'bfd '.
552      */

553     public static final int icSigUcrBgTag = 0x62666420; /* 'bfd ' */
554
555     /**
556      * ICC Profile Tag Signature: 'vued'.
557      */

558     public static final int icSigViewingCondDescTag = 0x76756564; /* 'vued' */
559
560     /**
561      * ICC Profile Tag Signature: 'view'.
562      */

563     public static final int icSigViewingConditionsTag = 0x76696577;/* 'view' */
564
565     /**
566      * ICC Profile Tag Signature: 'chrm'.
567      */

568     public static final int icSigChromaticityTag = 0x6368726d; /* 'chrm' */
569
570     /**
571      * ICC Profile Tag Signature: 'chad'.
572      */

573     public static final int icSigChromaticAdaptationTag = 0x63686164;/* 'chad' */
574
575     /**
576      * ICC Profile Tag Signature: 'clro'.
577      */

578     public static final int icSigColorantOrderTag = 0x636C726F; /* 'clro' */
579
580     /**
581      * ICC Profile Tag Signature: 'clrt'.
582      */

583     public static final int icSigColorantTableTag = 0x636C7274; /* 'clrt' */
584
585
586     /**
587      * ICC Profile Header Location: profile size in bytes.
588      */

589     public static final int icHdrSize = 0; /* Profile size in bytes */
590
591     /**
592      * ICC Profile Header Location: CMM for this profile.
593      */

594     public static final int icHdrCmmId = 4; /* CMM for this profile */
595
596     /**
597      * ICC Profile Header Location: format version number.
598      */

599     public static final int icHdrVersion = 8; /* Format version number */
600
601     /**
602      * ICC Profile Header Location: type of profile.
603      */

604     public static final int icHdrDeviceClass = 12; /* Type of profile */
605
606     /**
607      * ICC Profile Header Location: color space of data.
608      */

609     public static final int icHdrColorSpace = 16; /* Color space of data */
610
611     /**
612      * ICC Profile Header Location: PCS - XYZ or Lab only.
613      */

614     public static final int icHdrPcs = 20; /* PCS - XYZ or Lab only */
615
616     /**
617      * ICC Profile Header Location: date profile was created.
618      */

619     public static final int icHdrDate = 24; /* Date profile was created */
620
621     /**
622      * ICC Profile Header Location: icMagicNumber.
623      */

624     public static final int icHdrMagic = 36; /* icMagicNumber */
625
626     /**
627      * ICC Profile Header Location: primary platform.
628      */

629     public static final int icHdrPlatform = 40; /* Primary Platform */
630
631     /**
632      * ICC Profile Header Location: various bit settings.
633      */

634     public static final int icHdrFlags = 44; /* Various bit settings */
635
636     /**
637      * ICC Profile Header Location: device manufacturer.
638      */

639     public static final int icHdrManufacturer = 48; /* Device manufacturer */
640
641     /**
642      * ICC Profile Header Location: device model number.
643      */

644     public static final int icHdrModel = 52; /* Device model number */
645
646     /**
647      * ICC Profile Header Location: device attributes.
648      */

649     public static final int icHdrAttributes = 56; /* Device attributes */
650
651     /**
652      * ICC Profile Header Location: rendering intent.
653      */

654     public static final int icHdrRenderingIntent = 64; /* Rendering intent */
655
656     /**
657      * ICC Profile Header Location: profile illuminant.
658      */

659     public static final int icHdrIlluminant = 68; /* Profile illuminant */
660
661     /**
662      * ICC Profile Header Location: profile creator.
663      */

664     public static final int icHdrCreator = 80; /* Profile creator */
665
666     /**
667      * ICC Profile Header Location: profile's ID.
668      */

669     public static final int icHdrProfileID = 84; /* Profile's ID */
670
671
672     /**
673      * ICC Profile Constant: tag type signaturE.
674      */

675     public static final int icTagType = 0; /* tag type signature */
676
677     /**
678      * ICC Profile Constant: reserved.
679      */

680     public static final int icTagReserved = 4; /* reserved */
681
682     /**
683      * ICC Profile Constant: curveType count.
684      */

685     public static final int icCurveCount = 8; /* curveType count */
686
687     /**
688      * ICC Profile Constant: curveType data.
689      */

690     public static final int icCurveData = 12; /* curveType data */
691
692     /**
693      * ICC Profile Constant: XYZNumber X.
694      */

695     public static final int icXYZNumberX = 8; /* XYZNumber X */
696
697
698     /**
699      * Constructs an ICC_Profile object with a given ID.
700      */

701     ICC_Profile(long ID) {
702         this.ID = ID;
703     }
704
705
706     /**
707      * Constructs an ICC_Profile object whose loading will be deferred.
708      * The ID will be 0 until the profile is loaded.
709      */

710     ICC_Profile(ProfileDeferralInfo pdi) {
711         this.deferralInfo = pdi;
712         this.profileActivator = new ProfileActivator() {
713             public void activate() {
714                 activateDeferredProfile();
715             }
716         };
717         ProfileDeferralMgr.registerDeferral(this.profileActivator);
718     }
719
720
721     /**
722      * Frees the resources associated with an ICC_Profile object.
723      */

724     protected void finalize () {
725         if (ID != 0) {
726             CMM.checkStatus(CMM.cmmFreeProfile(ID));
727         } else if (profileActivator != null) {
728             ProfileDeferralMgr.unregisterDeferral(profileActivator);
729         }
730     }
731
732
733     /**
734      * Constructs an ICC_Profile object corresponding to the data in
735      * a byte array. Throws an IllegalArgumentException if the data
736      * does not correspond to a valid ICC Profile.
737      * @param data the specified ICC Profile data
738      * @return an <code>ICC_Profile</code> object corresponding to
739      * the data in the specified <code>data</code> array.
740      */

741     public static ICC_Profile JavaDoc getInstance(byte[] data) {
742     ICC_Profile JavaDoc thisProfile;
743
744         long[] theID = new long [1];
745
746         if (ProfileDeferralMgr.deferring) {
747             ProfileDeferralMgr.activateProfiles();
748         }
749         
750         try {
751             CMM.checkStatus(CMM.cmmLoadProfile(data, theID));
752         } catch (CMMException JavaDoc c) {
753             throw new IllegalArgumentException JavaDoc("Invalid ICC Profile Data");
754         }
755
756         try {
757             if ((getColorSpaceType (theID[0]) == ColorSpace.TYPE_GRAY) &&
758                 (getData (theID[0], icSigMediaWhitePointTag) != null) &&
759                 (getData (theID[0], icSigGrayTRCTag) != null)) {
760                 thisProfile = new ICC_ProfileGray JavaDoc (theID[0]);
761             }
762             else if ((getColorSpaceType (theID[0]) == ColorSpace.TYPE_RGB) &&
763                 (getData (theID[0], icSigMediaWhitePointTag) != null) &&
764                 (getData (theID[0], icSigRedColorantTag) != null) &&
765                 (getData (theID[0], icSigGreenColorantTag) != null) &&
766                 (getData (theID[0], icSigBlueColorantTag) != null) &&
767                 (getData (theID[0], icSigRedTRCTag) != null) &&
768                 (getData (theID[0], icSigGreenTRCTag) != null) &&
769                 (getData (theID[0], icSigBlueTRCTag) != null)) {
770                 thisProfile = new ICC_ProfileRGB JavaDoc (theID[0]);
771             }
772             else {
773                 thisProfile = new ICC_Profile JavaDoc (theID[0]);
774             }
775         } catch (CMMException JavaDoc c) {
776             thisProfile = new ICC_Profile JavaDoc (theID[0]);
777         }
778         return thisProfile;
779     }
780
781
782
783     /**
784      * Constructs an ICC_Profile corresponding to one of the specific color
785      * spaces defined by the ColorSpace class (for example CS_sRGB).
786      * Throws an IllegalArgumentException if cspace is not one of the
787      * defined color spaces.
788      *
789      * @param cspace the type of color space to create a profile for.
790      * The specified type is one of the color
791      * space constants defined in the <CODE>ColorSpace</CODE> class.
792      *
793      * @return an <code>ICC_Profile</code> object corresponding to
794      * the specified <code>ColorSpace</code> type.
795      * @exception IllegalArgumentException If <CODE>cspace</CODE> is not
796      * one of the predefined color space types.
797      */

798     public static ICC_Profile JavaDoc getInstance (int cspace) {
799     ICC_Profile JavaDoc thisProfile = null;
800     String JavaDoc fileName;
801
802     switch (cspace) {
803     case ColorSpace.CS_sRGB:
804             synchronized(ICC_Profile JavaDoc.class) {
805             if (sRGBprofile == null) {
806             try {
807                 /*
808                  * Deferral is only used for standard profiles.
809                  * Enabling the appropriate access privileges is handled
810                  * at a lower level.
811                  */

812                 sRGBprofile = getDeferredInstance(
813                 new ProfileDeferralInfo("sRGB.pf",
814                                                     ColorSpace.TYPE_RGB,
815                             3, CLASS_DISPLAY));
816             } catch (IOException JavaDoc e) {
817                 throw new IllegalArgumentException JavaDoc(
818                               "Can't load standard profile: sRGB.pf");
819             }
820             }
821             thisProfile = sRGBprofile;
822             }
823
824         break;
825
826     case ColorSpace.CS_CIEXYZ:
827             synchronized(ICC_Profile JavaDoc.class) {
828             if (XYZprofile == null) {
829             XYZprofile = getStandardProfile("CIEXYZ.pf");
830             }
831             thisProfile = XYZprofile;
832             }
833
834         break;
835
836     case ColorSpace.CS_PYCC:
837             synchronized(ICC_Profile JavaDoc.class) {
838             if (PYCCprofile == null) {
839             PYCCprofile = getStandardProfile("PYCC.pf");
840             }
841             thisProfile = PYCCprofile;
842             }
843
844         break;
845
846     case ColorSpace.CS_GRAY:
847             synchronized(ICC_Profile JavaDoc.class) {
848             if (GRAYprofile == null) {
849             GRAYprofile = getStandardProfile("GRAY.pf");
850             }
851             thisProfile = GRAYprofile;
852             }
853
854         break;
855
856     case ColorSpace.CS_LINEAR_RGB:
857             synchronized(ICC_Profile JavaDoc.class) {
858             if (LINEAR_RGBprofile == null) {
859             LINEAR_RGBprofile = getStandardProfile("LINEAR_RGB.pf");
860             }
861             thisProfile = LINEAR_RGBprofile;
862             }
863
864         break;
865
866     default:
867         throw new IllegalArgumentException JavaDoc("Unknown color space");
868     }
869
870         return thisProfile;
871     }
872
873     /* This asserts system privileges, so is used only for the
874      * standard profiles.
875      */

876     private static ICC_Profile JavaDoc getStandardProfile(final String JavaDoc name) {
877         
878     return (ICC_Profile JavaDoc) AccessController.doPrivileged(
879         new PrivilegedAction JavaDoc() {
880                  public Object JavaDoc run() {
881                      ICC_Profile JavaDoc p = null;
882                      try {
883                          p = getInstance (name);
884                      } catch (IOException JavaDoc ex) {
885                          throw new IllegalArgumentException JavaDoc(
886                    "Can't load standard profile: " + name);
887                      }
888                      return p;
889                  }
890              });
891     }
892
893     /**
894      * Constructs an ICC_Profile corresponding to the data in a file.
895      * fileName may be an absolute or a relative file specification.
896      * Relative file names are looked for in several places: first, relative
897      * to any directories specified by the java.iccprofile.path property;
898      * second, relative to any directories specified by the java.class.path
899      * property; finally, in a directory used to store profiles always
900      * available, such as the profile for sRGB. Built-in profiles use .pf as
901      * the file name extension for profiles, e.g. sRGB.pf.
902      * This method throws an IOException if the specified file cannot be
903      * opened or if an I/O error occurs while reading the file. It throws
904      * an IllegalArgumentException if the file does not contain valid ICC
905      * Profile data.
906      * @param fileName The file that contains the data for the profile.
907      *
908      * @return an <code>ICC_Profile</code> object corresponding to
909      * the data in the specified file.
910      * @exception IOException If the specified file cannot be opened or
911      * an I/O error occurs while reading the file.
912      *
913      * @exception IllegalArgumentException If the file does not
914      * contain valid ICC Profile data.
915      *
916      * @exception SecurityException If a security manager is installed
917      * and it does not permit read access to the given file.
918      */

919     public static ICC_Profile JavaDoc getInstance(String JavaDoc fileName) throws IOException JavaDoc {
920     ICC_Profile JavaDoc thisProfile;
921     FileInputStream JavaDoc fis;
922
923         SecurityManager JavaDoc security = System.getSecurityManager();
924     if (security != null) {
925             security.checkRead(fileName);
926         }
927
928         if ((fis = openProfile(fileName)) == null) {
929             throw new IOException JavaDoc("Cannot open file " + fileName);
930         }
931
932         thisProfile = getInstance(fis);
933
934         fis.close(); /* close the file */
935     
936         return thisProfile;
937     }
938
939
940     /**
941      * Constructs an ICC_Profile corresponding to the data in an InputStream.
942      * This method throws an IllegalArgumentException if the stream does not
943      * contain valid ICC Profile data. It throws an IOException if an I/O
944      * error occurs while reading the stream.
945      * @param s The input stream from which to read the profile data.
946      *
947      * @return an <CODE>ICC_Profile</CODE> object corresponding to the
948      * data in the specified <code>InputStream</code>.
949      *
950      * @exception IOException If an I/O error occurs while reading the stream.
951      *
952      * @exception IllegalArgumentException If the stream does not
953      * contain valid ICC Profile data.
954      */

955     public static ICC_Profile JavaDoc getInstance(InputStream JavaDoc s) throws IOException JavaDoc {
956     byte profileData[];
957
958         if (s instanceof ProfileDeferralInfo) {
959             /* hack to detect profiles whose loading can be deferred */
960             return getDeferredInstance((ProfileDeferralInfo) s);
961         }
962
963         if ((profileData = getProfileDataFromStream(s)) == null) {
964             throw new IllegalArgumentException JavaDoc("Invalid ICC Profile Data");
965         }
966
967         return getInstance(profileData);
968     }
969
970
971     static byte[] getProfileDataFromStream(InputStream JavaDoc s) throws IOException JavaDoc {
972     byte profileData[];
973     int profileSize;
974
975         byte header[] = new byte[128];
976         int bytestoread = 128;
977         int bytesread = 0;
978         int n;
979
980         while (bytestoread != 0) {
981             if ((n = s.read(header, bytesread, bytestoread)) < 0) {
982                 return null;
983             }
984             bytesread += n;
985             bytestoread -= n;
986         }
987         if (header[36] != 0x61 || header[37] != 0x63 ||
988             header[38] != 0x73 || header[39] != 0x70) {
989             return null; /* not a valid profile */
990         }
991         profileSize = ((header[0] & 0xff) << 24) |
992                       ((header[1] & 0xff) << 16) |
993                       ((header[2] & 0xff) << 8) |
994                        (header[3] & 0xff);
995         profileData = new byte[profileSize];
996         System.arraycopy(header, 0, profileData, 0, 128);
997         bytestoread = profileSize - 128;
998         bytesread = 128;
999         while (bytestoread != 0) {
1000            if ((n = s.read(profileData, bytesread, bytestoread)) < 0) {
1001                return null;
1002            }
1003            bytesread += n;
1004            bytestoread -= n;
1005        }
1006
1007        return profileData;
1008    }
1009
1010
1011    /**
1012     * Constructs an ICC_Profile for which the actual loading of the
1013     * profile data from a file and the initialization of the CMM should
1014     * be deferred as long as possible.
1015     * Deferral is only used for standard profiles.
1016     * If deferring is disabled, then getStandardProfile() ensures
1017     * that all of the appropriate access privileges are granted
1018     * when loading this profile.
1019     * If deferring is enabled, then the deferred activation
1020     * code will take care of access privileges.
1021     * @see activateDeferredProfile()
1022     */

1023    static ICC_Profile JavaDoc getDeferredInstance(ProfileDeferralInfo pdi)
1024        throws IOException JavaDoc {
1025
1026        if (!ProfileDeferralMgr.deferring) {
1027            return getStandardProfile(pdi.filename);
1028        }
1029        if (pdi.colorSpaceType == ColorSpace.TYPE_RGB) {
1030            return new ICC_ProfileRGB JavaDoc(pdi);
1031        } else if (pdi.colorSpaceType == ColorSpace.TYPE_GRAY) {
1032            return new ICC_ProfileGray JavaDoc(pdi);
1033        } else {
1034            return new ICC_Profile JavaDoc(pdi);
1035        }
1036    }
1037
1038
1039    void activateDeferredProfile() {
1040    long[] theID = new long [1];
1041    byte profileData[];
1042    FileInputStream JavaDoc fis;
1043    String JavaDoc fileName = deferralInfo.filename;
1044
1045        profileActivator = null;
1046        deferralInfo = null;
1047        if ((fis = openProfile(fileName)) == null) {
1048            throw new IllegalArgumentException JavaDoc("Cannot open file " + fileName);
1049        }
1050        try {
1051            profileData = getProfileDataFromStream(fis);
1052            fis.close(); /* close the file */
1053        }
1054        catch (IOException JavaDoc e) {
1055            throw new IllegalArgumentException JavaDoc("Invalid ICC Profile Data" +
1056                fileName);
1057        }
1058        if (profileData == null) {
1059            throw new IllegalArgumentException JavaDoc("Invalid ICC Profile Data" +
1060                fileName);
1061        }
1062        try {
1063            CMM.checkStatus(CMM.cmmLoadProfile(profileData, theID));
1064        } catch (CMMException JavaDoc c) {
1065            throw new IllegalArgumentException JavaDoc("Invalid ICC Profile Data" +
1066                fileName);
1067        }
1068        ID = theID[0];
1069    }
1070
1071
1072    /**
1073     * Returns profile major version.
1074     * @return The major version of the profile.
1075     */

1076    public int getMajorVersion() {
1077    byte[] theHeader;
1078    
1079        theHeader = getData(icSigHead); /* getData will activate deferred
1080                                           profiles if necessary */

1081
1082        return (int) theHeader[8];
1083    }
1084
1085    /**
1086     * Returns profile minor version.
1087     * @return The minor version of the profile.
1088     */

1089    public int getMinorVersion() {
1090    byte[] theHeader;
1091    
1092        theHeader = getData(icSigHead); /* getData will activate deferred
1093                                           profiles if necessary */

1094
1095        return (int) theHeader[9];
1096    }
1097
1098    /**
1099     * Returns the profile class.
1100     * @return One of the predefined profile class constants.
1101     */

1102    public int getProfileClass() {
1103    byte[] theHeader;
1104    int theClassSig, theClass;
1105    
1106        if (deferralInfo != null) {
1107            return deferralInfo.profileClass; /* Need to have this info for
1108                                                 ICC_ColorSpace without
1109                                                 causing a deferred profile
1110                                                 to be loaded */

1111        }
1112
1113        theHeader = getData(icSigHead);
1114
1115        theClassSig = intFromBigEndian (theHeader, icHdrDeviceClass);
1116                
1117        switch (theClassSig) {
1118        case icSigInputClass:
1119            theClass = CLASS_INPUT;
1120            break;
1121
1122        case icSigDisplayClass:
1123            theClass = CLASS_DISPLAY;
1124            break;
1125
1126        case icSigOutputClass:
1127            theClass = CLASS_OUTPUT;
1128            break;
1129
1130        case icSigLinkClass:
1131            theClass = CLASS_DEVICELINK;
1132            break;
1133
1134        case icSigColorSpaceClass:
1135            theClass = CLASS_COLORSPACECONVERSION;
1136            break;
1137
1138        case icSigAbstractClass:
1139            theClass = CLASS_ABSTRACT;
1140            break;
1141
1142        case icSigNamedColorClass:
1143            theClass = CLASS_NAMEDCOLOR;
1144            break;
1145
1146        default:
1147            throw new IllegalArgumentException JavaDoc("Unknown profile class");
1148        }
1149        
1150        return theClass;
1151    }
1152
1153    /**
1154     * Returns the color space type. Returns one of the color space type
1155     * constants defined by the ColorSpace class. This is the
1156     * "input" color space of the profile. The type defines the
1157     * number of components of the color space and the interpretation,
1158     * e.g. TYPE_RGB identifies a color space with three components - red,
1159     * green, and blue. It does not define the particular color
1160     * characteristics of the space, e.g. the chromaticities of the
1161     * primaries.
1162     * @return One of the color space type constants defined in the
1163     * <CODE>ColorSpace</CODE> class.
1164     */

1165    public int getColorSpaceType() {
1166        if (deferralInfo != null) {
1167            return deferralInfo.colorSpaceType; /* Need to have this info for
1168                                                   ICC_ColorSpace without
1169                                                   causing a deferred profile
1170                                                   to be loaded */

1171        }
1172        return getColorSpaceType(ID);
1173    }
1174    
1175    static int getColorSpaceType(long profileID) {
1176    byte[] theHeader;
1177    int theColorSpaceSig, theColorSpace;
1178    
1179        theHeader = getData(profileID, icSigHead);
1180        theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
1181        theColorSpace = iccCStoJCS (theColorSpaceSig);
1182        return theColorSpace;
1183    }
1184
1185    /**
1186     * Returns the color space type of the Profile Connection Space (PCS).
1187     * Returns one of the color space type constants defined by the
1188     * ColorSpace class. This is the "output" color space of the
1189     * profile. For an input, display, or output profile useful
1190     * for tagging colors or images, this will be either TYPE_XYZ or
1191     * TYPE_Lab and should be interpreted as the corresponding specific
1192     * color space defined in the ICC specification. For a device
1193     * link profile, this could be any of the color space type constants.
1194     * @return One of the color space type constants defined in the
1195     * <CODE>ColorSpace</CODE> class.
1196     */

1197    public int getPCSType() {
1198        if (ProfileDeferralMgr.deferring) {
1199            ProfileDeferralMgr.activateProfiles();
1200        }
1201        return getPCSType(ID);
1202    }
1203    
1204    
1205    static int getPCSType(long profileID) {
1206    byte[] theHeader;
1207    int thePCSSig, thePCS;
1208    
1209        theHeader = getData(profileID, icSigHead);
1210        thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
1211        thePCS = iccCStoJCS(thePCSSig);
1212        return thePCS;
1213    }
1214
1215
1216    /**
1217     * Write this ICC_Profile to a file.
1218     *
1219     * @param fileName The file to write the profile data to.
1220     *
1221     * @exception IOException If the file cannot be opened for writing
1222     * or an I/O error occurs while writing to the file.
1223     */

1224    public void write(String JavaDoc fileName) throws IOException JavaDoc {
1225    FileOutputStream JavaDoc outputFile;
1226    byte profileData[];
1227
1228        profileData = getData(); /* this will activate deferred
1229                                    profiles if necessary */

1230        outputFile = new FileOutputStream JavaDoc(fileName);
1231        outputFile.write(profileData);
1232        outputFile.close ();
1233    }
1234
1235
1236    /**
1237     * Write this ICC_Profile to an OutputStream.
1238     *
1239     * @param s The stream to write the profile data to.
1240     *
1241     * @exception IOException If an I/O error occurs while writing to the
1242     * stream.
1243     */

1244    public void write(OutputStream JavaDoc s) throws IOException JavaDoc {
1245    byte profileData[];
1246
1247        profileData = getData(); /* this will activate deferred
1248                                    profiles if necessary */

1249        s.write(profileData);
1250    }
1251
1252
1253    /**
1254     * Returns a byte array corresponding to the data of this ICC_Profile.
1255     * @return A byte array that contains the profile data.
1256     * @see #setData(int, byte[])
1257     */

1258    public byte[] getData() {
1259    int[] profileSize = new int [1];
1260    byte[] profileData;
1261
1262        if (ProfileDeferralMgr.deferring) {
1263            ProfileDeferralMgr.activateProfiles();
1264        }
1265
1266        /* get the number of bytes needed for this profile */
1267        CMM.checkStatus(CMM.cmmGetProfileSize(ID, profileSize));
1268
1269        profileData = new byte [profileSize[0]];
1270
1271        /* get the data for the profile */
1272        CMM.checkStatus(CMM.cmmGetProfileData(ID, profileData));
1273
1274        return profileData;
1275    }
1276
1277
1278    /**
1279     * Returns a particular tagged data element from the profile as
1280     * a byte array. Elements are identified by signatures
1281     * as defined in the ICC specification. The signature
1282     * icSigHead can be used to get the header. This method is useful
1283     * for advanced applets or applications which need to access
1284     * profile data directly.
1285     *
1286     * @param tagSignature The ICC tag signature for the data element you
1287     * want to get.
1288     *
1289     * @return A byte array that contains the tagged data element. Returns
1290     * <code>null</code> if the specified tag doesn't exist.
1291     * @see #setData(int, byte[])
1292     */

1293    public byte[] getData(int tagSignature) {
1294
1295        if (ProfileDeferralMgr.deferring) {
1296            ProfileDeferralMgr.activateProfiles();
1297        }
1298
1299        return getData(ID, tagSignature);
1300    }
1301    
1302
1303    static byte[] getData(long profileID, int tagSignature) {
1304    int[] tagSize = new int [1];
1305    byte[] tagData;
1306
1307    try {
1308            /* get the number of bytes needed for this tag */
1309            CMM.checkStatus(CMM.cmmGetTagSize(profileID, tagSignature,
1310                                              tagSize));
1311
1312            tagData = new byte[tagSize[0]]; /* get an array for the tag */
1313
1314            /* get the tag's data */
1315            CMM.checkStatus(CMM.cmmGetTagData(profileID, tagSignature,
1316                                              tagData));
1317    } catch(CMMException JavaDoc c) {
1318        tagData = null;
1319    }
1320
1321        return tagData;
1322    }
1323
1324    /**
1325     * Sets a particular tagged data element in the profile from
1326     * a byte array. This method is useful
1327     * for advanced applets or applications which need to access
1328     * profile data directly.
1329     *
1330     * @param tagSignature The ICC tag signature for the data element
1331     * you want to set.
1332     * @param tagData the data to set for the specified tag signature
1333     * @see #getData
1334     */

1335    public void setData(int tagSignature, byte[] tagData) {
1336
1337        if (ProfileDeferralMgr.deferring) {
1338            ProfileDeferralMgr.activateProfiles();
1339        }
1340
1341        CMM.checkStatus(CMM.cmmSetTagData(ID, tagSignature, tagData));
1342    }
1343
1344    /**
1345     * Sets the rendering intent of the profile.
1346     * This is used to select the proper transform from a profile that
1347     * has multiple transforms.
1348     */

1349    void setRenderingIntent(int renderingIntent) {
1350        byte[] theHeader = getData(icSigHead);/* getData will activate deferred
1351                                                 profiles if necessary */

1352        intToBigEndian (renderingIntent, theHeader, icHdrRenderingIntent);
1353                                                 /* set the rendering intent */
1354        setData (icSigHead, theHeader);
1355    }
1356
1357
1358    /**
1359     * Returns the rendering intent of the profile.
1360     * This is used to select the proper transform from a profile that
1361     * has multiple transforms. It is typically set in a source profile
1362     * to select a transform from an output profile.
1363     */

1364    int getRenderingIntent() {
1365        byte[] theHeader = getData(icSigHead);/* getData will activate deferred
1366                                                 profiles if necessary */

1367        
1368        int renderingIntent = intFromBigEndian(theHeader, icHdrRenderingIntent);
1369                                                 /* set the rendering intent */
1370        return renderingIntent;
1371    }
1372
1373
1374    /**
1375     * Returns the number of color components in the "input" color
1376     * space of this profile. For example if the color space type
1377     * of this profile is TYPE_RGB, then this method will return 3.
1378     *
1379     * @return The number of color components in the profile's input
1380     * color space.
1381     *
1382     * @throws ProfileDataException if color space is in the profile
1383     * is invalid
1384     */

1385    public int getNumComponents() {
1386    byte[] theHeader;
1387    int theColorSpaceSig, theNumComponents;
1388    
1389        if (deferralInfo != null) {
1390            return deferralInfo.numComponents; /* Need to have this info for
1391                                                  ICC_ColorSpace without
1392                                                  causing a deferred profile
1393                                                  to be loaded */

1394        }
1395        theHeader = getData(icSigHead);
1396
1397        theColorSpaceSig = intFromBigEndian (theHeader, icHdrColorSpace);
1398
1399        switch (theColorSpaceSig) {
1400        case icSigGrayData:
1401            theNumComponents = 1;
1402            break;
1403
1404        case icSigSpace2CLR:
1405            theNumComponents = 2;
1406            break;
1407
1408        case icSigXYZData:
1409        case icSigLabData:
1410        case icSigLuvData:
1411        case icSigYCbCrData:
1412        case icSigYxyData:
1413        case icSigRgbData:
1414        case icSigHsvData:
1415        case icSigHlsData:
1416        case icSigCmyData:
1417        case icSigSpace3CLR:
1418            theNumComponents = 3;
1419            break;
1420
1421        case icSigCmykData:
1422        case icSigSpace4CLR:
1423            theNumComponents = 4;
1424            break;
1425
1426        case icSigSpace5CLR:
1427            theNumComponents = 5;
1428            break;
1429
1430        case icSigSpace6CLR:
1431            theNumComponents = 6;
1432            break;
1433
1434        case icSigSpace7CLR:
1435            theNumComponents = 7;
1436            break;
1437
1438        case icSigSpace8CLR:
1439            theNumComponents = 8;
1440            break;
1441
1442        case icSigSpace9CLR:
1443            theNumComponents = 9;
1444            break;
1445
1446        case icSigSpaceACLR:
1447            theNumComponents = 10;
1448            break;
1449
1450        case icSigSpaceBCLR:
1451            theNumComponents = 11;
1452            break;
1453
1454        case icSigSpaceCCLR:
1455            theNumComponents = 12;
1456            break;
1457
1458        case icSigSpaceDCLR:
1459            theNumComponents = 13;
1460            break;
1461
1462        case icSigSpaceECLR:
1463            theNumComponents = 14;
1464            break;
1465
1466        case icSigSpaceFCLR:
1467            theNumComponents = 15;
1468            break;
1469
1470        default:
1471            throw new ProfileDataException JavaDoc ("invalid ICC color space");
1472        }
1473        
1474        return theNumComponents;
1475    }
1476
1477
1478    /**
1479     * Returns a float array of length 3 containing the X, Y, and Z
1480     * components of the mediaWhitePointTag in the ICC profile.
1481     */

1482    float[] getMediaWhitePoint() {
1483        return getXYZTag(icSigMediaWhitePointTag);
1484                                           /* get the media white point tag */
1485    }
1486
1487
1488    /**
1489     * Returns a float array of length 3 containing the X, Y, and Z
1490     * components encoded in an XYZType tag.
1491     */

1492    float[] getXYZTag(int theTagSignature) {
1493    byte[] theData;
1494    float[] theXYZNumber;
1495    int i1, i2, theS15Fixed16;
1496    
1497        theData = getData(theTagSignature); /* get the tag data */
1498                                            /* getData will activate deferred
1499                                               profiles if necessary */

1500        
1501        theXYZNumber = new float [3]; /* array to return */
1502
1503        /* convert s15Fixed16Number to float */
1504        for (i1 = 0, i2 = icXYZNumberX; i1 < 3; i1++, i2 += 4) {
1505            theS15Fixed16 = intFromBigEndian(theData, i2);
1506            theXYZNumber [i1] = ((float) theS15Fixed16) / 65536.0f;
1507        }
1508        return theXYZNumber;
1509    }
1510
1511
1512    /**
1513     * Returns a gamma value representing a tone reproduction
1514     * curve (TRC). If the profile represents the TRC as a table rather
1515     * than a single gamma value, then an exception is thrown. In this
1516     * case the actual table can be obtained via getTRC().
1517     * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag,
1518     * icSigGreenTRCTag, or icSigBlueTRCTag.
1519     * @return the gamma value as a float.
1520     * @exception ProfileDataException if the profile does not specify
1521     * the TRC as a single gamma value.
1522     */

1523    float getGamma(int theTagSignature) {
1524    byte[] theTRCData;
1525    float theGamma;
1526    int theU8Fixed8;
1527
1528        theTRCData = getData(theTagSignature); /* get the TRC */
1529                                               /* getData will activate deferred
1530                                                  profiles if necessary */

1531        
1532        if (intFromBigEndian (theTRCData, icCurveCount) != 1) {
1533            throw new ProfileDataException JavaDoc ("TRC is not a gamma");
1534        }
1535
1536        /* convert u8Fixed8 to float */
1537        theU8Fixed8 = (shortFromBigEndian(theTRCData, icCurveData)) & 0xffff;
1538            
1539        theGamma = ((float) theU8Fixed8) / 256.0f;
1540        
1541        return theGamma;
1542    }
1543
1544
1545    /**
1546     * Returns the TRC as an array of shorts. If the profile has
1547     * specified the TRC as linear (gamma = 1.0) or as a simple gamma
1548     * value, this method throws an exception, and the getGamma() method
1549     * should be used to get the gamma value. Otherwise the short array
1550     * returned here represents a lookup table where the input Gray value
1551     * is conceptually in the range [0.0, 1.0]. Value 0.0 maps
1552     * to array index 0 and value 1.0 maps to array index length-1.
1553     * Interpolation may be used to generate output values for
1554     * input values which do not map exactly to an index in the
1555     * array. Output values also map linearly to the range [0.0, 1.0].
1556     * Value 0.0 is represented by an array value of 0x0000 and
1557     * value 1.0 by 0xFFFF, i.e. the values are really unsigned
1558     * short values, although they are returned in a short array.
1559     * theTagSignature should be one of icSigGrayTRCTag, icSigRedTRCTag,
1560     * icSigGreenTRCTag, or icSigBlueTRCTag.
1561     * @return a short array representing the TRC.
1562     * @exception ProfileDataException if the profile does not specify
1563     * the TRC as a table.
1564     */

1565    short[] getTRC(int theTagSignature) {
1566    byte[] theTRCData;
1567    short[] theTRC;
1568    int i1, i2, nElements, theU8Fixed8;
1569
1570        theTRCData = getData(theTagSignature); /* get the TRC */
1571                                               /* getData will activate deferred
1572                                                  profiles if necessary */

1573        
1574        nElements = intFromBigEndian(theTRCData, icCurveCount);
1575
1576        if (nElements == 1) {
1577            throw new ProfileDataException JavaDoc("TRC is not a table");
1578        }
1579
1580        /* make the short array */
1581        theTRC = new short [nElements];
1582
1583        for (i1 = 0, i2 = icCurveData; i1 < nElements; i1++, i2 += 2) {
1584            theTRC[i1] = shortFromBigEndian(theTRCData, i2);
1585        }
1586        
1587        return theTRC;
1588    }
1589
1590
1591    /* convert an ICC color space signature into a Java color space type */
1592    static int iccCStoJCS(int theColorSpaceSig) {
1593    int theColorSpace;
1594
1595        switch (theColorSpaceSig) {
1596        case icSigXYZData:
1597            theColorSpace = ColorSpace.TYPE_XYZ;
1598            break;
1599
1600        case icSigLabData:
1601            theColorSpace = ColorSpace.TYPE_Lab;
1602            break;
1603
1604        case icSigLuvData:
1605            theColorSpace = ColorSpace.TYPE_Luv;
1606            break;
1607
1608        case icSigYCbCrData:
1609            theColorSpace = ColorSpace.TYPE_YCbCr;
1610            break;
1611
1612        case icSigYxyData:
1613            theColorSpace = ColorSpace.TYPE_Yxy;
1614            break;
1615
1616        case icSigRgbData:
1617            theColorSpace = ColorSpace.TYPE_RGB;
1618            break;
1619
1620        case icSigGrayData:
1621            theColorSpace = ColorSpace.TYPE_GRAY;
1622            break;
1623
1624        case icSigHsvData:
1625            theColorSpace = ColorSpace.TYPE_HSV;
1626            break;
1627
1628        case icSigHlsData:
1629            theColorSpace = ColorSpace.TYPE_HLS;
1630            break;
1631
1632        case icSigCmykData:
1633            theColorSpace = ColorSpace.TYPE_CMYK;
1634            break;
1635
1636        case icSigCmyData:
1637            theColorSpace = ColorSpace.TYPE_CMY;
1638            break;
1639
1640        case icSigSpace2CLR:
1641            theColorSpace = ColorSpace.TYPE_2CLR;
1642            break;
1643
1644        case icSigSpace3CLR:
1645            theColorSpace = ColorSpace.TYPE_3CLR;
1646            break;
1647
1648        case icSigSpace4CLR:
1649            theColorSpace = ColorSpace.TYPE_4CLR;
1650            break;
1651
1652        case icSigSpace5CLR:
1653            theColorSpace = ColorSpace.TYPE_5CLR;
1654            break;
1655
1656        case icSigSpace6CLR:
1657            theColorSpace = ColorSpace.TYPE_6CLR;
1658            break;
1659
1660        case icSigSpace7CLR:
1661            theColorSpace = ColorSpace.TYPE_7CLR;
1662            break;
1663
1664        case icSigSpace8CLR:
1665            theColorSpace = ColorSpace.TYPE_8CLR;
1666            break;
1667
1668        case icSigSpace9CLR:
1669            theColorSpace = ColorSpace.TYPE_9CLR;
1670            break;
1671
1672        case icSigSpaceACLR:
1673            theColorSpace = ColorSpace.TYPE_ACLR;
1674            break;
1675
1676        case icSigSpaceBCLR:
1677            theColorSpace = ColorSpace.TYPE_BCLR;
1678            break;
1679
1680        case icSigSpaceCCLR:
1681            theColorSpace = ColorSpace.TYPE_CCLR;
1682            break;
1683
1684        case icSigSpaceDCLR:
1685            theColorSpace = ColorSpace.TYPE_DCLR;
1686            break;
1687
1688        case icSigSpaceECLR:
1689            theColorSpace = ColorSpace.TYPE_ECLR;
1690            break;
1691
1692        case icSigSpaceFCLR:
1693            theColorSpace = ColorSpace.TYPE_FCLR;
1694            break;
1695
1696        default:
1697            throw new IllegalArgumentException JavaDoc ("Unknown color space");
1698        }
1699        
1700        return theColorSpace;
1701    }
1702    
1703    
1704    static int intFromBigEndian(byte[] array, int index) {
1705        return (((array[index] & 0xff) << 24) |
1706                ((array[index+1] & 0xff) << 16) |
1707                ((array[index+2] & 0xff) << 8) |
1708                 (array[index+3] & 0xff));
1709    }
1710    
1711    
1712    static void intToBigEndian(int value, byte[] array, int index) {
1713            array[index] = (byte) (value >> 24);
1714            array[index+1] = (byte) (value >> 16);
1715            array[index+2] = (byte) (value >> 8);
1716            array[index+3] = (byte) (value);
1717    }
1718    
1719    
1720    static short shortFromBigEndian(byte[] array, int index) {
1721        return (short) (((array[index] & 0xff) << 8) |
1722                         (array[index+1] & 0xff));
1723    }
1724    
1725    
1726    static void shortToBigEndian(short value, byte[] array, int index) {
1727            array[index] = (byte) (value >> 8);
1728            array[index+1] = (byte) (value);
1729    }
1730
1731
1732    /*
1733     * fileName may be an absolute or a relative file specification.
1734     * Relative file names are looked for in several places: first, relative
1735     * to any directories specified by the java.iccprofile.path property;
1736     * second, relative to any directories specified by the java.class.path
1737     * property; finally, in a directory used to store profiles always
1738     * available, such as a profile for sRGB. Built-in profiles use .pf as
1739     * the file name extension for profiles, e.g. sRGB.pf.
1740     */

1741    private static FileInputStream JavaDoc openProfile(final String JavaDoc fileName) {
1742    return (FileInputStream JavaDoc)java.security.AccessController.doPrivileged(
1743        new java.security.PrivilegedAction JavaDoc() {
1744        public Object JavaDoc run() {
1745        return privilegedOpenProfile(fileName);
1746        }
1747    });
1748    }
1749
1750    /*
1751     * this version is called from doPrivileged in privilegedOpenProfile.
1752     * the whole method is privileged!
1753     */

1754    private static FileInputStream JavaDoc privilegedOpenProfile(String JavaDoc fileName) {
1755        FileInputStream JavaDoc fis = null;
1756        String JavaDoc path, dir, fullPath;
1757
1758        File JavaDoc f = new File JavaDoc(fileName); /* try absolute file name */
1759
1760        if ((!f.isFile()) &&
1761        ((path = System.getProperty("java.iccprofile.path")) != null)){
1762                                    /* try relative to java.iccprofile.path */
1763            StringTokenizer JavaDoc st =
1764            new StringTokenizer JavaDoc(path, File.pathSeparator);
1765                while (st.hasMoreTokens() && (!f.isFile())) {
1766            dir = st.nextToken();
1767                fullPath = dir + File.separatorChar + fileName;
1768                    f = new File JavaDoc(fullPath);
1769        }
1770        }
1771
1772        if ((!f.isFile()) &&
1773        ((path = System.getProperty("java.class.path")) != null)) {
1774                                    /* try relative to java.class.path */
1775            StringTokenizer JavaDoc st =
1776            new StringTokenizer JavaDoc(path, File.pathSeparator);
1777                while (st.hasMoreTokens() && (!f.isFile())) {
1778            dir = st.nextToken();
1779                fullPath = dir + File.separatorChar + fileName;
1780                    f = new File JavaDoc(fullPath);
1781        }
1782        }
1783
1784        if (!f.isFile()) { /* try the directory of built-in profiles */
1785            dir = System.getProperty("java.home") +
1786            File.separatorChar + "lib" + File.separatorChar + "cmm";
1787        fullPath = dir + File.separatorChar + fileName;
1788                f = new File JavaDoc(fullPath);
1789        }
1790
1791        if (f.isFile()) {
1792            try {
1793                fis = new FileInputStream JavaDoc(f);
1794            } catch (FileNotFoundException JavaDoc e) {
1795            }
1796        }
1797        return fis;
1798    }
1799
1800
1801    /*
1802     * Serialization support.
1803     *
1804     * Directly deserialized profiles are useless since they are not
1805     * registered with CMM. We don't allow constructor to be called
1806     * directly and instead have clients to call one of getInstance
1807     * factory methods that will register the profile with CMM. For
1808     * deserialization we implement readResolve method that will
1809     * resolve the bogus deserialized profile object with one obtained
1810     * with getInstance as well.
1811     *
1812     * There're two primary factory methods for construction of ICC
1813     * profiles: getInstance(int cspace) and getInstance(byte[] data).
1814     * This implementation of ICC_Profile uses the former to return a
1815     * cached singleton profile object, other implementations will
1816     * likely use this technique too. To preserve the singleton
1817     * pattern across serialization we serialize cached singleton
1818     * profiles in such a way that deserializing VM could call
1819     * getInstance(int cspace) method that will resolve deserialized
1820     * object into the corresponding singleton as well.
1821     *
1822     * Since the singletons are private to ICC_Profile the readResolve
1823     * method have to be `protected' instead of `private' so that
1824     * singletons that are instances of subclasses of ICC_Profile
1825     * could be correctly deserialized.
1826     */

1827
1828
1829    /**
1830     * Version of the format of additional serialized data in the
1831     * stream. Version&nbsp;<code>1</code> corresponds to Java&nbsp;2
1832     * Platform,&nbsp;v1.3.
1833     * @since 1.3
1834     * @serial
1835     */

1836    private int iccProfileSerializedDataVersion = 1;
1837
1838
1839    /**
1840     * Writes default serializable fields to the stream. Writes a
1841     * string and an array of bytes to the stream as additional data.
1842     *
1843     * @param s stream used for serialization.
1844     * @throws IOException
1845     * thrown by <code>ObjectInputStream</code>.
1846     * @serialData
1847     * The <code>String</code> is the name of one of
1848     * <code>CS_<var>*</var></code> constants defined in the
1849     * {@link ColorSpace} class if the profile object is a profile
1850     * for a predefined color space (for example
1851     * <code>"CS_sRGB"</code>). The string is <code>null</code>
1852     * otherwise.
1853     * <p>
1854     * The <code>byte[]</code> array is the profile data for the
1855     * profile. For predefined color spaces <code>null</code> is
1856     * written instead of the profile data. If in the future
1857     * versions of Java API new predefined color spaces will be
1858     * added, future versions of this class may choose to write
1859     * for new predefined color spaces not only the color space
1860     * name, but the profile data as well so that older versions
1861     * could still deserialize the object.
1862     */

1863    private void writeObject(ObjectOutputStream JavaDoc s)
1864      throws IOException JavaDoc
1865    {
1866    s.defaultWriteObject();
1867
1868    String JavaDoc csName = null;
1869    if (this == sRGBprofile) {
1870        csName = "CS_sRGB";
1871    } else if (this == XYZprofile) {
1872        csName = "CS_CIEXYZ";
1873    } else if (this == PYCCprofile) {
1874        csName = "CS_PYCC";
1875    } else if (this == GRAYprofile) {
1876        csName = "CS_GRAY";
1877    } else if (this == LINEAR_RGBprofile) {
1878        csName = "CS_LINEAR_RGB";
1879    }
1880
1881    // Future versions may choose to write profile data for new
1882
// predefined color spaces as well, if any will be introduced,
1883
// so that old versions that don't recognize the new CS name
1884
// may fall back to constructing profile from the data.
1885
byte[] data = null;
1886    if (csName == null) {
1887        // getData will activate deferred profile if necessary
1888
data = getData();
1889    }
1890
1891    s.writeObject(csName);
1892    s.writeObject(data);
1893    }
1894
1895    // Temporary storage used by readObject to store resolved profile
1896
// (obtained with getInstance) for readResolve to return.
1897
private transient ICC_Profile JavaDoc resolvedDeserializedProfile;
1898
1899    /**
1900     * Reads default serializable fields from the stream. Reads from
1901     * the stream a string and an array of bytes as additional data.
1902     *
1903     * @param s stream used for deserialization.
1904     * @throws IOException
1905     * thrown by <code>ObjectInputStream</code>.
1906     * @throws ClassNotFoundException
1907     * thrown by <code>ObjectInputStream</code>.
1908     * @serialData
1909     * The <code>String</code> is the name of one of
1910     * <code>CS_<var>*</var></code> constants defined in the
1911     * {@link ColorSpace} class if the profile object is a profile
1912     * for a predefined color space (for example
1913     * <code>"CS_sRGB"</code>). The string is <code>null</code>
1914     * otherwise.
1915     * <p>
1916     * The <code>byte[]</code> array is the profile data for the
1917     * profile. It will usually be <code>null</code> for the
1918     * predefined profiles.
1919     * <p>
1920     * If the string is recognized as a constant name for
1921     * predefined color space the object will be resolved into
1922     * profile obtained with
1923     * <code>getInstance(int&nbsp;cspace)</code> and the profile
1924     * data are ignored. Otherwise the object will be resolved
1925     * into profile obtained with
1926     * <code>getInstance(byte[]&nbsp;data)</code>.
1927     * @see #readResolve()
1928     * @see #getInstance(int)
1929     * @see #getInstance(byte[])
1930     */

1931    private void readObject(ObjectInputStream JavaDoc s)
1932      throws IOException JavaDoc, ClassNotFoundException JavaDoc
1933    {
1934    s.defaultReadObject();
1935
1936    String JavaDoc csName = (String JavaDoc)s.readObject();
1937    byte[] data = (byte[])s.readObject();
1938
1939    int cspace = 0; // ColorSpace.CS_* constant if known
1940
boolean isKnownPredefinedCS = false;
1941    if (csName != null) {
1942        isKnownPredefinedCS = true;
1943        if (csName.equals("CS_sRGB")) {
1944        cspace = ColorSpace.CS_sRGB;
1945        } else if (csName.equals("CS_CIEXYZ")) {
1946        cspace = ColorSpace.CS_CIEXYZ;
1947        } else if (csName.equals("CS_PYCC")) {
1948        cspace = ColorSpace.CS_PYCC;
1949        } else if (csName.equals("CS_GRAY")) {
1950        cspace = ColorSpace.CS_GRAY;
1951        } else if (csName.equals("CS_LINEAR_RGB")) {
1952        cspace = ColorSpace.CS_LINEAR_RGB;
1953        } else {
1954        isKnownPredefinedCS = false;
1955        }
1956    }
1957
1958    if (isKnownPredefinedCS) {
1959        resolvedDeserializedProfile = getInstance(cspace);
1960    } else {
1961        resolvedDeserializedProfile = getInstance(data);
1962    }
1963    }
1964
1965    /**
1966     * Resolves instances being deserialized into instances registered
1967     * with CMM.
1968     * @return ICC_Profile object for profile registered with CMM.
1969     * @throws ObjectStreamException
1970     * never thrown, but mandated by the serialization spec.
1971     */

1972    protected Object JavaDoc readResolve() throws ObjectStreamException JavaDoc {
1973    return resolvedDeserializedProfile;
1974    }
1975}
1976
Popular Tags