1
/* ProfileHeader.java -- Encapsules ICC Profile header data
2
Copyright (C) 2004 Free Software Foundation
4
This file is part of GNU Classpath.
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)
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.
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
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
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. */
38
package gnu.java.awt.color;
40
import java.awt.color.ColorSpace;
41
import java.awt.color.ICC_Profile;
42
import java.nio.ByteBuffer;
46
* Header, abstracts and validates the header data.
48
* @author Sven de Marothy
50
public class ProfileHeader
53
* Magic identifier (ASCII 'acsp')
55
private static final int icMagicNumber = 0x61637370;
58
* Mapping from ICC Profile signatures to ColorSpace types
60
private static final int[] csTypeMap =
62
ICC_Profile.icSigXYZData,
64
ICC_Profile.icSigLabData,
66
ICC_Profile.icSigLuvData,
68
ICC_Profile.icSigYCbCrData,
69
ColorSpace.TYPE_YCbCr,
70
ICC_Profile.icSigYxyData,
72
ICC_Profile.icSigRgbData,
74
ICC_Profile.icSigGrayData,
76
ICC_Profile.icSigHsvData,
78
ICC_Profile.icSigHlsData,
80
ICC_Profile.icSigCmykData,
82
ICC_Profile.icSigCmyData,
84
ICC_Profile.icSigSpace2CLR,
86
ICC_Profile.icSigSpace3CLR,
88
ICC_Profile.icSigSpace4CLR,
90
ICC_Profile.icSigSpace5CLR,
92
ICC_Profile.icSigSpace6CLR,
94
ICC_Profile.icSigSpace7CLR,
96
ICC_Profile.icSigSpace8CLR,
98
ICC_Profile.icSigSpace9CLR,
100
ICC_Profile.icSigSpaceACLR,
101
ColorSpace.TYPE_ACLR,
102
ICC_Profile.icSigSpaceBCLR,
103
ColorSpace.TYPE_BCLR,
104
ICC_Profile.icSigSpaceCCLR,
105
ColorSpace.TYPE_CCLR,
106
ICC_Profile.icSigSpaceDCLR,
107
ColorSpace.TYPE_DCLR,
108
ICC_Profile.icSigSpaceECLR,
109
ColorSpace.TYPE_ECLR,
110
ICC_Profile.icSigSpaceFCLR,
115
* Size of an ICC header (128 bytes)
117
public static final int HEADERSIZE = 128;
120
* Mapping of ICC class signatures to profile class constants
122
private static final int[] classMap =
124
ICC_Profile.icSigInputClass,
125
ICC_Profile.CLASS_INPUT,
126
ICC_Profile.icSigDisplayClass,
127
ICC_Profile.CLASS_DISPLAY,
128
ICC_Profile.icSigOutputClass,
129
ICC_Profile.CLASS_OUTPUT,
130
ICC_Profile.icSigLinkClass,
131
ICC_Profile.CLASS_DEVICELINK,
132
ICC_Profile.icSigColorSpaceClass,
133
ICC_Profile.CLASS_COLORSPACECONVERSION,
134
ICC_Profile.icSigAbstractClass,
135
ICC_Profile.CLASS_ABSTRACT,
136
ICC_Profile.icSigNamedColorClass,
137
ICC_Profile.CLASS_NAMEDCOLOR
142
// Major/Minor version, The ICC-1998 spec is major v2
143
private int majorVersion;
145
// Major/Minor version, The ICC-1998 spec is major v2
146
private int minorVersion;
147
private int profileClass; // profile device class
148
private int colorSpace; // data color space type
149
private int profileColorSpace; // profile connection space (PCS) type
150
private byte[] timestamp; // original creation timestamp
151
private int platform; // platform signature
152
private int flags; // flags
153
private int magic; // magic number.
154
private int manufacturerSig; // manufacturer sig
155
private int modelSig; // model sig
156
private byte[] attributes; // Attributes
157
private int intent; // rendering intent
158
private byte[] illuminant; // illuminant info (Coordinates of D50 in the PCS)
159
private int creatorSig; // Creator sig (same type as manufacturer)
162
* Creates a 'default' header for use with our predefined profiles.
163
* Note the device and profile color spaces are not set.
165
public ProfileHeader()
169
modelSig = manufacturerSig = (int) 0x6E6f6E65; // 'none'
170
magic = icMagicNumber;
172
platform = 0; // no preferred platform
173
timestamp = new byte[8];
178
// D50 in XYZ format (encoded)
179
illuminant = new byte[]
181
(byte) 0x00, (byte) 0x00, (byte) 0xf6, (byte) 0xd6,
182
(byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
183
(byte) 0x00, (byte) 0x00, (byte) 0xd3, (byte) 0x2d
185
attributes = new byte[8];
186
profileClass = ICC_Profile.CLASS_DISPLAY;
190
* Creates a header from profile data. Only the header portion (128 bytes)
191
* is read, so the array passed need not be the full profile.
193
public ProfileHeader(byte[] data)
195
ByteBuffer buf = ByteBuffer.wrap(data);
197
// Get size (the sign bit shouldn't matter.
198
// A valid profile can never be +2Gb)
199
size = buf.getInt(ICC_Profile.icHdrSize);
202
cmmId = buf.getInt(ICC_Profile.icHdrCmmId);
205
majorVersion = (int) (data[ICC_Profile.icHdrVersion]);
206
minorVersion = (int) (data[ICC_Profile.icHdrVersion + 1]);
208
// Profile/Device class
209
int classSig = buf.getInt(ICC_Profile.icHdrDeviceClass);
211
for (int i = 0; i < classMap.length; i += 2)
212
if (classMap[i] == classSig)
214
profileClass = classMap[i + 1];
218
// get the data color space
219
int csSig = buf.getInt(ICC_Profile.icHdrColorSpace);
221
for (int i = 0; i < csTypeMap.length; i += 2)
222
if (csTypeMap[i] == csSig)
224
colorSpace = csTypeMap[i + 1];
228
// get the profile color space (PCS), must be xyz or lab except
229
// for device-link-class profiles
230
int pcsSig = buf.getInt(ICC_Profile.icHdrPcs);
231
profileColorSpace = -1;
232
if (profileClass != ICC_Profile.CLASS_DEVICELINK)
234
if (pcsSig == ICC_Profile.icSigXYZData)
235
profileColorSpace = ColorSpace.TYPE_XYZ;
236
if (pcsSig == ICC_Profile.icSigLabData)
237
profileColorSpace = ColorSpace.TYPE_Lab;
241
for (int i = 0; i < csTypeMap.length; i += 2)
242
if (csTypeMap[i] == pcsSig)
244
profileColorSpace = csTypeMap[i + 1];
249
// creation timestamp
250
timestamp = new byte[8];
251
System.arraycopy(data, ICC_Profile.icHdrDate, timestamp, 0, 8);
254
magic = buf.getInt(ICC_Profile.icHdrMagic);
257
platform = buf.getInt(ICC_Profile.icHdrPlatform);
259
flags = buf.getInt(ICC_Profile.icHdrFlags);
260
// get manufacturer sign
261
manufacturerSig = buf.getInt(ICC_Profile.icHdrManufacturer);
263
modelSig = buf.getInt(ICC_Profile.icHdrModel);
265
attributes = new byte[8];
266
System.arraycopy(data, ICC_Profile.icHdrAttributes, attributes, 0, 8);
268
intent = buf.getInt(ICC_Profile.icHdrRenderingIntent);
270
illuminant = new byte[12];
271
System.arraycopy(data, ICC_Profile.icHdrIlluminant, illuminant, 0, 12);
273
creatorSig = buf.getInt(ICC_Profile.icHdrCreator);
274
// The rest of the header (Total size: 128 bytes) is unused..
278
* Verify that the header is valid
279
* @param size equals the file size if it is to be verified, -1 otherwise
280
* @throws IllegalArgumentException if the header is found to be invalid.
282
public void verifyHeader(int size) throws IllegalArgumentException
285
if (size != -1 && this.size != size)
286
throw new IllegalArgumentException("Invalid profile length:" + size);
288
// Check version number
289
if (majorVersion != 2)
290
throw new IllegalArgumentException("Wrong major version number:"
293
// Profile/Device class
294
if (profileClass == -1)
295
throw new IllegalArgumentException("Invalid profile/device class");
297
// get the data color space
298
if (colorSpace == -1)
299
throw new IllegalArgumentException("Invalid colorspace");
301
// profile color space
302
if (profileColorSpace == -1)
303
throw new IllegalArgumentException("Invalid PCS.");
305
// check magic number
306
if (magic != icMagicNumber)
307
throw new IllegalArgumentException("Invalid magic number!");
311
* Creates a header, setting the header file size at the same time.
312
* @param size the profile file size.
314
public byte[] getData(int size)
316
byte[] data = new byte[HEADERSIZE];
317
ByteBuffer buf = ByteBuffer.wrap(data);
318
buf.putInt(ICC_Profile.icHdrSize, size);
319
buf.putInt(ICC_Profile.icHdrCmmId, cmmId);
320
buf.putShort(ICC_Profile.icHdrVersion,
321
(short) (majorVersion << 8 | minorVersion));
322
for (int i = 1; i < classMap.length; i += 2)
323
if (profileClass == classMap[i])
324
buf.putInt(ICC_Profile.icHdrDeviceClass, classMap[i - 1]);
325
for (int i = 1; i < csTypeMap.length; i += 2)
326
if (csTypeMap[i] == colorSpace)
327
buf.putInt(ICC_Profile.icHdrColorSpace, csTypeMap[i - 1]);
328
for (int i = 1; i < csTypeMap.length; i += 2)
329
if (csTypeMap[i] == profileColorSpace)
330
buf.putInt(ICC_Profile.icHdrPcs, csTypeMap[i - 1]);
332
System.arraycopy(timestamp, 0, data, ICC_Profile.icHdrDate,
334
buf.putInt(ICC_Profile.icHdrMagic, icMagicNumber);
335
buf.putInt(ICC_Profile.icHdrPlatform, platform);
336
buf.putInt(ICC_Profile.icHdrFlags, flags);
337
buf.putInt(ICC_Profile.icHdrManufacturer, manufacturerSig);
338
buf.putInt(ICC_Profile.icHdrModel, modelSig);
339
System.arraycopy(attributes, 0, data, ICC_Profile.icHdrAttributes,
341
buf.putInt(ICC_Profile.icHdrRenderingIntent, intent);
342
System.arraycopy(illuminant, 0, data, ICC_Profile.icHdrIlluminant,
344
buf.putInt(ICC_Profile.icHdrCreator, creatorSig);
353
public void setSize(int s)
358
public int getMajorVersion()
363
public int getMinorVersion()
368
public int getProfileClass()
373
public void setProfileClass(int pc)
378
public int getColorSpace()
383
public int getProfileColorSpace()
385
return profileColorSpace;
388
public void setColorSpace(int cs)
393
public void setProfileColorSpace(int pcs)
395
profileColorSpace = pcs;