| /* ProfileHeader.java -- Encapsules ICC Profile header data |
| Copyright (C) 2004 Free Software Foundation |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. |
| */ |
| |
| package gnu.java.awt.color; |
| |
| import java.awt.color.ColorSpace; |
| import java.awt.color.ICC_Profile; |
| import java.nio.ByteBuffer; |
| |
| |
| /** |
| * Header, abstracts and validates the header data. |
| * |
| * @author Sven de Marothy |
| */ |
| public class ProfileHeader |
| { |
| /** |
| * Magic identifier (ASCII 'acsp') |
| */ |
| private static final int icMagicNumber = 0x61637370; |
| |
| /** |
| * Mapping from ICC Profile signatures to ColorSpace types |
| */ |
| private static final int[] csTypeMap = |
| { |
| ICC_Profile.icSigXYZData, |
| ColorSpace.TYPE_XYZ, |
| ICC_Profile.icSigLabData, |
| ColorSpace.TYPE_Lab, |
| ICC_Profile.icSigLuvData, |
| ColorSpace.TYPE_Luv, |
| ICC_Profile.icSigYCbCrData, |
| ColorSpace.TYPE_YCbCr, |
| ICC_Profile.icSigYxyData, |
| ColorSpace.TYPE_Yxy, |
| ICC_Profile.icSigRgbData, |
| ColorSpace.TYPE_RGB, |
| ICC_Profile.icSigGrayData, |
| ColorSpace.TYPE_GRAY, |
| ICC_Profile.icSigHsvData, |
| ColorSpace.TYPE_HSV, |
| ICC_Profile.icSigHlsData, |
| ColorSpace.TYPE_HLS, |
| ICC_Profile.icSigCmykData, |
| ColorSpace.TYPE_CMYK, |
| ICC_Profile.icSigCmyData, |
| ColorSpace.TYPE_CMY, |
| ICC_Profile.icSigSpace2CLR, |
| ColorSpace.TYPE_2CLR, |
| ICC_Profile.icSigSpace3CLR, |
| ColorSpace.TYPE_3CLR, |
| ICC_Profile.icSigSpace4CLR, |
| ColorSpace.TYPE_4CLR, |
| ICC_Profile.icSigSpace5CLR, |
| ColorSpace.TYPE_5CLR, |
| ICC_Profile.icSigSpace6CLR, |
| ColorSpace.TYPE_6CLR, |
| ICC_Profile.icSigSpace7CLR, |
| ColorSpace.TYPE_7CLR, |
| ICC_Profile.icSigSpace8CLR, |
| ColorSpace.TYPE_8CLR, |
| ICC_Profile.icSigSpace9CLR, |
| ColorSpace.TYPE_9CLR, |
| ICC_Profile.icSigSpaceACLR, |
| ColorSpace.TYPE_ACLR, |
| ICC_Profile.icSigSpaceBCLR, |
| ColorSpace.TYPE_BCLR, |
| ICC_Profile.icSigSpaceCCLR, |
| ColorSpace.TYPE_CCLR, |
| ICC_Profile.icSigSpaceDCLR, |
| ColorSpace.TYPE_DCLR, |
| ICC_Profile.icSigSpaceECLR, |
| ColorSpace.TYPE_ECLR, |
| ICC_Profile.icSigSpaceFCLR, |
| ColorSpace.TYPE_FCLR |
| }; |
| |
| /** |
| * Size of an ICC header (128 bytes) |
| */ |
| public static final int HEADERSIZE = 128; |
| |
| /** |
| * Mapping of ICC class signatures to profile class constants |
| */ |
| private static final int[] classMap = |
| { |
| ICC_Profile.icSigInputClass, |
| ICC_Profile.CLASS_INPUT, |
| ICC_Profile.icSigDisplayClass, |
| ICC_Profile.CLASS_DISPLAY, |
| ICC_Profile.icSigOutputClass, |
| ICC_Profile.CLASS_OUTPUT, |
| ICC_Profile.icSigLinkClass, |
| ICC_Profile.CLASS_DEVICELINK, |
| ICC_Profile.icSigColorSpaceClass, |
| ICC_Profile.CLASS_COLORSPACECONVERSION, |
| ICC_Profile.icSigAbstractClass, |
| ICC_Profile.CLASS_ABSTRACT, |
| ICC_Profile.icSigNamedColorClass, |
| ICC_Profile.CLASS_NAMEDCOLOR |
| }; |
| private int size; |
| private int cmmId; |
| |
| // Major/Minor version, The ICC-1998 spec is major v2 |
| private int majorVersion; |
| |
| // Major/Minor version, The ICC-1998 spec is major v2 |
| private int minorVersion; |
| private int profileClass; // profile device class |
| private int colorSpace; // data color space type |
| private int profileColorSpace; // profile connection space (PCS) type |
| private byte[] timestamp; // original creation timestamp |
| private int platform; // platform signature |
| private int flags; // flags |
| private int magic; // magic number. |
| private int manufacturerSig; // manufacturer sig |
| private int modelSig; // model sig |
| private byte[] attributes; // Attributes |
| private int intent; // rendering intent |
| private byte[] illuminant; // illuminant info (Coordinates of D50 in the PCS) |
| private int creatorSig; // Creator sig (same type as manufacturer) |
| |
| /** |
| * Creates a 'default' header for use with our predefined profiles. |
| * Note the device and profile color spaces are not set. |
| */ |
| public ProfileHeader() |
| { |
| creatorSig = 0; |
| intent = 0; |
| modelSig = manufacturerSig = (int) 0x6E6f6E65; // 'none' |
| magic = icMagicNumber; |
| cmmId = 0; |
| platform = 0; // no preferred platform |
| timestamp = new byte[8]; |
| majorVersion = 2; |
| minorVersion = 0x10; |
| flags = 0; |
| |
| // D50 in XYZ format (encoded) |
| illuminant = new byte[] |
| { |
| (byte) 0x00, (byte) 0x00, (byte) 0xf6, (byte) 0xd6, |
| (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, |
| (byte) 0x00, (byte) 0x00, (byte) 0xd3, (byte) 0x2d |
| }; |
| attributes = new byte[8]; |
| profileClass = ICC_Profile.CLASS_DISPLAY; |
| } |
| |
| /** |
| * Creates a header from profile data. Only the header portion (128 bytes) |
| * is read, so the array passed need not be the full profile. |
| */ |
| public ProfileHeader(byte[] data) |
| { |
| ByteBuffer buf = ByteBuffer.wrap(data); |
| |
| // Get size (the sign bit shouldn't matter. |
| // A valid profile can never be +2Gb) |
| size = buf.getInt(ICC_Profile.icHdrSize); |
| |
| // CMM ID |
| cmmId = buf.getInt(ICC_Profile.icHdrCmmId); |
| |
| // Version number |
| majorVersion = (int) (data[ICC_Profile.icHdrVersion]); |
| minorVersion = (int) (data[ICC_Profile.icHdrVersion + 1]); |
| |
| // Profile/Device class |
| int classSig = buf.getInt(ICC_Profile.icHdrDeviceClass); |
| profileClass = -1; |
| for (int i = 0; i < classMap.length; i += 2) |
| if (classMap[i] == classSig) |
| { |
| profileClass = classMap[i + 1]; |
| break; |
| } |
| |
| // get the data color space |
| int csSig = buf.getInt(ICC_Profile.icHdrColorSpace); |
| colorSpace = -1; |
| for (int i = 0; i < csTypeMap.length; i += 2) |
| if (csTypeMap[i] == csSig) |
| { |
| colorSpace = csTypeMap[i + 1]; |
| break; |
| } |
| |
| // get the profile color space (PCS), must be xyz or lab except |
| // for device-link-class profiles |
| int pcsSig = buf.getInt(ICC_Profile.icHdrPcs); |
| profileColorSpace = -1; |
| if (profileClass != ICC_Profile.CLASS_DEVICELINK) |
| { |
| if (pcsSig == ICC_Profile.icSigXYZData) |
| profileColorSpace = ColorSpace.TYPE_XYZ; |
| if (pcsSig == ICC_Profile.icSigLabData) |
| profileColorSpace = ColorSpace.TYPE_Lab; |
| } |
| else |
| { |
| for (int i = 0; i < csTypeMap.length; i += 2) |
| if (csTypeMap[i] == pcsSig) |
| { |
| profileColorSpace = csTypeMap[i + 1]; |
| break; |
| } |
| } |
| |
| // creation timestamp |
| timestamp = new byte[8]; |
| System.arraycopy(data, ICC_Profile.icHdrDate, timestamp, 0, 8); |
| |
| // magic number |
| magic = buf.getInt(ICC_Profile.icHdrMagic); |
| |
| // platform info |
| platform = buf.getInt(ICC_Profile.icHdrPlatform); |
| // get flags |
| flags = buf.getInt(ICC_Profile.icHdrFlags); |
| // get manufacturer sign |
| manufacturerSig = buf.getInt(ICC_Profile.icHdrManufacturer); |
| // get header model |
| modelSig = buf.getInt(ICC_Profile.icHdrModel); |
| // attributes |
| attributes = new byte[8]; |
| System.arraycopy(data, ICC_Profile.icHdrAttributes, attributes, 0, 8); |
| // rendering intent |
| intent = buf.getInt(ICC_Profile.icHdrRenderingIntent); |
| // illuminant info |
| illuminant = new byte[12]; |
| System.arraycopy(data, ICC_Profile.icHdrIlluminant, illuminant, 0, 12); |
| // Creator signature |
| creatorSig = buf.getInt(ICC_Profile.icHdrCreator); |
| // The rest of the header (Total size: 128 bytes) is unused.. |
| } |
| |
| /** |
| * Verify that the header is valid |
| * @param size equals the file size if it is to be verified, -1 otherwise |
| * @throws IllegalArgumentException if the header is found to be invalid. |
| */ |
| public void verifyHeader(int size) throws IllegalArgumentException |
| { |
| // verify size |
| if (size != -1 && this.size != size) |
| throw new IllegalArgumentException("Invalid profile length:" + size); |
| |
| // Check version number |
| if (majorVersion != 2) |
| throw new IllegalArgumentException("Wrong major version number:" |
| + majorVersion); |
| |
| // Profile/Device class |
| if (profileClass == -1) |
| throw new IllegalArgumentException("Invalid profile/device class"); |
| |
| // get the data color space |
| if (colorSpace == -1) |
| throw new IllegalArgumentException("Invalid colorspace"); |
| |
| // profile color space |
| if (profileColorSpace == -1) |
| throw new IllegalArgumentException("Invalid PCS."); |
| |
| // check magic number |
| if (magic != icMagicNumber) |
| throw new IllegalArgumentException("Invalid magic number!"); |
| } |
| |
| /** |
| * Creates a header, setting the header file size at the same time. |
| * @param size the profile file size. |
| */ |
| public byte[] getData(int size) |
| { |
| byte[] data = new byte[HEADERSIZE]; |
| ByteBuffer buf = ByteBuffer.wrap(data); |
| buf.putInt(ICC_Profile.icHdrSize, size); |
| buf.putInt(ICC_Profile.icHdrCmmId, cmmId); |
| buf.putShort(ICC_Profile.icHdrVersion, |
| (short) (majorVersion << 8 | minorVersion)); |
| for (int i = 1; i < classMap.length; i += 2) |
| if (profileClass == classMap[i]) |
| buf.putInt(ICC_Profile.icHdrDeviceClass, classMap[i - 1]); |
| for (int i = 1; i < csTypeMap.length; i += 2) |
| if (csTypeMap[i] == colorSpace) |
| buf.putInt(ICC_Profile.icHdrColorSpace, csTypeMap[i - 1]); |
| for (int i = 1; i < csTypeMap.length; i += 2) |
| if (csTypeMap[i] == profileColorSpace) |
| buf.putInt(ICC_Profile.icHdrPcs, csTypeMap[i - 1]); |
| |
| System.arraycopy(timestamp, 0, data, ICC_Profile.icHdrDate, |
| timestamp.length); |
| buf.putInt(ICC_Profile.icHdrMagic, icMagicNumber); |
| buf.putInt(ICC_Profile.icHdrPlatform, platform); |
| buf.putInt(ICC_Profile.icHdrFlags, flags); |
| buf.putInt(ICC_Profile.icHdrManufacturer, manufacturerSig); |
| buf.putInt(ICC_Profile.icHdrModel, modelSig); |
| System.arraycopy(attributes, 0, data, ICC_Profile.icHdrAttributes, |
| attributes.length); |
| buf.putInt(ICC_Profile.icHdrRenderingIntent, intent); |
| System.arraycopy(illuminant, 0, data, ICC_Profile.icHdrIlluminant, |
| illuminant.length); |
| buf.putInt(ICC_Profile.icHdrCreator, creatorSig); |
| return buf.array(); |
| } |
| |
| public int getSize() |
| { |
| return size; |
| } |
| |
| public void setSize(int s) |
| { |
| size = s; |
| } |
| |
| public int getMajorVersion() |
| { |
| return majorVersion; |
| } |
| |
| public int getMinorVersion() |
| { |
| return minorVersion; |
| } |
| |
| public int getProfileClass() |
| { |
| return profileClass; |
| } |
| |
| public void setProfileClass(int pc) |
| { |
| profileClass = pc; |
| } |
| |
| public int getColorSpace() |
| { |
| return colorSpace; |
| } |
| |
| public int getProfileColorSpace() |
| { |
| return profileColorSpace; |
| } |
| |
| public void setColorSpace(int cs) |
| { |
| colorSpace = cs; |
| } |
| |
| public void setProfileColorSpace(int pcs) |
| { |
| profileColorSpace = pcs; |
| } |
| |
| } |