Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id: NamedColorProfileParser.java 1681108 2015-05-22 13:26:12Z ssteiner $ */
package org.apache.xmlgraphics.java2d.color.profile;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import org.apache.xmlgraphics.java2d.color.CIELabColorSpace;
import org.apache.xmlgraphics.java2d.color.ColorSpaces;
import org.apache.xmlgraphics.java2d.color.NamedColorSpace;
import org.apache.xmlgraphics.java2d.color.RenderingIntent;
/**
* This class is a parser for ICC named color profiles. It uses Java's {@link ICC_Profile} class
* for parsing the basic structure but adds functionality to parse certain profile tags.
*/
public class NamedColorProfileParser {
private static final int MLUC = 0x6D6C7563; //'mluc'
private static final int NCL2 = 0x6E636C32; //'ncl2'
/**
* Indicates whether the profile is a named color profile.
* @param profile the color profile
* @return true if the profile is a named color profile, false otherwise
*/
public static boolean isNamedColorProfile(ICC_Profile profile) {
return profile.getProfileClass() == ICC_Profile.CLASS_NAMEDCOLOR;
}
/**
* Parses a named color profile (NCP).
* @param profile the profile to analyze
* @param profileName Optional profile name associated with this color profile
* @param profileURI Optional profile URI associated with this color profile
* @return an object representing the parsed NCP
* @throws IOException if an I/O error occurs
*/
public NamedColorProfile parseProfile(ICC_Profile profile,
String profileName, String profileURI) throws IOException {
if (!isNamedColorProfile(profile)) {
throw new IllegalArgumentException("Given profile is not a named color profile (NCP)");
}
String profileDescription = getProfileDescription(profile);
String copyright = getCopyright(profile);
RenderingIntent intent = getRenderingIntent(profile);
NamedColorSpace[] ncs = readNamedColors(profile, profileName, profileURI);
return new NamedColorProfile(profileDescription, copyright, ncs, intent);
}
/**
* Parses a named color profile (NCP).
* @param profile the profile to analyze
* @return an object representing the parsed NCP
* @throws IOException if an I/O error occurs
*/
public NamedColorProfile parseProfile(ICC_Profile profile) throws IOException {
return parseProfile(profile, null, null);
}
private String getProfileDescription(ICC_Profile profile) throws IOException {
byte[] tag = profile.getData(ICC_Profile.icSigProfileDescriptionTag);
return readSimpleString(tag);
}
private String getCopyright(ICC_Profile profile) throws IOException {
byte[] tag = profile.getData(ICC_Profile.icSigCopyrightTag);
return readSimpleString(tag);
}
private RenderingIntent getRenderingIntent(ICC_Profile profile) throws IOException {
byte[] hdr = profile.getData(ICC_Profile.icSigHead);
int value = hdr[ICC_Profile.icHdrRenderingIntent];
return RenderingIntent.fromICCValue(value);
}
private NamedColorSpace[] readNamedColors(ICC_Profile profile,
String profileName, String profileURI) throws IOException {
byte[] tag = profile.getData(ICC_Profile.icSigNamedColor2Tag);
DataInput din = new DataInputStream(new ByteArrayInputStream(tag));
int sig = din.readInt();
if (sig != NCL2) {
throw new UnsupportedOperationException("Unsupported structure type: "
+ toSignatureString(sig) + ". Expected " + toSignatureString(NCL2));
}
din.skipBytes(8);
int numColors = din.readInt();
NamedColorSpace[] result = new NamedColorSpace[numColors];
int numDeviceCoord = din.readInt();
String prefix = readAscii(din, 32);
String suffix = readAscii(din, 32);
for (int i = 0; i < numColors; i++) {
String name = prefix + readAscii(din, 32) + suffix;
int[] pcs = readUInt16Array(din, 3);
float[] colorvalue = new float[3];
for (int j = 0; j < pcs.length; j++) {
colorvalue[j] = ((float)pcs[j]) / 0x8000;
}
//device coordinates are ignored for now
/*int[] deviceCoord =*/ readUInt16Array(din, numDeviceCoord);
switch (profile.getPCSType()) {
case ColorSpace.TYPE_XYZ:
result[i] = new NamedColorSpace(name, colorvalue, profileName, profileURI);
break;
case ColorSpace.TYPE_Lab:
//Not sure if this always D50 here,
//but the illuminant in the header is fixed to D50.
CIELabColorSpace labCS = ColorSpaces.getCIELabColorSpaceD50();
result[i] = new NamedColorSpace(name, labCS.toColor(colorvalue, 1.0f),
profileName, profileURI);
break;
default:
throw new UnsupportedOperationException(
"PCS type is not supported: " + profile.getPCSType());
}
}
return result;
}
private int[] readUInt16Array(DataInput din, int count) throws IOException {
if (count == 0) {
return new int[0];
}
int[] result = new int[count];
for (int i = 0; i < count; i++) {
int v = din.readUnsignedShort();
result[i] = v;
}
return result;
}
private String readAscii(DataInput in, int maxLength) throws IOException {
byte[] data = new byte[maxLength];
in.readFully(data);
String result = new String(data, "US-ASCII");
int idx = result.indexOf('\0');
if (idx >= 0) {
result = result.substring(0, idx);
}
return result;
}
private String readSimpleString(byte[] tag) throws IOException {
DataInput din = new DataInputStream(new ByteArrayInputStream(tag));
int sig = din.readInt();
if (sig == MLUC) {
return readMLUC(din);
} else {
return null; //Unsupported tag structure type
}
}
private String readMLUC(DataInput din) throws IOException {
din.skipBytes(16);
int firstLength = din.readInt();
int firstOffset = din.readInt();
int offset = 28;
din.skipBytes(firstOffset - offset);
byte[] utf16 = new byte[firstLength];
din.readFully(utf16);
return new String(utf16, "UTF-16BE");
}
private String toSignatureString(int sig) {
StringBuffer sb = new StringBuffer();
sb.append((char)(sig >> 24 & 0xFF));
sb.append((char)(sig >> 16 & 0xFF));
sb.append((char)(sig >> 8 & 0xFF));
sb.append((char)(sig & 0xFF));
return sb.toString();
}
}