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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [java/] [awt/] [color/] [ICC_Profile.java] - Blame information for rev 771

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 771 jeremybenn
/* 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
    int totalBytes = header.getSize() - ProfileHeader.HEADERSIZE;
430
    int bytesLeft = totalBytes;
431
    while (bytesLeft > 0)
432
      {
433
        int read = in.read(data,
434
                           ProfileHeader.HEADERSIZE + (totalBytes - bytesLeft),
435
                           bytesLeft);
436
        bytesLeft -= read;
437
      }
438
 
439
    return getInstance(data);
440
  }
441
 
442
  /**
443
   * Returns the major version number
444
   */
445
  public int getMajorVersion()
446
  {
447
    return header.getMajorVersion();
448
  }
449
 
450
  /**
451
   * Returns the minor version number.
452
   *
453
   * Only the least-significant byte contains data, in BCD form:
454
   * the least-significant nibble is the BCD bug fix revision,
455
   * the most-significant nibble is the BCD minor revision number.
456
   *
457
   * (E.g. For a v2.1.0 profile this will return <code>0x10</code>)
458
   */
459
  public int getMinorVersion()
460
  {
461
    return header.getMinorVersion();
462
  }
463
 
464
  /**
465
   * Returns the device class of this profile,
466
   *
467
   * (E.g. CLASS_INPUT for a scanner profile,
468
   * CLASS_OUTPUT for a printer)
469
   */
470
  public int getProfileClass()
471
  {
472
    return header.getProfileClass();
473
  }
474
 
475
  /**
476
   * Returns the color space of this profile, in terms
477
   * of the color space constants defined in ColorSpace.
478
   * (For example, it may be a ColorSpace.TYPE_RGB)
479
   */
480
  public int getColorSpaceType()
481
  {
482
    return header.getColorSpace();
483
  }
484
 
485
  /**
486
   * Returns the color space of this profile's Profile Connection Space (OCS)
487
   *
488
   * In terms of the color space constants defined in ColorSpace.
489
   * This may be TYPE_XYZ or TYPE_Lab
490
   */
491
  public int getPCSType()
492
  {
493
    return header.getProfileColorSpace();
494
  }
495
 
496
  /**
497
   * Writes the profile data to an ICC profile file.
498
   * @param filename - The name of the file to write
499
   * @throws IOException if the write failed.
500
   */
501
  public void write(String filename) throws IOException
502
  {
503
    FileOutputStream out = new FileOutputStream(filename);
504
    write(out);
505
    out.flush();
506
    out.close();
507
  }
508
 
509
  /**
510
   * Writes the profile data in ICC profile file-format to a stream.
511
   * This is useful for embedding ICC profiles in file formats which
512
   * support this (such as JPEG and SVG).
513
   *
514
   * The stream is not closed after writing.
515
   * @param out - The outputstream to which the profile data should be written
516
   * @throws IOException if the write failed.
517
   */
518
  public void write(OutputStream out) throws IOException
519
  {
520
    out.write(getData());
521
  }
522
 
523
  /**
524
   * Returns the data corresponding to this ICC_Profile as a byte array.
525
   *
526
   * @return The data in a byte array,
527
   * where the first element corresponds to first byte of the profile file.
528
   */
529
  public byte[] getData()
530
  {
531
    int size = getSize();
532
    byte[] data = new byte[size];
533
 
534
    // Header
535
    System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE);
536
    // # of tags
537
    byte[] tt = getTagTable();
538
    System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length);
539
 
540
    Enumeration e = tagTable.elements();
541
    while (e.hasMoreElements())
542
      {
543
        TagEntry tag = (TagEntry) e.nextElement();
544
        System.arraycopy(tag.getData(), 0,
545
                         data, tag.getOffset(), tag.getSize());
546
      }
547
    return data;
548
  }
549
 
550
  /**
551
   * Returns the ICC profile tag data
552
   * The non ICC-tag icSigHead is also permitted to request the header data.
553
   *
554
   * @param tagSignature The ICC signature of the requested tag
555
   * @return A byte array containing the tag data
556
   */
557
  public byte[] getData(int tagSignature)
558
  {
559
    if (tagSignature == icSigHead)
560
      return header.getData(getSize());
561
 
562
    TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature));
563
    if (t == null)
564
      return null;
565
    return t.getData();
566
  }
567
 
568
  /**
569
   * Sets the ICC profile tag data.
570
   *
571
   * Note that an ICC profile can only contain one tag of each type, if
572
   * a tag already exists with the given signature, it is replaced.
573
   *
574
   * @param tagSignature - The signature of the tag to set
575
   * @param data - A byte array containing the tag data
576
   */
577
  public void setData(int tagSignature, byte[] data)
578
  {
579
    profileID = -1; // Not a predefined color space if modified.
580
 
581
    if (tagSignature == icSigHead)
582
      header = new ProfileHeader(data);
583
    else
584
      {
585
        TagEntry t = new TagEntry(tagSignature, data);
586
        tagTable.put(t.hashKey(), t);
587
      }
588
  }
589
 
590
  /**
591
   * Get the number of components in the profile's device color space.
592
   */
593
  public int getNumComponents()
594
  {
595
    int[] lookup =
596
                   {
597
                     ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3,
598
                     ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1,
599
                     ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3,
600
                     ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3,
601
                     ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3,
602
                     ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3,
603
                     ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4,
604
                     ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6,
605
                     ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8,
606
                     ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10,
607
                     ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12,
608
                     ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14,
609
                     ColorSpace.TYPE_FCLR, 15
610
                   };
611
    for (int i = 0; i < lookup.length; i += 2)
612
      if (header.getColorSpace() == lookup[i])
613
        return lookup[i + 1];
614
    return 3; // should never happen.
615
  }
616
 
617
  /**
618
   * After deserializing we must determine if the class we want
619
   * is really one of the more specialized ICC_ProfileRGB or
620
   * ICC_ProfileGray classes.
621
   */
622
  protected Object readResolve() throws ObjectStreamException
623
  {
624
    if (isRGBProfile(header, tagTable))
625
      return new ICC_ProfileRGB(getData());
626
    if (isGrayProfile(header, tagTable))
627
      return new ICC_ProfileGray(getData());
628
    return this;
629
  }
630
 
631
  /**
632
   * Deserializes an instance
633
   */
634
  private void readObject(ObjectInputStream s)
635
                   throws IOException, ClassNotFoundException
636
  {
637
    s.defaultReadObject();
638
    String predef = (String) s.readObject();
639
    byte[] data = (byte[]) s.readObject();
640
 
641
    if (data != null)
642
      {
643
        header = new ProfileHeader(data);
644
        tagTable = createTagTable(data);
645
        profileID = -1; // Not a predefined color space
646
      }
647
 
648
    if (predef != null)
649
      {
650
        predef = predef.intern();
651
        if (predef.equals("CS_sRGB"))
652
          createProfile(ColorSpace.CS_sRGB);
653
        if (predef.equals("CS_LINEAR_RGB"))
654
          createProfile(ColorSpace.CS_LINEAR_RGB);
655
        if (predef.equals("CS_CIEXYZ"))
656
          createProfile(ColorSpace.CS_CIEXYZ);
657
        if (predef.equals("CS_GRAY"))
658
          createProfile(ColorSpace.CS_GRAY);
659
        if (predef.equals("CS_PYCC"))
660
          createProfile(ColorSpace.CS_PYCC);
661
      }
662
  }
663
 
664
  /**
665
   * Serializes an instance
666
   * The format is a String and a byte array,
667
   * The string is non-null if the instance is one of the built-in profiles.
668
   * Otherwise the byte array is non-null and represents the profile data.
669
   */
670
  private void writeObject(ObjectOutputStream s) throws IOException
671
  {
672
    s.defaultWriteObject();
673
    if (profileID == ColorSpace.CS_sRGB)
674
      s.writeObject("CS_sRGB");
675
    else if (profileID == ColorSpace.CS_LINEAR_RGB)
676
      s.writeObject("CS_LINEAR_RGB");
677
    else if (profileID == ColorSpace.CS_CIEXYZ)
678
      s.writeObject("CS_CIEXYZ");
679
    else if (profileID == ColorSpace.CS_GRAY)
680
      s.writeObject("CS_GRAY");
681
    else if (profileID == ColorSpace.CS_PYCC)
682
      s.writeObject("CS_PYCC");
683
    else
684
      {
685
        s.writeObject(null); // null string
686
        s.writeObject(getData()); // data
687
        return;
688
      }
689
    s.writeObject(null); // null data
690
  }
691
 
692
  /**
693
   * Sorts a ICC profile byte array into TagEntry objects stored in
694
   * a hash table.
695
   */
696
  private static Hashtable createTagTable(byte[] data)
697
                                   throws IllegalArgumentException
698
  {
699
    ByteBuffer buf = ByteBuffer.wrap(data);
700
    int nTags = buf.getInt(tagTableOffset);
701
 
702
    Hashtable tagTable = new Hashtable();
703
    for (int i = 0; i < nTags; i++)
704
      {
705
        TagEntry te = new TagEntry(buf.getInt(tagTableOffset
706
                                              + i * TagEntry.entrySize + 4),
707
                                   buf.getInt(tagTableOffset
708
                                              + i * TagEntry.entrySize + 8),
709
                                   buf.getInt(tagTableOffset
710
                                              + i * TagEntry.entrySize + 12),
711
                                   data);
712
 
713
        if (tagTable.put(te.hashKey(), te) != null)
714
          throw new IllegalArgumentException("Duplicate tag in profile:" + te);
715
      }
716
    return tagTable;
717
  }
718
 
719
  /**
720
   * Returns the total size of the padded, stored data
721
   * Note: Tags must be stored on 4-byte aligned offsets.
722
   */
723
  private int getSize()
724
  {
725
    int totalSize = ProfileHeader.HEADERSIZE; // size of header
726
 
727
    int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table
728
    if ((tagTableSize & 0x0003) != 0)
729
      tagTableSize += 4 - (tagTableSize & 0x0003); // pad
730
    totalSize += tagTableSize;
731
 
732
    Enumeration e = tagTable.elements();
733
    while (e.hasMoreElements())
734
      { // tag data
735
        int tagSize = ((TagEntry) e.nextElement()).getSize();
736
        if ((tagSize & 0x0003) != 0)
737
          tagSize += 4 - (tagSize & 0x0003); // pad
738
        totalSize += tagSize;
739
      }
740
    return totalSize;
741
  }
742
 
743
  /**
744
   * Generates the tag index table
745
   */
746
  private byte[] getTagTable()
747
  {
748
    int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize;
749
    if ((tagTableSize & 0x0003) != 0)
750
      tagTableSize += 4 - (tagTableSize & 0x0003); // pad
751
 
752
    int offset = 4;
753
    int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize;
754
    ByteBuffer buf = ByteBuffer.allocate(tagTableSize);
755
    buf.putInt(tagTable.size()); // number of tags
756
 
757
    Enumeration e = tagTable.elements();
758
    while (e.hasMoreElements())
759
      {
760
        TagEntry tag = (TagEntry) e.nextElement();
761
        buf.putInt(offset, tag.getSignature());
762
        buf.putInt(offset + 4, tagOffset);
763
        buf.putInt(offset + 8, tag.getSize());
764
        tag.setOffset(tagOffset);
765
        int tagSize = tag.getSize();
766
        if ((tagSize & 0x0003) != 0)
767
          tagSize += 4 - (tagSize & 0x0003); // pad
768
        tagOffset += tagSize;
769
        offset += 12;
770
      }
771
    return buf.array();
772
  }
773
 
774
  /**
775
   * Returns if the criteria for an ICC_ProfileRGB are met.
776
   * This means:
777
   * Color space is TYPE_RGB
778
   * (r,g,b)ColorantTags included
779
   * (r,g,b)TRCTags included
780
   * mediaWhitePointTag included
781
   */
782
  private static boolean isRGBProfile(ProfileHeader header, Hashtable tags)
783
  {
784
    if (header.getColorSpace() != ColorSpace.TYPE_RGB)
785
      return false;
786
    if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null)
787
      return false;
788
    if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null)
789
      return false;
790
    if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null)
791
      return false;
792
    if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null)
793
      return false;
794
    if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null)
795
      return false;
796
    if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null)
797
      return false;
798
    return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
799
  }
800
 
801
  /**
802
   * Returns if the criteria for an ICC_ProfileGray are met.
803
   * This means:
804
   * Colorspace is TYPE_GRAY
805
   * grayTRCTag included
806
   * mediaWhitePointTag included
807
   */
808
  private static boolean isGrayProfile(ProfileHeader header, Hashtable tags)
809
  {
810
    if (header.getColorSpace() != ColorSpace.TYPE_GRAY)
811
      return false;
812
    if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null)
813
      return false;
814
    return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null);
815
  }
816
 
817
  /**
818
   * Returns curve data for a 'curv'-type tag
819
   * If it's a gamma curve, a single entry will be returned with the
820
   * gamma value (including 1.0 for linear response)
821
   * Otherwise the TRC table is returned.
822
   *
823
   * (Package private - used by ICC_ProfileRGB and ICC_ProfileGray)
824
   */
825
  short[] getCurve(int signature)
826
  {
827
    byte[] data = getData(signature);
828
    short[] curve;
829
 
830
    // can't find tag?
831
    if (data == null)
832
      return null;
833
 
834
    // not an curve type tag?
835
    ByteBuffer buf = ByteBuffer.wrap(data);
836
    if (buf.getInt(0) != 0x63757276) // 'curv' type
837
      return null;
838
    int count = buf.getInt(8);
839
    if (count == 0)
840
      {
841
        curve = new short[1];
842
        curve[0] = 0x0100; // 1.00 in u8fixed8
843
        return curve;
844
      }
845
    if (count == 1)
846
      {
847
        curve = new short[1];
848
        curve[0] = buf.getShort(12); // other u8fixed8 gamma
849
        return curve;
850
      }
851
    curve = new short[count];
852
    for (int i = 0; i < count; i++)
853
      curve[i] = buf.getShort(12 + i * 2);
854
    return curve;
855
  }
856
 
857
  /**
858
   * Returns XYZ tristimulus values for an 'XYZ ' type tag
859
   * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag.
860
   *
861
   * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray)
862
   */
863
  float[] getXYZData(int signature)
864
  {
865
    byte[] data = getData(signature);
866
 
867
    // can't find tag?
868
    if (data == null)
869
      return null;
870
 
871
    // not an XYZData type tag?
872
    ByteBuffer buf = ByteBuffer.wrap(data);
873
    if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type
874
      return null;
875
 
876
    float[] point = new float[3];
877
 
878
    // get the X,Y,Z tristimulus values
879
    point[0] = ((float) buf.getInt(8)) / 65536f;
880
    point[1] = ((float) buf.getInt(12)) / 65536f;
881
    point[2] = ((float) buf.getInt(16)) / 65536f;
882
    return point;
883
  }
884
 
885
  /**
886
   * Returns the profile ID if it's a predefined profile
887
   * Or -1 for a profile loaded from an ICC profile
888
   *
889
   * (Package private - used by ICC_ColorSpace)
890
   */
891
  int isPredefined()
892
  {
893
    return profileID;
894
  }
895
 
896
  /**
897
   * Creates a tag of XYZ-value type.
898
   */
899
  private byte[] makeXYZData(float[] values)
900
  {
901
    ByteBuffer buf = ByteBuffer.allocate(20);
902
    buf.putInt(0, icSigXYZData); // 'XYZ '
903
    buf.putInt(4, 0);
904
    buf.putInt(8, (int) (values[0] * 65536.0));
905
    buf.putInt(12, (int) (values[1] * 65536.0));
906
    buf.putInt(16, (int) (values[2] * 65536.0));
907
    return buf.array();
908
  }
909
 
910
  /**
911
   * Creates a tag of text type
912
   */
913
  private byte[] makeTextTag(String text)
914
  {
915
    int length = text.length();
916
    ByteBuffer buf = ByteBuffer.allocate(8 + length + 1);
917
    byte[] data;
918
    try
919
      {
920
        data = text.getBytes("US-ASCII");
921
      }
922
    catch (UnsupportedEncodingException e)
923
      {
924
        data = new byte[length]; // shouldn't happen
925
      }
926
 
927
    buf.putInt(0, (int) 0x74657874); // 'text'
928
    buf.putInt(4, 0);
929
    for (int i = 0; i < length; i++)
930
      buf.put(8 + i, data[i]);
931
    buf.put(8 + length, (byte) 0); // null-terminate
932
    return buf.array();
933
  }
934
 
935
  /**
936
   * Creates a tag of textDescriptionType
937
   */
938
  private byte[] makeDescTag(String text)
939
  {
940
    int length = text.length();
941
    ByteBuffer buf = ByteBuffer.allocate(90 + length + 1);
942
    buf.putInt(0, (int) 0x64657363); // 'desc'
943
    buf.putInt(4, 0); // reserved
944
    buf.putInt(8, length + 1); // ASCII length, including null termination
945
    byte[] data;
946
 
947
    try
948
      {
949
        data = text.getBytes("US-ASCII");
950
      }
951
    catch (UnsupportedEncodingException e)
952
      {
953
        data = new byte[length]; // shouldn't happen
954
      }
955
 
956
    for (int i = 0; i < length; i++)
957
      buf.put(12 + i, data[i]);
958
    buf.put(12 + length, (byte) 0); // null-terminate
959
 
960
    for (int i = 0; i < 39; i++)
961
      buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore
962
 
963
    return buf.array();
964
  }
965
 
966
  /**
967
   * Creates a tag of TRC type (linear curve)
968
   */
969
  private byte[] makeTRC()
970
  {
971
    ByteBuffer buf = ByteBuffer.allocate(12);
972
    buf.putInt(0, 0x63757276); // 'curv' type
973
    buf.putInt(4, 0); // reserved
974
    buf.putInt(8, 0);
975
    return buf.array();
976
  }
977
 
978
  /**
979
   * Creates a tag of TRC type (single gamma value)
980
   */
981
  private byte[] makeTRC(float gamma)
982
  {
983
    short gammaValue = (short) (gamma * 256f);
984
    ByteBuffer buf = ByteBuffer.allocate(14);
985
    buf.putInt(0, 0x63757276); // 'curv' type
986
    buf.putInt(4, 0); // reserved
987
    buf.putInt(8, 1);
988
    buf.putShort(12, gammaValue); // 1.00 in u8fixed8
989
    return buf.array();
990
  }
991
 
992
  /**
993
   * Creates a tag of TRC type (TRC curve points)
994
   */
995
  private byte[] makeTRC(float[] trc)
996
  {
997
    ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length);
998
    buf.putInt(0, 0x63757276); // 'curv' type
999
    buf.putInt(4, 0); // reserved
1000
    buf.putInt(8, trc.length); // number of points
1001
 
1002
    // put the curve values
1003
    for (int i = 0; i < trc.length; i++)
1004
      buf.putShort(12 + i * 2, (short) (trc[i] * 65535f));
1005
 
1006
    return buf.array();
1007
  }
1008
 
1009
  /**
1010
   * Creates an identity color lookup table.
1011
   */
1012
  private byte[] makeIdentityClut()
1013
  {
1014
    final int nIn = 3;
1015
    final int nOut = 3;
1016
    final int nInEntries = 256;
1017
    final int nOutEntries = 256;
1018
    final int gridpoints = 16;
1019
 
1020
    // gridpoints**nIn
1021
    final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints;
1022
    final int totalSize = clutSize + 2 * nInEntries * nIn
1023
                          + 2 * nOutEntries * nOut + 52;
1024
 
1025
    ByteBuffer buf = ByteBuffer.allocate(totalSize);
1026
    buf.putInt(0, 0x6D667432); // 'mft2'
1027
    buf.putInt(4, 0); // reserved
1028
    buf.put(8, (byte) nIn); // number input channels
1029
    buf.put(9, (byte) nOut); // number output channels
1030
    buf.put(10, (byte) gridpoints); // number gridpoints
1031
    buf.put(11, (byte) 0); // padding
1032
 
1033
    // identity matrix
1034
    buf.putInt(12, 65536); // = 1 in s15.16 fixed point
1035
    buf.putInt(16, 0);
1036
    buf.putInt(20, 0);
1037
    buf.putInt(24, 0);
1038
    buf.putInt(28, 65536);
1039
    buf.putInt(32, 0);
1040
    buf.putInt(36, 0);
1041
    buf.putInt(40, 0);
1042
    buf.putInt(44, 65536);
1043
 
1044
    buf.putShort(48, (short) nInEntries); // input table entries
1045
    buf.putShort(50, (short) nOutEntries); // output table entries
1046
 
1047
    // write the linear input channels, unsigned 16.16 fixed point,
1048
    // from 0.0 to FF.FF
1049
    for (int channel = 0; channel < 3; channel++)
1050
      for (int i = 0; i < nInEntries; i++)
1051
        {
1052
          short n = (short) ((i << 8) | i); // assumes 256 entries
1053
          buf.putShort(52 + (channel * nInEntries + i) * 2, n);
1054
        }
1055
    int clutOffset = 52 + nInEntries * nIn * 2;
1056
 
1057
    for (int x = 0; x < gridpoints; x++)
1058
      for (int y = 0; y < gridpoints; y++)
1059
        for (int z = 0; z < gridpoints; z++)
1060
          {
1061
            int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut
1062
                         + x * gridpoints * gridpoints * 2 * nOut;
1063
            double xf = ((double) x) / ((double) gridpoints - 1.0);
1064
            double yf = ((double) y) / ((double) gridpoints - 1.0);
1065
            double zf = ((double) z) / ((double) gridpoints - 1.0);
1066
            buf.putShort(offset, (short) (xf * 65535.0));
1067
            buf.putShort(offset + 2, (short) (yf * 65535.0));
1068
            buf.putShort(offset + 4, (short) (zf * 65535.0));
1069
          }
1070
 
1071
    for (int channel = 0; channel < 3; channel++)
1072
      for (int i = 0; i < nOutEntries; i++)
1073
        {
1074
          short n = (short) ((i << 8) | i); // assumes 256 entries
1075
          buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2,
1076
                       n);
1077
        }
1078
 
1079
    return buf.array();
1080
  }
1081
 
1082
  /**
1083
   * Creates profile data corresponding to the built-in colorspaces.
1084
   */
1085
  private void createProfile(int colorSpace) throws IllegalArgumentException
1086
  {
1087
    this.profileID = colorSpace;
1088
    header = new ProfileHeader();
1089
    tagTable = new Hashtable();
1090
 
1091
    switch (colorSpace)
1092
      {
1093
      case ColorSpace.CS_sRGB:
1094
        createRGBProfile();
1095
        return;
1096
      case ColorSpace.CS_LINEAR_RGB:
1097
        createLinearRGBProfile();
1098
        return;
1099
      case ColorSpace.CS_CIEXYZ:
1100
        createCIEProfile();
1101
        return;
1102
      case ColorSpace.CS_GRAY:
1103
        createGrayProfile();
1104
        return;
1105
      case ColorSpace.CS_PYCC:
1106
        createPyccProfile();
1107
        return;
1108
      default:
1109
        throw new IllegalArgumentException("Not a predefined color space!");
1110
      }
1111
  }
1112
 
1113
  /**
1114
   * Creates an ICC_Profile representing the sRGB color space
1115
   */
1116
  private void createRGBProfile()
1117
  {
1118
    header.setColorSpace( ColorSpace.TYPE_RGB );
1119
    header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1120
    ICC_ColorSpace cs = new ICC_ColorSpace(this);
1121
 
1122
    float[] r = { 1f, 0f, 0f };
1123
    float[] g = { 0f, 1f, 0f };
1124
    float[] b = { 0f, 0f, 1f };
1125
    float[] black = { 0f, 0f, 0f };
1126
 
1127
    // CIE 1931 D50 white point (in Lab coordinates)
1128
    float[] white = D50;
1129
 
1130
    // Get tristimulus values (matrix elements)
1131
    r = cs.toCIEXYZ(r);
1132
    g = cs.toCIEXYZ(g);
1133
    b = cs.toCIEXYZ(b);
1134
 
1135
    // Generate the sRGB TRC curve, this is the linear->nonlinear
1136
    // RGB transform.
1137
    cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB));
1138
    float[] points = new float[TRC_POINTS];
1139
    float[] in = new float[3];
1140
    for (int i = 0; i < TRC_POINTS; i++)
1141
      {
1142
        in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1);
1143
        in = cs.fromRGB(in);
1144
        // Note this value is the same for all components.
1145
        points[i] = in[0];
1146
      }
1147
 
1148
    setData(icSigRedColorantTag, makeXYZData(r));
1149
    setData(icSigGreenColorantTag, makeXYZData(g));
1150
    setData(icSigBlueColorantTag, makeXYZData(b));
1151
    setData(icSigMediaWhitePointTag, makeXYZData(white));
1152
    setData(icSigMediaBlackPointTag, makeXYZData(black));
1153
    setData(icSigRedTRCTag, makeTRC(points));
1154
    setData(icSigGreenTRCTag, makeTRC(points));
1155
    setData(icSigBlueTRCTag, makeTRC(points));
1156
    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1157
    setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB"));
1158
    this.profileID = ColorSpace.CS_sRGB;
1159
  }
1160
 
1161
  /**
1162
   * Creates an linear sRGB profile
1163
   */
1164
  private void createLinearRGBProfile()
1165
  {
1166
    header.setColorSpace(ColorSpace.TYPE_RGB);
1167
    header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1168
    ICC_ColorSpace cs = new ICC_ColorSpace(this);
1169
 
1170
    float[] r = { 1f, 0f, 0f };
1171
    float[] g = { 0f, 1f, 0f };
1172
    float[] b = { 0f, 0f, 1f };
1173
    float[] black = { 0f, 0f, 0f };
1174
 
1175
    float[] white = D50;
1176
 
1177
    // Get tristimulus values (matrix elements)
1178
    r = cs.toCIEXYZ(r);
1179
    g = cs.toCIEXYZ(g);
1180
    b = cs.toCIEXYZ(b);
1181
 
1182
    setData(icSigRedColorantTag, makeXYZData(r));
1183
    setData(icSigGreenColorantTag, makeXYZData(g));
1184
    setData(icSigBlueColorantTag, makeXYZData(b));
1185
 
1186
    setData(icSigMediaWhitePointTag, makeXYZData(white));
1187
    setData(icSigMediaBlackPointTag, makeXYZData(black));
1188
 
1189
    setData(icSigRedTRCTag, makeTRC());
1190
    setData(icSigGreenTRCTag, makeTRC());
1191
    setData(icSigBlueTRCTag, makeTRC());
1192
    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1193
    setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB"));
1194
    this.profileID = ColorSpace.CS_LINEAR_RGB;
1195
  }
1196
 
1197
  /**
1198
   * Creates an CIE XYZ identity profile
1199
   */
1200
  private void createCIEProfile()
1201
  {
1202
    header.setColorSpace( ColorSpace.TYPE_XYZ );
1203
    header.setProfileColorSpace( ColorSpace.TYPE_XYZ );
1204
    header.setProfileClass( CLASS_COLORSPACECONVERSION );
1205
    ICC_ColorSpace cs = new ICC_ColorSpace(this);
1206
 
1207
    float[] white = D50;
1208
 
1209
    setData(icSigMediaWhitePointTag, makeXYZData(white));
1210
    setData(icSigAToB0Tag, makeIdentityClut());
1211
    setData(icSigBToA0Tag, makeIdentityClut());
1212
    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1213
    setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile"));
1214
    this.profileID = ColorSpace.CS_CIEXYZ;
1215
  }
1216
 
1217
  /**
1218
   * Creates a linear gray ICC_Profile
1219
   */
1220
  private void createGrayProfile()
1221
  {
1222
    header.setColorSpace(ColorSpace.TYPE_GRAY);
1223
    header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1224
 
1225
    // CIE 1931 D50 white point (in Lab coordinates)
1226
    float[] white = D50;
1227
 
1228
    setData(icSigMediaWhitePointTag, makeXYZData(white));
1229
    setData(icSigGrayTRCTag, makeTRC(1.0f));
1230
    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1231
    setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale"));
1232
    this.profileID = ColorSpace.CS_GRAY;
1233
  }
1234
 
1235
  /**
1236
   * XXX Implement me
1237
   */
1238
  private void createPyccProfile()
1239
  {
1240
    header.setColorSpace(ColorSpace.TYPE_3CLR);
1241
    header.setProfileColorSpace(ColorSpace.TYPE_XYZ);
1242
 
1243
    // Create CLUTs here. :-)
1244
 
1245
    setData(icSigCopyrightTag, makeTextTag(copyrightNotice));
1246
    setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC"));
1247
    this.profileID = ColorSpace.CS_PYCC;
1248
  }
1249
} // class ICC_Profile

powered by: WebSVN 2.1.0

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