/[classpath]/classpath/java/awt/color/ICC_Profile.java
ViewVC logotype

Diff of /classpath/java/awt/color/ICC_Profile.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5.2.1 by gnu_andrew, Fri Jan 14 10:24:15 2005 UTC revision 1.5.2.2 by gnu_andrew, Sat Jan 15 17:01:48 2005 UTC
# Line 1  Line 1 
1  /* ICC_Profile.java -- color space profiling  /* ICC_Profile.java -- color space profiling
2     Copyright (C) 2000, 2002 Free Software Foundation     Copyright (C) 2000, 2002, 2004 Free Software Foundation
3    
4  This file is part of GNU Classpath.     This file is part of GNU Classpath.
   
 GNU Classpath is free software; you can redistribute it and/or modify  
 it under the terms of the GNU General Public License as published by  
 the Free Software Foundation; either version 2, or (at your option)  
 any later version.  
   
 GNU Classpath is distributed in the hope that it will be useful, but  
 WITHOUT ANY WARRANTY; without even the implied warranty of  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
 General Public License for more details.  
   
 You should have received a copy of the GNU General Public License  
 along with GNU Classpath; see the file COPYING.  If not, write to the  
 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  
 02111-1307 USA.  
   
 Linking this library statically or dynamically with other modules is  
 making a combined work based on this library.  Thus, the terms and  
 conditions of the GNU General Public License cover the whole  
 combination.  
   
 As a special exception, the copyright holders of this library give you  
 permission to link this library with independent modules to produce an  
 executable, regardless of the license terms of these independent  
 modules, and to copy and distribute the resulting executable under  
 terms of your choice, provided that you also meet, for each linked  
 independent module, the terms and conditions of the license of that  
 module.  An independent module is a module which is not derived from  
 or based on this library.  If you modify this library, you may extend  
 this exception to your version of the library, but you are not  
 obligated to do so.  If you do not wish to do so, delete this  
 exception statement from your version. */  
5    
6       GNU Classpath is free software; you can redistribute it and/or modify
7       it under the terms of the GNU General Public License as published by
8       the Free Software Foundation; either version 2, or (at your option)
9       any later version.
10    
11       GNU Classpath is distributed in the hope that it will be useful, but
12       WITHOUT ANY WARRANTY; without even the implied warranty of
13       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14       General Public License for more details.
15    
16       You should have received a copy of the GNU General Public License
17       along with GNU Classpath; see the file COPYING.  If not, write to the
18       Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19       02111-1307 USA.
20    
21       Linking this library statically or dynamically with other modules is
22       making a combined work based on this library.  Thus, the terms and
23       conditions of the GNU General Public License cover the whole
24       combination.
25    
26       As a special exception, the copyright holders of this library give you
27       permission to link this library with independent modules to produce an
28       executable, regardless of the license terms of these independent
29       modules, and to copy and distribute the resulting executable under
30       terms of your choice, provided that you also meet, for each linked
31       independent module, the terms and conditions of the license of that
32       module.  An independent module is a module which is not derived from
33       or based on this library.  If you modify this library, you may extend
34       this exception to your version of the library, but you are not
35       obligated to do so.  If you do not wish to do so, delete this
36       exception statement from your version. */
37    
38  package java.awt.color;  package java.awt.color;
39    
40    import gnu.java.awt.color.ProfileHeader;
41    import gnu.java.awt.color.TagEntry;
42  import java.io.FileInputStream;  import java.io.FileInputStream;
43  import java.io.FileOutputStream;  import java.io.FileOutputStream;
44  import java.io.IOException;  import java.io.IOException;
# Line 47  import java.io.ObjectOutputStream; Line 48  import java.io.ObjectOutputStream;
48  import java.io.ObjectStreamException;  import java.io.ObjectStreamException;
49  import java.io.OutputStream;  import java.io.OutputStream;
50  import java.io.Serializable;  import java.io.Serializable;
51    import java.io.UnsupportedEncodingException;
52    import java.nio.ByteBuffer;
53    import java.util.Enumeration;
54    import java.util.Hashtable;
55    
56    
57  /**  /**
58   * STUBBED   * ICC Profile - represents an ICC Color profile.
59     * The ICC profile format is a standard file format which maps the transform
60     * from a device color space to a standard Profile Color Space (PCS), which
61     * can either be CIE L*a*b or CIE XYZ.
62     * (With the exception of device link profiles which map from one device space
63     * to another)
64     *
65     * ICC profiles calibrated to specific input/output devices are used when color
66     * fidelity is of importance.
67     *
68     * An instance of ICC_Profile can be created using the getInstance() methods,
69     * either using one of the predefined color spaces enumerated in ColorSpace,
70     * or from an ICC profile file, or from an input stream.
71     *
72     * An ICC_ColorSpace object can then be created to transform color values
73     * through the profile.
74     *
75     * The ICC_Profile class implements the version 2 format specified by
76     * International Color Consortium Specification ICC.1:1998-09,
77     * and its addendum ICC.1A:1999-04, April 1999
78     * (available at www.color.org)
79     *
80     * @author Sven de Marothy
81   * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>   * @author Rolf W. Rasmussen <rolfwr@ii.uib.no>
82   * @since 1.2   * @since 1.2
83   */   */
# Line 60  public class ICC_Profile implements Seri Line 88  public class ICC_Profile implements Seri
88     */     */
89    private static final long serialVersionUID = -3938515861990936766L;    private static final long serialVersionUID = -3938515861990936766L;
90    
91      /**
92       * ICC Profile classes
93       */
94    public static final int CLASS_INPUT = 0;    public static final int CLASS_INPUT = 0;
95    public static final int CLASS_DISPLAY = 1;    public static final int CLASS_DISPLAY = 1;
96    public static final int CLASS_OUTPUT = 2;    public static final int CLASS_OUTPUT = 2;
# Line 68  public class ICC_Profile implements Seri Line 99  public class ICC_Profile implements Seri
99    public static final int CLASS_ABSTRACT = 5;    public static final int CLASS_ABSTRACT = 5;
100    public static final int CLASS_NAMEDCOLOR = 6;    public static final int CLASS_NAMEDCOLOR = 6;
101    
102    public static final int icSigXYZData = 1482250784;    /**
103    public static final int icSigLabData = 1281450528;     * ICC Profile class signatures
104    public static final int icSigLuvData = 1282766368;     */
105    public static final int icSigYCbCrData = 1497588338;    public static final int icSigInputClass = 0x73636e72; // 'scnr'
106    public static final int icSigYxyData = 1501067552;    public static final int icSigDisplayClass = 0x6d6e7472; // 'mntr'
107    public static final int icSigRgbData = 1380401696;    public static final int icSigOutputClass = 0x70727472; // 'prtr'
108    public static final int icSigGrayData = 1196573017;    public static final int icSigLinkClass = 0x6c696e6b; // 'link'
109    public static final int icSigHsvData = 1213421088;    public static final int icSigColorSpaceClass = 0x73706163; // 'spac'
110    public static final int icSigHlsData = 1212961568;    public static final int icSigAbstractClass = 0x61627374; // 'abst'
111    public static final int icSigCmykData = 1129142603;    public static final int icSigNamedColorClass = 0x6e6d636c; // 'nmcl'
112    public static final int icSigCmyData = 1129142560;  
113    public static final int icSigSpace2CLR = 843271250;    /**
114    public static final int icSigSpace3CLR = 860048466;     * Color space signatures
115    public static final int icSigSpace4CLR = 876825682;     */
116    public static final int icSigSpace5CLR = 893602898;    public static final int icSigXYZData = 0x58595A20; // 'XYZ '
117    public static final int icSigSpace6CLR = 910380114;    public static final int icSigLabData = 0x4C616220; // 'Lab '
118    public static final int icSigSpace7CLR = 927157330;    public static final int icSigLuvData = 0x4C757620; // 'Luv '
119    public static final int icSigSpace8CLR = 943934546;    public static final int icSigYCbCrData = 0x59436272; // 'YCbr'
120    public static final int icSigSpace9CLR = 960711762;    public static final int icSigYxyData = 0x59787920; // 'Yxy '
121    public static final int icSigSpaceACLR = 1094929490;    public static final int icSigRgbData = 0x52474220; // 'RGB '
122    public static final int icSigSpaceBCLR = 1111706706;    public static final int icSigGrayData = 0x47524159; // 'GRAY'
123    public static final int icSigSpaceCCLR = 1128483922;    public static final int icSigHsvData = 0x48535620; // 'HSV '
124    public static final int icSigSpaceDCLR = 1145261138;    public static final int icSigHlsData = 0x484C5320; // 'HLS '
125    public static final int icSigSpaceECLR = 1162038354;    public static final int icSigCmykData = 0x434D594B; // 'CMYK'
126    public static final int icSigSpaceFCLR = 1178815570;    public static final int icSigCmyData = 0x434D5920; // 'CMY '
127      public static final int icSigSpace2CLR = 0x32434C52; // '2CLR'
128    public static final int icSigInputClass = 1935896178;    public static final int icSigSpace3CLR = 0x33434C52; // '3CLR'
129    public static final int icSigDisplayClass = 1835955314;    public static final int icSigSpace4CLR = 0x34434C52; // '4CLR'
130    public static final int icSigOutputClass = 1886549106;    public static final int icSigSpace5CLR = 0x35434C52; // '5CLR'
131    public static final int icSigLinkClass = 1818848875;    public static final int icSigSpace6CLR = 0x36434C52; // '6CLR'
132    public static final int icSigAbstractClass = 1633842036;    public static final int icSigSpace7CLR = 0x37434C52; // '7CLR'
133    public static final int icSigColorSpaceClass = 1936744803;    public static final int icSigSpace8CLR = 0x38434C52; // '8CLR'
134    public static final int icSigNamedColorClass = 1852662636;    public static final int icSigSpace9CLR = 0x39434C52; // '9CLR'
135      public static final int icSigSpaceACLR = 0x41434C52; // 'ACLR'
136      public static final int icSigSpaceBCLR = 0x42434C52; // 'BCLR'
137      public static final int icSigSpaceCCLR = 0x43434C52; // 'CCLR'
138      public static final int icSigSpaceDCLR = 0x44434C52; // 'DCLR'
139      public static final int icSigSpaceECLR = 0x45434C52; // 'ECLR'
140      public static final int icSigSpaceFCLR = 0x46434C52; // 'FCLR'
141    
142      /**
143       * Rendering intents
144       */
145    public static final int icPerceptual = 0;    public static final int icPerceptual = 0;
146    public static final int icRelativeColorimetric = 1;    public static final int icRelativeColorimetric = 1;
147    public static final int icSaturation = 2;    public static final int icSaturation = 2;
148    public static final int icAbsoluteColorimetric = 3;    public static final int icAbsoluteColorimetric = 3;
149    
150    public static final int icSigHead = 1751474532;    /**
151    public static final int icSigAToB0Tag = 1093812784;     * Tag signatures
152    public static final int icSigAToB1Tag = 1093812785;     */
153    public static final int icSigAToB2Tag = 1093812786;    public static final int icSigAToB0Tag = 0x41324230; // 'A2B0'
154    public static final int icSigBlueColorantTag = 1649957210;    public static final int icSigAToB1Tag = 0x41324231; // 'A2B1'
155    public static final int icSigBlueTRCTag = 1649693251;    public static final int icSigAToB2Tag = 0x41324232; // 'A2B2'
156    public static final int icSigBToA0Tag = 1110589744;    public static final int icSigBlueColorantTag = 0x6258595A; // 'bXYZ'
157    public static final int icSigBToA1Tag = 1110589745;    public static final int icSigBlueTRCTag = 0x62545243; // 'bTRC'
158    public static final int icSigBToA2Tag = 1110589746;    public static final int icSigBToA0Tag = 0x42324130; // 'B2A0'
159    public static final int icSigCalibrationDateTimeTag = 1667329140;    public static final int icSigBToA1Tag = 0x42324131; // 'B2A1'
160    public static final int icSigCharTargetTag = 1952543335;    public static final int icSigBToA2Tag = 0x42324132; // 'B2A2'
161    public static final int icSigCopyrightTag = 1668313716;    public static final int icSigCalibrationDateTimeTag = 0x63616C74; // 'calt'
162    public static final int icSigCrdInfoTag = 1668441193;    public static final int icSigCharTargetTag = 0x74617267; // 'targ'
163    public static final int icSigDeviceMfgDescTag = 1684893284;    public static final int icSigCopyrightTag = 0x63707274; // 'cprt'
164    public static final int icSigDeviceModelDescTag = 1684890724;    public static final int icSigCrdInfoTag = 0x63726469; // 'crdi'
165    public static final int icSigDeviceSettingsTag = 1684371059;    public static final int icSigDeviceMfgDescTag = 0x646D6E64; // 'dmnd'
166    public static final int icSigGamutTag = 1734438260;    public static final int icSigDeviceModelDescTag = 0x646D6464; // 'dmdd'
167    public static final int icSigGrayTRCTag = 1800688195;    public static final int icSigDeviceSettingsTag = 0x64657673; // 'devs'
168    public static final int icSigGreenColorantTag = 1733843290;    public static final int icSigGamutTag = 0x67616D74; // 'gamt'
169    public static final int icSigGreenTRCTag = 1733579331;    public static final int icSigGrayTRCTag = 0x6b545243; // 'kTRC'
170    public static final int icSigLuminanceTag = 1819635049;    public static final int icSigGreenColorantTag = 0x6758595A; // 'gXYZ'
171    public static final int icSigMeasurementTag = 1835360627;    public static final int icSigGreenTRCTag = 0x67545243; // 'gTRC'
172    public static final int icSigMediaBlackPointTag = 1651208308;    public static final int icSigLuminanceTag = 0x6C756d69; // 'lumi'
173    public static final int icSigMediaWhitePointTag = 2004119668;    public static final int icSigMeasurementTag = 0x6D656173; // 'meas'
174    public static final int icSigNamedColor2Tag = 1852009522;    public static final int icSigMediaBlackPointTag = 0x626B7074; // 'bkpt'
175    public static final int icSigOutputResponseTag = 1919251312;    public static final int icSigMediaWhitePointTag = 0x77747074; // 'wtpt'
176    public static final int icSigPreview0Tag = 1886545200;    public static final int icSigNamedColorTag = 0x6E636f6C; // ''ncol'  
177    public static final int icSigPreview1Tag = 1886545201;    public static final int icSigNamedColor2Tag = 0x6E636C32; // 'ncl2'
178    public static final int icSigPreview2Tag = 1886545202;    public static final int icSigOutputResponseTag = 0x72657370; // 'resp'
179    public static final int icSigProfileDescriptionTag = 1684370275;    public static final int icSigPreview0Tag = 0x70726530; // 'pre0'
180    public static final int icSigProfileSequenceDescTag = 1886610801;    public static final int icSigPreview1Tag = 0x70726531; // 'pre1'
181    public static final int icSigPs2CRD0Tag = 1886610480;    public static final int icSigPreview2Tag = 0x70726532; // 'pre2'
182    public static final int icSigPs2CRD1Tag = 1886610481;    public static final int icSigProfileDescriptionTag = 0x64657363; // 'desc'
183    public static final int icSigPs2CRD2Tag = 1886610482;    public static final int icSigProfileSequenceDescTag = 0x70736571; // 'pseq'
184    public static final int icSigPs2CRD3Tag = 1886610483;    public static final int icSigPs2CRD0Tag = 0x70736430; // 'psd0'
185    public static final int icSigPs2CSATag = 1886597747;    public static final int icSigPs2CRD1Tag = 0x70736431; // 'psd1'
186    public static final int icSigPs2RenderingIntentTag = 1886597737;    public static final int icSigPs2CRD2Tag = 0x70736432; // 'psd2'
187    public static final int icSigRedColorantTag = 1918392666;    public static final int icSigPs2CRD3Tag = 0x70736433; // 'psd3'
188    public static final int icSigRedTRCTag = 1918128707;    public static final int icSigPs2CSATag = 0x70733273; // 'ps2s'
189    public static final int icSigScreeningDescTag = 1935897188;    public static final int icSigPs2RenderingIntentTag = 0x70733269; // 'ps2i'
190    public static final int icSigScreeningTag = 1935897198;    public static final int icSigRedColorantTag = 0x7258595A; // 'rXYZ'
191    public static final int icSigTechnologyTag = 1952801640;    public static final int icSigRedTRCTag = 0x72545243; // 'rTRC'
192    public static final int icSigUcrBgTag = 1650877472;    public static final int icSigScreeningDescTag = 0x73637264; // 'scrd'
193    public static final int icSigViewingCondDescTag = 1987405156;    public static final int icSigScreeningTag = 0x7363726E; // 'scrn'
194    public static final int icSigViewingConditionsTag = 1986618743;    public static final int icSigTechnologyTag = 0x74656368; // 'tech'
195    public static final int icSigChromaticityTag = 1667789421;    public static final int icSigUcrBgTag = 0x62666420; // 'bfd '
196      public static final int icSigViewingCondDescTag = 0x76756564; // 'vued'
197      public static final int icSigViewingConditionsTag = 0x76696577; // 'view'
198      public static final int icSigChromaticityTag = 0x6368726D; // 'chrm'
199    
200      /**
201       * Non-ICC tag 'head' for use in retrieving the header with getData()
202       */
203      public static final int icSigHead = 0x68656164;
204    
205      /**
206       * Header offsets
207       */
208    public static final int icHdrSize = 0;    public static final int icHdrSize = 0;
209    public static final int icHdrCmmId = 4;    public static final int icHdrCmmId = 4;
210    public static final int icHdrVersion = 8;    public static final int icHdrVersion = 8;
# Line 171  public class ICC_Profile implements Seri Line 222  public class ICC_Profile implements Seri
222    public static final int icHdrIlluminant = 68;    public static final int icHdrIlluminant = 68;
223    public static final int icHdrCreator = 80;    public static final int icHdrCreator = 80;
224    
225      /**
226       *
227       */
228    public static final int icTagType = 0;    public static final int icTagType = 0;
229    public static final int icTagReserved = 4;    public static final int icTagReserved = 4;
230    public static final int icCurveCount = 8;    public static final int icCurveCount = 8;
231    public static final int icCurveData = 12;    public static final int icCurveData = 12;
   
232    public static final int icXYZNumberX = 8;    public static final int icXYZNumberX = 8;
233    
234    /**    /**
235       * offset of the Tag table
236       */
237      private static final int tagTableOffset = 128;
238    
239      /**
240     * @serial     * @serial
241     */     */
242    final int iccProfileSerializedDataVersion = 1;    private final int iccProfileSerializedDataVersion = 1;
243    
244      /**
245       * Constants related to generating profiles for
246       * built-in colorspace profiles
247       */
248      /**
249       * Copyright notice to stick into built-in-profile files.
250       */
251      private static final String copyrightNotice = "Generated by GNU Classpath.";
252    
253      /**
254       * Resolution of the TRC to use for predefined profiles.
255       * 1024 should suffice.
256       */
257      private static final int TRC_POINTS = 1024;
258    
259      /**
260       * CIE 1931 D50 white point (in Lab coordinates)
261       */
262      private static final float[] D50 = { 0.96422f, 1.00f, 0.82521f };
263    
264    transient int profileID;    /**
265       * Color space profile ID
266       * Set to the predefined profile class (e.g. CS_sRGB) if a predefined
267       * color space is used, set to -1 otherwise.
268       * (or if the profile has been modified)
269       */
270      private transient int profileID;
271    
272      /**
273       * The profile header data
274       */
275      private transient ProfileHeader header;
276    
277      /**
278       * A hashtable containing the profile tags as TagEntry objects
279       */
280      private transient Hashtable tagTable;
281    
282      /**
283       * Contructor for predefined colorspaces
284       */
285    ICC_Profile(int profileID)    ICC_Profile(int profileID)
286    {    {
287      this.profileID = profileID;      header = null;
288        tagTable = null;
289        createProfile(profileID);
290      }
291    
292      /**
293       * Constructs an ICC_Profile from a header and a table of loaded tags.
294       */
295      ICC_Profile(ProfileHeader h, Hashtable tags) throws IllegalArgumentException
296      {
297        header = h;
298        tagTable = tags;
299        profileID = -1; // Not a predefined color space
300    }    }
301    
302      /**
303       * Constructs an ICC_Profile from a byte array of data.
304       */
305      ICC_Profile(byte[] data) throws IllegalArgumentException
306      {
307        // get header and verify it
308        header = new ProfileHeader(data);
309        header.verifyHeader(data.length);
310        tagTable = createTagTable(data);
311        profileID = -1; // Not a predefined color space
312      }
313    
314      /**
315       * Free up the used memory.
316       */
317    protected void finalize()    protected void finalize()
318    {    {
319      // XXX What resources should we free?      header = null;
320        tagTable = null;
321    }    }
322    
323      /**
324       * Returns an ICC_Profile instance from a byte array of profile data.
325       *
326       * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
327       * may be returned if appropriate.
328       *
329       * @throws IllegalArgumentException if the profile data is an invalid
330       * v2 profile.
331       *
332       * @param data - the profile data
333       * @return An ICC_Profile object
334       */
335    public static ICC_Profile getInstance(byte[] data)    public static ICC_Profile getInstance(byte[] data)
336    {    {
337      throw new Error("not implemented");      ProfileHeader header = new ProfileHeader(data);
338    
339        // verify it as a correct ICC header, including size
340        header.verifyHeader(data.length);
341    
342        Hashtable tags = createTagTable(data);
343    
344        if (isRGBProfile(header, tags))
345          return new ICC_ProfileRGB(data);
346        if (isGrayProfile(header, tags))
347          return new ICC_ProfileGray(data);
348    
349        return new ICC_Profile(header, tags);
350    }    }
351    
352      /**
353       * Returns an predefined ICC_Profile instance.
354       *
355       * This will construct an ICC_Profile instance from one of the predefined
356       * color spaces in the ColorSpace class. (e.g. CS_sRGB, CS_GRAY, etc)
357       *
358       * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
359       * may be returned if appropriate.
360       *
361       * @return An ICC_Profile object
362       */
363    public static ICC_Profile getInstance(int cspace)    public static ICC_Profile getInstance(int cspace)
364    {    {
365        if (cspace == ColorSpace.CS_sRGB || cspace == ColorSpace.CS_LINEAR_RGB)
366          return new ICC_ProfileRGB(cspace);
367        if (cspace == ColorSpace.CS_GRAY)
368          return new ICC_ProfileGray(cspace);
369      return new ICC_Profile(cspace);      return new ICC_Profile(cspace);
370    }    }
371    
372    public static ICC_Profile getInstance(String filename) throws IOException    /**
373       * Returns an ICC_Profile instance from an ICC Profile file.
374       *
375       * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
376       * may be returned if appropriate.
377       *
378       * @throws IllegalArgumentException if the profile data is an invalid
379       * v2 profile.
380       * @throws IOException if the file could not be read.
381       *
382       * @param filename - the file name of the profile file.
383       * @return An ICC_Profile object
384       */
385      public static ICC_Profile getInstance(String filename)
386                                     throws IOException
387    {    {
388      return getInstance(new FileInputStream(filename));      return getInstance(new FileInputStream(filename));
389    }    }
390    
391    public static ICC_Profile getInstance(InputStream in) throws IOException    /**
392       * Returns an ICC_Profile instance from an InputStream.
393       *
394       * This method can be used for reading ICC profiles embedded in files
395       * which support this. (JPEG and SVG for instance).
396       *
397       * The stream is treated in the following way: The profile header
398       * (128 bytes) is read first, and the header is validated. If the profile
399       * header is valid, it will then attempt to read the rest of the profile
400       * from the stream. The stream is not closed after reading.
401       *
402       * An instance of the specialized classes ICC_ProfileRGB or ICC_ProfileGray
403       * may be returned if appropriate.
404       *
405       * @throws IllegalArgumentException if the profile data is an invalid
406       * v2 profile.
407       * @throws IOException if the stream could not be read.
408       *
409       * @param in - the input stream to read the profile from.
410       * @return An ICC_Profile object
411       */
412      public static ICC_Profile getInstance(InputStream in)
413                                     throws IOException
414    {    {
415      throw new Error("not implemented");      // read the header
416        byte[] headerData = new byte[ProfileHeader.HEADERSIZE];
417        if (in.read(headerData) != ProfileHeader.HEADERSIZE)
418          throw new IllegalArgumentException("Invalid profile header");
419    
420        ProfileHeader header = new ProfileHeader(headerData);
421    
422        // verify it as a correct ICC header, but do not verify the
423        // size as we are reading from a stream.
424        header.verifyHeader(-1);
425    
426        // get the size
427        byte[] data = new byte[header.getSize()];
428        System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE);
429    
430        // read the rest
431        if (in.read(data, ProfileHeader.HEADERSIZE,
432                    header.getSize() - ProfileHeader.HEADERSIZE) != header.getSize()
433            - ProfileHeader.HEADERSIZE)
434          throw new IOException("Incorrect profile size");
435    
436        return getInstance(data);
437    }    }
438    
439      /**
440       * Returns the major version number
441       */
442    public int getMajorVersion()    public int getMajorVersion()
443    {    {
444      throw new Error("not implemented");      return header.getMajorVersion();
445    }    }
446    
447      /**
448       * Returns the minor version number.
449       *
450       * Only the least-significant byte contains data, in BCD form:
451       * the least-significant nibble is the BCD bug fix revision,
452       * the most-significant nibble is the BCD minor revision number.
453       *
454       * (E.g. For a v2.1.0 profile this will return <code>0x10</code>)
455       */
456    public int getMinorVersion()    public int getMinorVersion()
457    {    {
458      throw new Error("not implemented");      return header.getMinorVersion();
459    }    }
460    
461      /**
462       * Returns the device class of this profile,
463       *
464       * (E.g. CLASS_INPUT for a scanner profile,
465       * CLASS_OUTPUT for a printer)
466       */
467    public int getProfileClass()    public int getProfileClass()
468    {    {
469      throw new Error("not implemented");      return header.getProfileClass();
470    }    }
471    
472      /**
473       * Returns the color space of this profile, in terms
474       * of the color space constants defined in ColorSpace.
475       * (For example, it may be a ColorSpace.TYPE_RGB)
476       */
477    public int getColorSpaceType()    public int getColorSpaceType()
478    {    {
479      throw new Error("not implemented");      return header.getColorSpace();
480    }    }
481    
482      /**
483       * Returns the color space of this profile's Profile Connection Space (OCS)
484       *
485       * In terms of the color space constants defined in ColorSpace.
486       * This may be TYPE_XYZ or TYPE_Lab
487       */
488    public int getPCSType()    public int getPCSType()
489    {    {
490      throw new Error("not implemented");      return header.getProfileColorSpace();
491    }    }
492    
493      /**
494       * Writes the profile data to an ICC profile file.
495       * @param filename - The name of the file to write
496       * @throws IOException if the write failed.
497       */
498    public void write(String filename) throws IOException    public void write(String filename) throws IOException
499    {    {
500      write(new FileOutputStream(filename));      FileOutputStream out = new FileOutputStream(filename);
501        write(out);
502        out.flush();
503        out.close();
504    }    }
505    
506      /**
507       * Writes the profile data in ICC profile file-format to a stream.
508       * This is useful for embedding ICC profiles in file formats which
509       * support this (such as JPEG and SVG).
510       *
511       * The stream is not closed after writing.
512       * @param out - The outputstream to which the profile data should be written
513       * @throws IOException if the write failed.
514       */
515    public void write(OutputStream out) throws IOException    public void write(OutputStream out) throws IOException
516    {    {
517      throw new Error("not implemented");      out.write(getData());
518    }    }
519    
520      /**
521       * Returns the data corresponding to this ICC_Profile as a byte array.
522       *
523       * @return The data in a byte array,
524       * where the first element corresponds to first byte of the profile file.
525       */
526    public byte[] getData()    public byte[] getData()
527    {    {
528      throw new Error("not implemented");      int size = getSize();
529        byte[] data = new byte[size];
530    
531        // Header
532        System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
533        // # of tags
534        byte[] tt = getTagTable();
535        System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
536    
537        Enumeration e = tagTable.elements();
538        while (e.hasMoreElements())
539          {
540            TagEntry tag = (TagEntry) e.nextElement();
541            System.arraycopy(tag.getData(), 0,
542                             data, tag.getOffset(), tag.getSize());
543          }
544        return data;
545    }    }
546    
547      /**
548       * Returns the ICC profile tag data
549       * The non ICC-tag icSigHead is also permitted to request the header data.
550       *
551       * @param tagSignature The ICC signature of the requested tag
552       * @return A byte array containing the tag data
553       */
554    public byte[] getData(int tagSignature)    public byte[] getData(int tagSignature)
555    {    {
556      throw new Error("not implemented");      if (tagSignature == icSigHead)
557          return header.getData(getSize());
558    
559        TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
560        if (t == null)
561          return null;
562        return t.getData();
563    }    }
564    
565      /**
566       * Sets the ICC profile tag data.
567       *
568       * Note that an ICC profile can only contain one tag of each type, if
569       * a tag already exists with the given signature, it is replaced.
570       *
571       * @param tagSignature - The signature of the tag to set
572       * @param data - A byte array containing the tag data
573       */
574    public void setData(int tagSignature, byte[] data)    public void setData(int tagSignature, byte[] data)
575    {    {
576      throw new Error("not implemented");      profileID = -1; // Not a predefined color space if modified.
577    
578        if (tagSignature == icSigHead)
579          header = new ProfileHeader(data);
580        else
581          {
582            TagEntry t = new TagEntry(tagSignature, data);
583            tagTable.put(t.hashKey(), t);
584          }
585    }    }
586    
587      /**
588       * Get the number of components in the profile's device color space.
589       */
590    public int getNumComponents()    public int getNumComponents()
591    {    {
592      switch (profileID)      int[] lookup =
593                       {
594                         ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
595                         ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
596                         ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
597                         ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
598                         ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
599                         ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
600                         ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
601                         ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
602                         ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
603                         ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
604                         ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
605                         ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
606                         ColorSpace.TYPE_FCLR, 15
607                       };
608        for (int i = 0; i < lookup.length; i += 2)
609          if (header.getColorSpace() == lookup[i])
610            return lookup[i + 1];
611        return 3; // should never happen.
612      }
613    
614      /**
615       * After deserializing we must determine if the class we want
616       * is really one of the more specialized ICC_ProfileRGB or
617       * ICC_ProfileGray classes.
618       */
619      protected Object readResolve() throws ObjectStreamException
620      {
621        if (isRGBProfile(header, tagTable))
622          return new ICC_ProfileRGB(getData());
623        if (isGrayProfile(header, tagTable))
624          return new ICC_ProfileGray(getData());
625        return this;
626      }
627    
628      /**
629       * Deserializes an instance
630       */
631      private void readObject(ObjectInputStream s)
632                       throws IOException, ClassNotFoundException
633      {
634        s.defaultReadObject();
635        String predef = (String) s.readObject();
636        byte[] data = (byte[]) s.readObject();
637    
638        if (data != null)
639          {
640            header = new ProfileHeader(data);
641            tagTable = createTagTable(data);
642            profileID = -1; // Not a predefined color space
643          }
644    
645        if (predef != null)
646          {
647            predef = predef.intern();
648            if (predef.equals("CS_sRGB"))
649              createProfile(ColorSpace.CS_sRGB);
650            if (predef.equals("CS_LINEAR_RGB"))
651              createProfile(ColorSpace.CS_LINEAR_RGB);
652            if (predef.equals("CS_CIEXYZ"))
653              createProfile(ColorSpace.CS_CIEXYZ);
654            if (predef.equals("CS_GRAY"))
655              createProfile(ColorSpace.CS_GRAY);
656            if (predef.equals("CS_PYCC"))
657              createProfile(ColorSpace.CS_PYCC);
658          }
659      }
660    
661      /**
662       * Serializes an instance
663       * The format is a String and a byte array,
664       * The string is non-null if the instance is one of the built-in profiles.
665       * Otherwise the byte array is non-null and represents the profile data.
666       */
667      private void writeObject(ObjectOutputStream s) throws IOException
668      {
669        s.defaultWriteObject();
670        if (profileID == ColorSpace.CS_sRGB)
671          s.writeObject("CS_sRGB");
672        else if (profileID == ColorSpace.CS_LINEAR_RGB)
673          s.writeObject("CS_LINEAR_RGB");
674        else if (profileID == ColorSpace.CS_CIEXYZ)
675          s.writeObject("CS_CIEXYZ");
676        else if (profileID == ColorSpace.CS_GRAY)
677          s.writeObject("CS_GRAY");
678        else if (profileID == ColorSpace.CS_PYCC)
679          s.writeObject("CS_PYCC");
680        else
681          {
682            s.writeObject(null); // null string
683            s.writeObject(getData()); // data
684            return;
685          }
686        s.writeObject(null); // null data
687      }
688    
689      /**
690       * Sorts a ICC profile byte array into TagEntry objects stored in
691       * a hash table.
692       */
693      private static Hashtable createTagTable(byte[] data)
694                                       throws IllegalArgumentException
695      {
696        ByteBuffer buf = ByteBuffer.wrap(data);
697        int nTags = buf.getInt(tagTableOffset);
698    
699        Hashtable tagTable = new Hashtable();
700        for (int i = 0; i < nTags; i++)
701          {
702            TagEntry te = new TagEntry(buf.getInt(tagTableOffset
703                                                  + i * TagEntry.entrySize + 4),
704                                       buf.getInt(tagTableOffset
705                                                  + i * TagEntry.entrySize + 8),
706                                       buf.getInt(tagTableOffset
707                                                  + i * TagEntry.entrySize + 12),
708                                       data);
709    
710            if (tagTable.put(te.hashKey(), te) != null)
711              throw new IllegalArgumentException("Duplicate tag in profile:" + te);
712          }
713        return tagTable;
714      }
715    
716      /**
717       * Returns the total size of the padded, stored data
718       * Note: Tags must be stored on 4-byte aligned offsets.
719       */
720      private int getSize()
721      {
722        int totalSize = ProfileHeader.HEADERSIZE; // size of header
723    
724        int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table  
725        if ((tagTableSize & 0x0003) != 0)
726          tagTableSize += 4 - (tagTableSize & 0x0003); // pad
727        totalSize += tagTableSize;
728    
729        Enumeration e = tagTable.elements();
730        while (e.hasMoreElements())
731          { // tag data
732            int tagSize = ((TagEntry) e.nextElement()).getSize();
733            if ((tagSize & 0x0003) != 0)
734              tagSize += 4 - (tagSize & 0x0003); // pad
735            totalSize += tagSize;
736          }
737        return totalSize;
738      }
739    
740      /**
741       * Generates the tag index table
742       */
743      private byte[] getTagTable()
744      {
745        int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
746        if ((tagTableSize & 0x0003) != 0)
747          tagTableSize += 4 - (tagTableSize & 0x0003); // pad
748    
749        int offset = 4;
750        int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
751        ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
752        buf.putInt(tagTable.size()); // number of tags
753    
754        Enumeration e = tagTable.elements();
755        while (e.hasMoreElements())
756          {
757            TagEntry tag = (TagEntry) e.nextElement();
758            buf.putInt(offset, tag.getSignature());
759            buf.putInt(offset + 4, tagOffset);
760            buf.putInt(offset + 8, tag.getSize());
761            tag.setOffset(tagOffset);
762            int tagSize = tag.getSize();
763            if ((tagSize & 0x0003) != 0)
764              tagSize += 4 - (tagSize & 0x0003); // pad        
765            tagOffset += tagSize;
766            offset += 12;
767          }
768        return buf.array();
769      }
770    
771      /**
772       * Returns if the criteria for an ICC_ProfileRGB are met.
773       * This means:
774       * Color space is TYPE_RGB
775       * (r,g,b)ColorantTags included
776       * (r,g,b)TRCTags included
777       * mediaWhitePointTag included
778       */
779      private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
780      {
781        if (header.getColorSpace() != ColorSpace.TYPE_RGB)
782          return false;
783        if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
784          return false;
785        if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
786          return false;
787        if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
788          return false;
789        if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
790          return false;
791        if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
792          return false;
793        if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
794          return false;
795        return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
796      }
797    
798      /**
799       * Returns if the criteria for an ICC_ProfileGray are met.
800       * This means:
801       * Colorspace is TYPE_GRAY
802       * grayTRCTag included
803       * mediaWhitePointTag included
804       */
805      private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
806      {
807        if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
808          return false;
809        if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
810          return false;
811        return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
812      }
813    
814      /**
815       * Returns curve data for a 'curv'-type tag
816       * If it's a gamma curve, a single entry will be returned with the
817       * gamma value (including 1.0 for linear response)
818       * Otherwise the TRC table is returned.
819       *
820       * (Package private - used by ICC_ProfileRGB and ICC_ProfileGray)
821       */
822      short[] getCurve(int signature)
823      {
824        byte[] data = getData(signature);
825        short[] curve;
826    
827        // can't find tag?
828        if (data == null)
829          return null;
830    
831        // not an curve type tag?
832        ByteBuffer buf = ByteBuffer.wrap(data);
833        if (buf.getInt(0) != 0x63757276) // 'curv' type
834          return null;
835        int count = buf.getInt(8);
836        if (count == 0)
837          {
838            curve = new short[1];
839            curve[0] = 0x0100; // 1.00 in u8fixed8
840            return curve;
841          }
842        if (count == 1)
843          {
844            curve = new short[1];
845            curve[0] = buf.getShort(12); // other u8fixed8 gamma
846            return curve;
847          }
848        curve = new short[count];
849        for (int i = 0; i < count; i++)
850          curve[i] = buf.getShort(12 + i * 2);
851        return curve;
852      }
853    
854      /**
855       * Returns XYZ tristimulus values for an 'XYZ ' type tag
856       * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag.
857       *
858       * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray)
859       */
860      float[] getXYZData(int signature)
861      {
862        byte[] data = getData(signature);
863    
864        // can't find tag?
865        if (data == null)
866          return null;
867    
868        // not an XYZData type tag?
869        ByteBuffer buf = ByteBuffer.wrap(data);
870        if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type
871          return null;
872    
873        float[] point = new float[3];
874    
875        // get the X,Y,Z tristimulus values
876        point[0] = ((float) buf.getInt(8)) / 65536f;
877        point[1] = ((float) buf.getInt(12)) / 65536f;
878        point[2] = ((float) buf.getInt(16)) / 65536f;
879        return point;
880      }
881    
882      /**
883       * Returns the profile ID if it's a predefined profile
884       * Or -1 for a profile loaded from an ICC profile
885       *
886       * (Package private - used by ICC_ColorSpace)
887       */
888      int isPredefined()
889      {
890        return profileID;
891      }
892    
893      /**
894       * Creates a tag of XYZ-value type.
895       */
896      private byte[] makeXYZData(float[] values)
897      {
898        ByteBuffer buf = ByteBuffer.allocate(20);
899        buf.putInt(0, icSigXYZData); // 'XYZ '
900        buf.putInt(4, 0);
901        buf.putInt(8, (int) (values[0] * 65536.0));
902        buf.putInt(12, (int) (values[1] * 65536.0));
903        buf.putInt(16, (int) (values[2] * 65536.0));
904        return buf.array();
905      }
906    
907      /**
908       * Creates a tag of text type
909       */
910      private byte[] makeTextTag(String text)
911      {
912        int length = text.length();
913        ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
914        byte[] data;
915        try
916          {
917            data = text.getBytes("US-ASCII");
918          }
919        catch (UnsupportedEncodingException e)
920          {
921            data = new byte[length]; // shouldn't happen
922          }
923    
924        buf.putInt(0, (int) 0x74657874); // 'text'
925        buf.putInt(4, 0);
926        for (int i = 0; i < length; i++)
927          buf.put(8 + i, data[i]);
928        buf.put(8 + length, (byte) 0); // null-terminate
929        return buf.array();
930      }
931    
932      /**
933       * Creates a tag of textDescriptionType
934       */
935      private byte[] makeDescTag(String text)
936      {
937        int length = text.length();
938        ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
939        buf.putInt(0, (int) 0x64657363); // 'desc'
940        buf.putInt(4, 0); // reserved
941        buf.putInt(8, length + 1); // ASCII length, including null termination
942        byte[] data;
943    
944        try
945          {
946            data = text.getBytes("US-ASCII");
947          }
948        catch (UnsupportedEncodingException e)
949          {
950            data = new byte[length]; // shouldn't happen
951          }
952    
953        for (int i = 0; i < length; i++)
954          buf.put(12 + i, data[i]);
955        buf.put(12 + length, (byte) 0); // null-terminate
956    
957        for (int i = 0; i < 39; i++)
958          buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore
959    
960        return buf.array();
961      }
962    
963      /**
964       * Creates a tag of TRC type (linear curve)
965       */
966      private byte[] makeTRC()
967      {
968        ByteBuffer buf = ByteBuffer.allocate(12);
969        buf.putInt(0, 0x63757276); // 'curv' type
970        buf.putInt(4, 0); // reserved
971        buf.putInt(8, 0);
972        return buf.array();
973      }
974    
975      /**
976       * Creates a tag of TRC type (single gamma value)
977       */
978      private byte[] makeTRC(float gamma)
979      {
980        short gammaValue = (short) (gamma * 256f);
981        ByteBuffer buf = ByteBuffer.allocate(14);
982        buf.putInt(0, 0x63757276); // 'curv' type
983        buf.putInt(4, 0); // reserved
984        buf.putInt(8, 1);
985        buf.putShort(12, gammaValue); // 1.00 in u8fixed8
986        return buf.array();
987      }
988    
989      /**
990       * Creates a tag of TRC type (TRC curve points)
991       */
992      private byte[] makeTRC(float[] trc)
993      {
994        ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
995        buf.putInt(0, 0x63757276); // 'curv' type
996        buf.putInt(4, 0); // reserved
997        buf.putInt(8, trc.length); // number of points
998    
999        // put the curve values
1000        for (int i = 0; i < trc.length; i++)
1001          buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
1002    
1003        return buf.array();
1004      }
1005    
1006      /**
1007       * Creates an identity color lookup table.
1008       */
1009      private byte[] makeIdentityClut()
1010      {
1011        final int nIn = 3;
1012        final int nOut = 3;
1013        final int nInEntries = 256;
1014        final int nOutEntries = 256;
1015        final int gridpoints = 16;
1016    
1017        // gridpoints**nIn
1018        final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
1019        final int totalSize = clutSize + 2 * nInEntries * nIn
1020                              + 2 * nOutEntries * nOut + 52;
1021    
1022        ByteBuffer buf = ByteBuffer.allocate(totalSize);
1023        buf.putInt(0, 0x6D667432); // 'mft2'
1024        buf.putInt(4, 0); // reserved
1025        buf.put(8, (byte) nIn); // number input channels
1026        buf.put(9, (byte) nOut); // number output channels
1027        buf.put(10, (byte) gridpoints); // number gridpoints
1028        buf.put(11, (byte) 0); // padding
1029    
1030        // identity matrix
1031        buf.putInt(12, 65536); // = 1 in s15.16 fixed point
1032        buf.putInt(16, 0);
1033        buf.putInt(20, 0);
1034        buf.putInt(24, 0);
1035        buf.putInt(28, 65536);
1036        buf.putInt(32, 0);
1037        buf.putInt(36, 0);
1038        buf.putInt(40, 0);
1039        buf.putInt(44, 65536);
1040    
1041        buf.putShort(48, (short) nInEntries); // input table entries
1042        buf.putShort(50, (short) nOutEntries); // output table entries
1043    
1044        // write the linear input channels, unsigned 16.16 fixed point,
1045        // from 0.0 to FF.FF
1046        for (int channel = 0; channel < 3; channel++)
1047          for (int i = 0; i < nInEntries; i++)
1048            {
1049              short n = (short) ((i << 8) | i); // assumes 256 entries
1050              buf.putShort(52 + (channel * nInEntries + i) * 2, n);
1051            }
1052        int clutOffset = 52 + nInEntries * nIn * 2;
1053    
1054        for (int x = 0; x < gridpoints; x++)
1055          for (int y = 0; y < gridpoints; y++)
1056            for (int z = 0; z < gridpoints; z++)
1057              {
1058                int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
1059                             + x * gridpoints * gridpoints * 2 * nOut;
1060                double xf = ((double) x) / ((double) gridpoints - 1.0);
1061                double yf = ((double) y) / ((double) gridpoints - 1.0);
1062                double zf = ((double) z) / ((double) gridpoints - 1.0);
1063                buf.putShort(offset, (short) (xf * 65535.0));
1064                buf.putShort(offset + 2, (short) (yf * 65535.0));
1065                buf.putShort(offset + 4, (short) (zf * 65535.0));
1066              }
1067    
1068        for (int channel = 0; channel < 3; channel++)
1069          for (int i = 0; i < nOutEntries; i++)
1070            {
1071              short n = (short) ((i << 8) | i); // assumes 256 entries
1072              buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
1073                           n);
1074            }
1075    
1076        return buf.array();
1077      }
1078    
1079      /**
1080       * Creates profile data corresponding to the built-in colorspaces.
1081       */
1082      private void createProfile(int colorSpace) throws IllegalArgumentException
1083      {
1084        this.profileID = colorSpace;
1085        header = new ProfileHeader();
1086        tagTable = new Hashtable();
1087    
1088        switch (colorSpace)
1089        {        {
1090        case ColorSpace.CS_sRGB:        case ColorSpace.CS_sRGB:
1091            createRGBProfile();
1092            return;
1093        case ColorSpace.CS_LINEAR_RGB:        case ColorSpace.CS_LINEAR_RGB:
1094            createLinearRGBProfile();
1095            return;
1096        case ColorSpace.CS_CIEXYZ:        case ColorSpace.CS_CIEXYZ:
1097          return 3;          createCIEProfile();
1098            return;
1099        case ColorSpace.CS_GRAY:        case ColorSpace.CS_GRAY:
1100          return 1;          createGrayProfile();
1101        case ColorSpace.CS_PYCC: // have no clue about this one          return;
1102          case ColorSpace.CS_PYCC:
1103            createPyccProfile();
1104            return;
1105        default:        default:
1106          throw new UnsupportedOperationException("profile not implemented");          throw new IllegalArgumentException("Not a predefined color space!");
1107        }        }
1108    }    }
1109    
1110    protected Object readResolve() throws ObjectStreamException    /**
1111       * Creates an ICC_Profile representing the sRGB color space
1112       */
1113      private void createRGBProfile()
1114    {    {
1115      throw new Error("not implemented");      header.setColorSpace( ColorSpace.TYPE_RGB );
1116        header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1117        ICC_ColorSpace cs = new ICC_ColorSpace(this);
1118    
1119        float[] r = { 1f, 0f, 0f };
1120        float[] g = { 0f, 1f, 0f };
1121        float[] b = { 0f, 0f, 1f };
1122        float[] black = { 0f, 0f, 0f };
1123    
1124        // CIE 1931 D50 white point (in Lab coordinates)
1125        float[] white = D50;
1126    
1127        // Get tristimulus values (matrix elements)
1128        r = cs.toCIEXYZ(r);
1129        g = cs.toCIEXYZ(g);
1130        b = cs.toCIEXYZ(b);
1131    
1132        // Generate the sRGB TRC curve, this is the linear->nonlinear
1133        // RGB transform.
1134        cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
1135        float[] points = new float[TRC_POINTS];
1136        float[] in = new float[3];
1137        for (int i = 0; i < TRC_POINTS; i++)
1138          {
1139            in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
1140            in = cs.fromRGB(in);
1141            // Note this value is the same for all components.
1142            points[i] = in[0];
1143          }
1144    
1145        setData(icSigRedColorantTag, makeXYZData(r));
1146        setData(icSigGreenColorantTag, makeXYZData(g));
1147        setData(icSigBlueColorantTag, makeXYZData(b));
1148        setData(icSigMediaWhitePointTag, makeXYZData(white));
1149        setData(icSigMediaBlackPointTag, makeXYZData(black));
1150        setData(icSigRedTRCTag, makeTRC(points));
1151        setData(icSigGreenTRCTag, makeTRC(points));
1152        setData(icSigBlueTRCTag, makeTRC(points));
1153        setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1154        setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
1155        this.profileID = ColorSpace.CS_sRGB;
1156    }    }
1157    
1158    private void readObject(ObjectInputStream s)    /**
1159      throws IOException, ClassNotFoundException     * Creates an linear sRGB profile
1160       */
1161      private void createLinearRGBProfile()
1162    {    {
1163      throw new Error("not implemented");      header.setColorSpace(ColorSpace.TYPE_RGB);
1164        header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1165        ICC_ColorSpace cs = new ICC_ColorSpace(this);
1166    
1167        float[] r = { 1f, 0f, 0f };
1168        float[] g = { 0f, 1f, 0f };
1169        float[] b = { 0f, 0f, 1f };
1170        float[] black = { 0f, 0f, 0f };
1171    
1172        float[] white = D50;
1173    
1174        // Get tristimulus values (matrix elements)
1175        r = cs.toCIEXYZ(r);
1176        g = cs.toCIEXYZ(g);
1177        b = cs.toCIEXYZ(b);
1178    
1179        setData(icSigRedColorantTag, makeXYZData(r));
1180        setData(icSigGreenColorantTag, makeXYZData(g));
1181        setData(icSigBlueColorantTag, makeXYZData(b));
1182    
1183        setData(icSigMediaWhitePointTag, makeXYZData(white));
1184        setData(icSigMediaBlackPointTag, makeXYZData(black));
1185    
1186        setData(icSigRedTRCTag, makeTRC());
1187        setData(icSigGreenTRCTag, makeTRC());
1188        setData(icSigBlueTRCTag, makeTRC());
1189        setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1190        setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
1191        this.profileID = ColorSpace.CS_LINEAR_RGB;
1192    }    }
1193    
1194    private void writeObject(ObjectOutputStream s) throws IOException    /**
1195       * Creates an CIE XYZ identity profile
1196       */
1197      private void createCIEProfile()
1198      {
1199        header.setColorSpace( ColorSpace.TYPE_XYZ );
1200        header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1201        header.setProfileClass( CLASS_COLORSPACECONVERSION );
1202        ICC_ColorSpace cs = new ICC_ColorSpace(this);
1203    
1204        float[] white = D50;
1205    
1206        setData(icSigMediaWhitePointTag, makeXYZData(white));
1207        setData(icSigAToB0Tag, makeIdentityClut());
1208        setData(icSigBToA0Tag, makeIdentityClut());
1209        setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1210        setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
1211        this.profileID = ColorSpace.CS_CIEXYZ;
1212      }
1213    
1214      /**
1215       * Creates a linear gray ICC_Profile
1216       */
1217      private void createGrayProfile()
1218      {
1219        header.setColorSpace(ColorSpace.TYPE_GRAY);
1220        header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1221    
1222        // CIE 1931 D50 white point (in Lab coordinates)
1223        float[] white = D50;
1224    
1225        setData(icSigMediaWhitePointTag, makeXYZData(white));
1226        setData(icSigGrayTRCTag, makeTRC(1.0f));
1227        setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1228        setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
1229        this.profileID = ColorSpace.CS_GRAY;
1230      }
1231    
1232      /**
1233       * XXX Implement me
1234       */
1235      private void createPyccProfile()
1236    {    {
1237      throw new Error("not implemented");      header.setColorSpace(ColorSpace.TYPE_3CLR);
1238        header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1239    
1240        // Create CLUTs here. :-)
1241    
1242        setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1243        setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
1244        this.profileID = ColorSpace.CS_PYCC;
1245    }    }
1246  } // class ICC_Profile  } // class ICC_Profile

Legend:
Removed from v.1.5.2.1  
changed lines
  Added in v.1.5.2.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26