📄 icc_profile.java
字号:
throw new IllegalArgumentException("Invalid profile header"); ProfileHeader header = new ProfileHeader(headerData); // verify it as a correct ICC header, but do not verify the // size as we are reading from a stream. header.verifyHeader(-1); // get the size byte[] data = new byte[header.getSize()]; System.arraycopy(headerData, 0, data, 0, ProfileHeader.HEADERSIZE); // read the rest if (in.read(data, ProfileHeader.HEADERSIZE, header.getSize() - ProfileHeader.HEADERSIZE) != header.getSize() - ProfileHeader.HEADERSIZE) throw new IOException("Incorrect profile size"); return getInstance(data); } /** * Returns the major version number */ public int getMajorVersion() { return header.getMajorVersion(); } /** * Returns the minor version number. * * Only the least-significant byte contains data, in BCD form: * the least-significant nibble is the BCD bug fix revision, * the most-significant nibble is the BCD minor revision number. * * (E.g. For a v2.1.0 profile this will return <code>0x10</code>) */ public int getMinorVersion() { return header.getMinorVersion(); } /** * Returns the device class of this profile, * * (E.g. CLASS_INPUT for a scanner profile, * CLASS_OUTPUT for a printer) */ public int getProfileClass() { return header.getProfileClass(); } /** * Returns the color space of this profile, in terms * of the color space constants defined in ColorSpace. * (For example, it may be a ColorSpace.TYPE_RGB) */ public int getColorSpaceType() { return header.getColorSpace(); } /** * Returns the color space of this profile's Profile Connection Space (OCS) * * In terms of the color space constants defined in ColorSpace. * This may be TYPE_XYZ or TYPE_Lab */ public int getPCSType() { return header.getProfileColorSpace(); } /** * Writes the profile data to an ICC profile file. * @param filename - The name of the file to write * @throws IOException if the write failed. */ public void write(String filename) throws IOException { FileOutputStream out = new FileOutputStream(filename); write(out); out.flush(); out.close(); } /** * Writes the profile data in ICC profile file-format to a stream. * This is useful for embedding ICC profiles in file formats which * support this (such as JPEG and SVG). * * The stream is not closed after writing. * @param out - The outputstream to which the profile data should be written * @throws IOException if the write failed. */ public void write(OutputStream out) throws IOException { out.write(getData()); } /** * Returns the data corresponding to this ICC_Profile as a byte array. * * @return The data in a byte array, * where the first element corresponds to first byte of the profile file. */ public byte[] getData() { int size = getSize(); byte[] data = new byte[size]; // Header System.arraycopy(header.getData(size), 0, data, 0, ProfileHeader.HEADERSIZE); // # of tags byte[] tt = getTagTable(); System.arraycopy(tt, 0, data, ProfileHeader.HEADERSIZE, tt.length); Enumeration e = tagTable.elements(); while (e.hasMoreElements()) { TagEntry tag = (TagEntry) e.nextElement(); System.arraycopy(tag.getData(), 0, data, tag.getOffset(), tag.getSize()); } return data; } /** * Returns the ICC profile tag data * The non ICC-tag icSigHead is also permitted to request the header data. * * @param tagSignature The ICC signature of the requested tag * @return A byte array containing the tag data */ public byte[] getData(int tagSignature) { if (tagSignature == icSigHead) return header.getData(getSize()); TagEntry t = (TagEntry) tagTable.get(TagEntry.tagHashKey(tagSignature)); if (t == null) return null; return t.getData(); } /** * Sets the ICC profile tag data. * * Note that an ICC profile can only contain one tag of each type, if * a tag already exists with the given signature, it is replaced. * * @param tagSignature - The signature of the tag to set * @param data - A byte array containing the tag data */ public void setData(int tagSignature, byte[] data) { profileID = -1; // Not a predefined color space if modified. if (tagSignature == icSigHead) header = new ProfileHeader(data); else { TagEntry t = new TagEntry(tagSignature, data); tagTable.put(t.hashKey(), t); } } /** * Get the number of components in the profile's device color space. */ public int getNumComponents() { int[] lookup = { ColorSpace.TYPE_RGB, 3, ColorSpace.TYPE_CMY, 3, ColorSpace.TYPE_CMYK, 4, ColorSpace.TYPE_GRAY, 1, ColorSpace.TYPE_YCbCr, 3, ColorSpace.TYPE_XYZ, 3, ColorSpace.TYPE_Lab, 3, ColorSpace.TYPE_HSV, 3, ColorSpace.TYPE_2CLR, 2, ColorSpace.TYPE_Luv, 3, ColorSpace.TYPE_Yxy, 3, ColorSpace.TYPE_HLS, 3, ColorSpace.TYPE_3CLR, 3, ColorSpace.TYPE_4CLR, 4, ColorSpace.TYPE_5CLR, 5, ColorSpace.TYPE_6CLR, 6, ColorSpace.TYPE_7CLR, 7, ColorSpace.TYPE_8CLR, 8, ColorSpace.TYPE_9CLR, 9, ColorSpace.TYPE_ACLR, 10, ColorSpace.TYPE_BCLR, 11, ColorSpace.TYPE_CCLR, 12, ColorSpace.TYPE_DCLR, 13, ColorSpace.TYPE_ECLR, 14, ColorSpace.TYPE_FCLR, 15 }; for (int i = 0; i < lookup.length; i += 2) if (header.getColorSpace() == lookup[i]) return lookup[i + 1]; return 3; // should never happen. } /** * After deserializing we must determine if the class we want * is really one of the more specialized ICC_ProfileRGB or * ICC_ProfileGray classes. */ protected Object readResolve() throws ObjectStreamException { if (isRGBProfile(header, tagTable)) return new ICC_ProfileRGB(getData()); if (isGrayProfile(header, tagTable)) return new ICC_ProfileGray(getData()); return this; } /** * Deserializes an instance */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); String predef = (String) s.readObject(); byte[] data = (byte[]) s.readObject(); if (data != null) { header = new ProfileHeader(data); tagTable = createTagTable(data); profileID = -1; // Not a predefined color space } if (predef != null) { predef = predef.intern(); if (predef.equals("CS_sRGB")) createProfile(ColorSpace.CS_sRGB); if (predef.equals("CS_LINEAR_RGB")) createProfile(ColorSpace.CS_LINEAR_RGB); if (predef.equals("CS_CIEXYZ")) createProfile(ColorSpace.CS_CIEXYZ); if (predef.equals("CS_GRAY")) createProfile(ColorSpace.CS_GRAY); if (predef.equals("CS_PYCC")) createProfile(ColorSpace.CS_PYCC); } } /** * Serializes an instance * The format is a String and a byte array, * The string is non-null if the instance is one of the built-in profiles. * Otherwise the byte array is non-null and represents the profile data. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); if (profileID == ColorSpace.CS_sRGB) s.writeObject("CS_sRGB"); else if (profileID == ColorSpace.CS_LINEAR_RGB) s.writeObject("CS_LINEAR_RGB"); else if (profileID == ColorSpace.CS_CIEXYZ) s.writeObject("CS_CIEXYZ"); else if (profileID == ColorSpace.CS_GRAY) s.writeObject("CS_GRAY"); else if (profileID == ColorSpace.CS_PYCC) s.writeObject("CS_PYCC"); else { s.writeObject(null); // null string s.writeObject(getData()); // data return; } s.writeObject(null); // null data } /** * Sorts a ICC profile byte array into TagEntry objects stored in * a hash table. */ private static Hashtable createTagTable(byte[] data) throws IllegalArgumentException { ByteBuffer buf = ByteBuffer.wrap(data); int nTags = buf.getInt(tagTableOffset); Hashtable tagTable = new Hashtable(); for (int i = 0; i < nTags; i++) { TagEntry te = new TagEntry(buf.getInt(tagTableOffset + i * TagEntry.entrySize + 4), buf.getInt(tagTableOffset + i * TagEntry.entrySize + 8), buf.getInt(tagTableOffset + i * TagEntry.entrySize + 12), data); if (tagTable.put(te.hashKey(), te) != null) throw new IllegalArgumentException("Duplicate tag in profile:" + te); } return tagTable; } /** * Returns the total size of the padded, stored data * Note: Tags must be stored on 4-byte aligned offsets. */ private int getSize() { int totalSize = ProfileHeader.HEADERSIZE; // size of header int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; // size of tag table if ((tagTableSize & 0x0003) != 0) tagTableSize += 4 - (tagTableSize & 0x0003); // pad totalSize += tagTableSize; Enumeration e = tagTable.elements(); while (e.hasMoreElements()) { // tag data int tagSize = ((TagEntry) e.nextElement()).getSize(); if ((tagSize & 0x0003) != 0) tagSize += 4 - (tagSize & 0x0003); // pad totalSize += tagSize; } return totalSize; } /** * Generates the tag index table */ private byte[] getTagTable() { int tagTableSize = 4 + tagTable.size() * TagEntry.entrySize; if ((tagTableSize & 0x0003) != 0) tagTableSize += 4 - (tagTableSize & 0x0003); // pad int offset = 4; int tagOffset = ProfileHeader.HEADERSIZE + tagTableSize; ByteBuffer buf = ByteBuffer.allocate(tagTableSize); buf.putInt(tagTable.size()); // number of tags Enumeration e = tagTable.elements(); while (e.hasMoreElements()) { TagEntry tag = (TagEntry) e.nextElement(); buf.putInt(offset, tag.getSignature()); buf.putInt(offset + 4, tagOffset); buf.putInt(offset + 8, tag.getSize()); tag.setOffset(tagOffset); int tagSize = tag.getSize(); if ((tagSize & 0x0003) != 0) tagSize += 4 - (tagSize & 0x0003); // pad tagOffset += tagSize; offset += 12; } return buf.array(); } /** * Returns if the criteria for an ICC_ProfileRGB are met. * This means: * Color space is TYPE_RGB * (r,g,b)ColorantTags included * (r,g,b)TRCTags included * mediaWhitePointTag included */ private static boolean isRGBProfile(ProfileHeader header, Hashtable tags) { if (header.getColorSpace() != ColorSpace.TYPE_RGB) return false; if (tags.get(TagEntry.tagHashKey(icSigRedColorantTag)) == null) return false; if (tags.get(TagEntry.tagHashKey(icSigGreenColorantTag)) == null) return false; if (tags.get(TagEntry.tagHashKey(icSigBlueColorantTag)) == null) return false; if (tags.get(TagEntry.tagHashKey(icSigRedTRCTag)) == null) return false; if (tags.get(TagEntry.tagHashKey(icSigGreenTRCTag)) == null) return false; if (tags.get(TagEntry.tagHashKey(icSigBlueTRCTag)) == null) return false; return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null); } /** * Returns if the criteria for an ICC_ProfileGray are met. * This means: * Colorspace is TYPE_GRAY * grayTRCTag included * mediaWhitePointTag included */ private static boolean isGrayProfile(ProfileHeader header, Hashtable tags) { if (header.getColorSpace() != ColorSpace.TYPE_GRAY) return false; if (tags.get(TagEntry.tagHashKey(icSigGrayTRCTag)) == null) return false; return (tags.get(TagEntry.tagHashKey(icSigMediaWhitePointTag)) != null); } /** * Returns curve data for a 'curv'-type tag * If it's a gamma curve, a single entry will be returned with the * gamma value (including 1.0 for linear response) * Otherwise the TRC table is returned. * * (Package private - used by ICC_ProfileRGB and ICC_ProfileGray) */ short[] getCurve(int signature) { byte[] data = getData(signature); short[] curve; // can't find tag? if (data == null) return null; // not an curve type tag? ByteBuffer buf = ByteBuffer.wrap(data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -