📄 icc_profile.java
字号:
if (buf.getInt(0) != 0x63757276) // 'curv' type return null; int count = buf.getInt(8); if (count == 0) { curve = new short[1]; curve[0] = 0x0100; // 1.00 in u8fixed8 return curve; } if (count == 1) { curve = new short[1]; curve[0] = buf.getShort(12); // other u8fixed8 gamma return curve; } curve = new short[count]; for (int i = 0; i < count; i++) curve[i] = buf.getShort(12 + i * 2); return curve; } /** * Returns XYZ tristimulus values for an 'XYZ ' type tag * @return the XYZ values, or null if the tag was not an 'XYZ ' type tag. * * (Package private - used by ICC_ProfileXYZ and ICC_ProfileGray) */ float[] getXYZData(int signature) { byte[] data = getData(signature); // can't find tag? if (data == null) return null; // not an XYZData type tag? ByteBuffer buf = ByteBuffer.wrap(data); if (buf.getInt(0) != icSigXYZData) // 'XYZ ' type return null; float[] point = new float[3]; // get the X,Y,Z tristimulus values point[0] = ((float) buf.getInt(8)) / 65536f; point[1] = ((float) buf.getInt(12)) / 65536f; point[2] = ((float) buf.getInt(16)) / 65536f; return point; } /** * Returns the profile ID if it's a predefined profile * Or -1 for a profile loaded from an ICC profile * * (Package private - used by ICC_ColorSpace) */ int isPredefined() { return profileID; } /** * Creates a tag of XYZ-value type. */ private byte[] makeXYZData(float[] values) { ByteBuffer buf = ByteBuffer.allocate(20); buf.putInt(0, icSigXYZData); // 'XYZ ' buf.putInt(4, 0); buf.putInt(8, (int) (values[0] * 65536.0)); buf.putInt(12, (int) (values[1] * 65536.0)); buf.putInt(16, (int) (values[2] * 65536.0)); return buf.array(); } /** * Creates a tag of text type */ private byte[] makeTextTag(String text) { int length = text.length(); ByteBuffer buf = ByteBuffer.allocate(8 + length + 1); byte[] data; try { data = text.getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { data = new byte[length]; // shouldn't happen } buf.putInt(0, (int) 0x74657874); // 'text' buf.putInt(4, 0); for (int i = 0; i < length; i++) buf.put(8 + i, data[i]); buf.put(8 + length, (byte) 0); // null-terminate return buf.array(); } /** * Creates a tag of textDescriptionType */ private byte[] makeDescTag(String text) { int length = text.length(); ByteBuffer buf = ByteBuffer.allocate(90 + length + 1); buf.putInt(0, (int) 0x64657363); // 'desc' buf.putInt(4, 0); // reserved buf.putInt(8, length + 1); // ASCII length, including null termination byte[] data; try { data = text.getBytes("US-ASCII"); } catch (UnsupportedEncodingException e) { data = new byte[length]; // shouldn't happen } for (int i = 0; i < length; i++) buf.put(12 + i, data[i]); buf.put(12 + length, (byte) 0); // null-terminate for (int i = 0; i < 39; i++) buf.putShort(13 + length + (i * 2), (short) 0); // 78 bytes we can ignore return buf.array(); } /** * Creates a tag of TRC type (linear curve) */ private byte[] makeTRC() { ByteBuffer buf = ByteBuffer.allocate(12); buf.putInt(0, 0x63757276); // 'curv' type buf.putInt(4, 0); // reserved buf.putInt(8, 0); return buf.array(); } /** * Creates a tag of TRC type (single gamma value) */ private byte[] makeTRC(float gamma) { short gammaValue = (short) (gamma * 256f); ByteBuffer buf = ByteBuffer.allocate(14); buf.putInt(0, 0x63757276); // 'curv' type buf.putInt(4, 0); // reserved buf.putInt(8, 1); buf.putShort(12, gammaValue); // 1.00 in u8fixed8 return buf.array(); } /** * Creates a tag of TRC type (TRC curve points) */ private byte[] makeTRC(float[] trc) { ByteBuffer buf = ByteBuffer.allocate(12 + 2 * trc.length); buf.putInt(0, 0x63757276); // 'curv' type buf.putInt(4, 0); // reserved buf.putInt(8, trc.length); // number of points // put the curve values for (int i = 0; i < trc.length; i++) buf.putShort(12 + i * 2, (short) (trc[i] * 65535f)); return buf.array(); } /** * Creates an identity color lookup table. */ private byte[] makeIdentityClut() { final int nIn = 3; final int nOut = 3; final int nInEntries = 256; final int nOutEntries = 256; final int gridpoints = 16; // gridpoints**nIn final int clutSize = 2 * nOut * gridpoints * gridpoints * gridpoints; final int totalSize = clutSize + 2 * nInEntries * nIn + 2 * nOutEntries * nOut + 52; ByteBuffer buf = ByteBuffer.allocate(totalSize); buf.putInt(0, 0x6D667432); // 'mft2' buf.putInt(4, 0); // reserved buf.put(8, (byte) nIn); // number input channels buf.put(9, (byte) nOut); // number output channels buf.put(10, (byte) gridpoints); // number gridpoints buf.put(11, (byte) 0); // padding // identity matrix buf.putInt(12, 65536); // = 1 in s15.16 fixed point buf.putInt(16, 0); buf.putInt(20, 0); buf.putInt(24, 0); buf.putInt(28, 65536); buf.putInt(32, 0); buf.putInt(36, 0); buf.putInt(40, 0); buf.putInt(44, 65536); buf.putShort(48, (short) nInEntries); // input table entries buf.putShort(50, (short) nOutEntries); // output table entries // write the linear input channels, unsigned 16.16 fixed point, // from 0.0 to FF.FF for (int channel = 0; channel < 3; channel++) for (int i = 0; i < nInEntries; i++) { short n = (short) ((i << 8) | i); // assumes 256 entries buf.putShort(52 + (channel * nInEntries + i) * 2, n); } int clutOffset = 52 + nInEntries * nIn * 2; for (int x = 0; x < gridpoints; x++) for (int y = 0; y < gridpoints; y++) for (int z = 0; z < gridpoints; z++) { int offset = clutOffset + z * 2 * nOut + y * gridpoints * 2 * nOut + x * gridpoints * gridpoints * 2 * nOut; double xf = ((double) x) / ((double) gridpoints - 1.0); double yf = ((double) y) / ((double) gridpoints - 1.0); double zf = ((double) z) / ((double) gridpoints - 1.0); buf.putShort(offset, (short) (xf * 65535.0)); buf.putShort(offset + 2, (short) (yf * 65535.0)); buf.putShort(offset + 4, (short) (zf * 65535.0)); } for (int channel = 0; channel < 3; channel++) for (int i = 0; i < nOutEntries; i++) { short n = (short) ((i << 8) | i); // assumes 256 entries buf.putShort(clutOffset + clutSize + (channel * nOutEntries + i) * 2, n); } return buf.array(); } /** * Creates profile data corresponding to the built-in colorspaces. */ private void createProfile(int colorSpace) throws IllegalArgumentException { this.profileID = colorSpace; header = new ProfileHeader(); tagTable = new Hashtable(); switch (colorSpace) { case ColorSpace.CS_sRGB: createRGBProfile(); return; case ColorSpace.CS_LINEAR_RGB: createLinearRGBProfile(); return; case ColorSpace.CS_CIEXYZ: createCIEProfile(); return; case ColorSpace.CS_GRAY: createGrayProfile(); return; case ColorSpace.CS_PYCC: createPyccProfile(); return; default: throw new IllegalArgumentException("Not a predefined color space!"); } } /** * Creates an ICC_Profile representing the sRGB color space */ private void createRGBProfile() { header.setColorSpace( ColorSpace.TYPE_RGB ); header.setProfileColorSpace( ColorSpace.TYPE_XYZ ); ICC_ColorSpace cs = new ICC_ColorSpace(this); float[] r = { 1f, 0f, 0f }; float[] g = { 0f, 1f, 0f }; float[] b = { 0f, 0f, 1f }; float[] black = { 0f, 0f, 0f }; // CIE 1931 D50 white point (in Lab coordinates) float[] white = D50; // Get tristimulus values (matrix elements) r = cs.toCIEXYZ(r); g = cs.toCIEXYZ(g); b = cs.toCIEXYZ(b); // Generate the sRGB TRC curve, this is the linear->nonlinear // RGB transform. cs = new ICC_ColorSpace(getInstance(ICC_ColorSpace.CS_LINEAR_RGB)); float[] points = new float[TRC_POINTS]; float[] in = new float[3]; for (int i = 0; i < TRC_POINTS; i++) { in[0] = in[1] = in[2] = ((float) i) / ((float) TRC_POINTS - 1); in = cs.fromRGB(in); // Note this value is the same for all components. points[i] = in[0]; } setData(icSigRedColorantTag, makeXYZData(r)); setData(icSigGreenColorantTag, makeXYZData(g)); setData(icSigBlueColorantTag, makeXYZData(b)); setData(icSigMediaWhitePointTag, makeXYZData(white)); setData(icSigMediaBlackPointTag, makeXYZData(black)); setData(icSigRedTRCTag, makeTRC(points)); setData(icSigGreenTRCTag, makeTRC(points)); setData(icSigBlueTRCTag, makeTRC(points)); setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); setData(icSigProfileDescriptionTag, makeDescTag("Generic sRGB")); this.profileID = ColorSpace.CS_sRGB; } /** * Creates an linear sRGB profile */ private void createLinearRGBProfile() { header.setColorSpace(ColorSpace.TYPE_RGB); header.setProfileColorSpace(ColorSpace.TYPE_XYZ); ICC_ColorSpace cs = new ICC_ColorSpace(this); float[] r = { 1f, 0f, 0f }; float[] g = { 0f, 1f, 0f }; float[] b = { 0f, 0f, 1f }; float[] black = { 0f, 0f, 0f }; float[] white = D50; // Get tristimulus values (matrix elements) r = cs.toCIEXYZ(r); g = cs.toCIEXYZ(g); b = cs.toCIEXYZ(b); setData(icSigRedColorantTag, makeXYZData(r)); setData(icSigGreenColorantTag, makeXYZData(g)); setData(icSigBlueColorantTag, makeXYZData(b)); setData(icSigMediaWhitePointTag, makeXYZData(white)); setData(icSigMediaBlackPointTag, makeXYZData(black)); setData(icSigRedTRCTag, makeTRC()); setData(icSigGreenTRCTag, makeTRC()); setData(icSigBlueTRCTag, makeTRC()); setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); setData(icSigProfileDescriptionTag, makeDescTag("Linear RGB")); this.profileID = ColorSpace.CS_LINEAR_RGB; } /** * Creates an CIE XYZ identity profile */ private void createCIEProfile() { header.setColorSpace( ColorSpace.TYPE_XYZ ); header.setProfileColorSpace( ColorSpace.TYPE_XYZ ); header.setProfileClass( CLASS_COLORSPACECONVERSION ); ICC_ColorSpace cs = new ICC_ColorSpace(this); float[] white = D50; setData(icSigMediaWhitePointTag, makeXYZData(white)); setData(icSigAToB0Tag, makeIdentityClut()); setData(icSigBToA0Tag, makeIdentityClut()); setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); setData(icSigProfileDescriptionTag, makeDescTag("CIE XYZ identity profile")); this.profileID = ColorSpace.CS_CIEXYZ; } /** * Creates a linear gray ICC_Profile */ private void createGrayProfile() { header.setColorSpace(ColorSpace.TYPE_GRAY); header.setProfileColorSpace(ColorSpace.TYPE_XYZ); // CIE 1931 D50 white point (in Lab coordinates) float[] white = D50; setData(icSigMediaWhitePointTag, makeXYZData(white)); setData(icSigGrayTRCTag, makeTRC(1.0f)); setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); setData(icSigProfileDescriptionTag, makeDescTag("Linear grayscale")); this.profileID = ColorSpace.CS_GRAY; } /** * XXX Implement me */ private void createPyccProfile() { header.setColorSpace(ColorSpace.TYPE_3CLR); header.setProfileColorSpace(ColorSpace.TYPE_XYZ); // Create CLUTs here. :-) setData(icSigCopyrightTag, makeTextTag(copyrightNotice)); setData(icSigProfileDescriptionTag, makeDescTag("Photo YCC")); this.profileID = ColorSpace.CS_PYCC; }} // class ICC_Profile
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -