/*
* Copyright 2006-2012 ICEsoft Technologies Inc.
*
* Licensed 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.
*/
package org.icepdf.core.pobjects.graphics;
import org.icepdf.core.io.SeekableInput;
import org.icepdf.core.pobjects.Stream;
import org.icepdf.core.util.Library;
import org.icepdf.core.util.Utils;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* put your documentation comment here
*/
public class ICCBased extends PColorSpace {
private static final Logger logger =
Logger.getLogger(ICCBased.class.toString());
int numcomp;
PColorSpace alternate;
Stream stream;
ColorSpace colorSpace;
private float[] lastInput;
private Color lastOutput;
/**
* @param l
* @param h
*/
public ICCBased(Library l, Stream h) {
super(l, h.getEntries());
numcomp = h.getInt("N");
switch (numcomp) {
case 1:
alternate = new DeviceGray(l, null);
break;
case 3:
alternate = new DeviceRGB(l, null);
break;
case 4:
alternate = new DeviceCMYK(l, null);
break;
}
stream = h;
}
/**
*
*/
public synchronized void init() {
if (inited) {
return;
}
inited = true;
InputStream in = null;
try {
stream.init();
in = stream.getInputStreamForDecodedStreamBytes();
if (logger.isLoggable(Level.FINEST)) {
String content;
if (in instanceof SeekableInput) {
content = Utils.getContentFromSeekableInput((SeekableInput) in, false);
} else {
InputStream[] inArray = new InputStream[]{in};
content = Utils.getContentAndReplaceInputStream(inArray, false);
in = inArray[0];
}
logger.finest("Content = " + content);
}
if (in != null) {
ICC_Profile profile = ICC_Profile.getInstance(in);
colorSpace = new ICC_ColorSpace(profile);
}
} catch (Exception e) {
logger.log(Level.FINE, "Error Processing ICCBased Colour Profile", e);
}
finally {
try {
if (in != null) in.close();
}
catch (IOException e) {
}
}
}
/**
* Get the alternative colour specified by the N dictionary entry. DeviceGray,
* DeviceRGB, or DeviceCMYK, depending on whether the value of N is 1, 3
* or 4, respectively.
*
* @return PDF colour space represented by the N (number of components)key.
*/
public PColorSpace getAlternate() {
return alternate;
}
/**
* @param f
* @return
*/
public Color getColor(float[] f) {
init();
if (colorSpace != null) {
try {
synchronized (this) {
// We cache the previous inputs and output, since images
// tend to have long runs of the same color
if (lastOutput != null && lastInput != null &&
f != null && lastInput.length == f.length) {
boolean matches = true;
int num = lastInput.length;
for (int i = num - 1; i >= 0; i--) {
if (f[i] != lastInput[i]) {
matches = false;
break;
}
}
if (matches)
return lastOutput;
}
int n = colorSpace.getNumComponents();
// Get the reverse of f, and only take n values
// Might as well limit the bounds while we're at it
float[] fvalue = new float[n];
int toCopy = n;
int fLength = f.length;
if (fLength < toCopy) {
toCopy = fLength;
}
for (int i = 0; i < toCopy; i++) {
float curr = f[fLength - 1 - i];
if (curr < 0.0f)
curr = 0.0f;
else if (curr > 1.0f)
curr = 1.0f;
fvalue[i] = curr;
}
float[] frgbvalue = colorSpace.toRGB(fvalue);
int value = (0xFF000000) |
((((int) (frgbvalue[0] * 255)) & 0xFF) << 16) |
((((int) (frgbvalue[1] * 255)) & 0xFF) << 8) |
((((int) (frgbvalue[2] * 255)) & 0xFF));
Color c = new Color(value);
// Update the cache
if (lastInput == null || lastInput.length != fLength)
lastInput = new float[fLength];
for (int i = fLength - 1; i >= 0; i--)
lastInput[i] = f[i];
lastOutput = c;
return c;
}
/*
Color c = new Color( colorSpace,reverse(f), 1 );
return new Color(
ColorSpace_CS_sRGB,
c.getRGBComponents(null),
1);
*/
} catch (Exception e) {
logger.log(Level.FINE, "Error getting ICCBased colour", e);
}
}
return alternate.getColor(f);
}
public ColorSpace getColorSpace() {
return colorSpace;
}
/**
* Gets the number of components specified by the N entry.
*
* @return number of colour components in color space
*/
public int getNumComponents() {
return numcomp;
}
}