OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [java/] [awt/] [color/] [ICC_Profile.java] - Blame information for rev 14

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.