/*
* 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.util.Library;
import java.awt.*;
import java.util.Hashtable;
/**
* Device CMYK colour space definitions. The primary purpose of this colour
* space is to convert cymk colours to rgb. No ICC profile is used in this
* process and the generated rgb colour is just and approximation.
*/
public class DeviceCMYK extends PColorSpace {
DeviceCMYK(Library l, Hashtable h) {
super(l, h);
}
public int getNumComponents() {
return 4;
}
/**
* Converts a 4 component cmyk colour to rgb. With out a valid ICC colour
* profile this is just an approximation.
*
* @param f 4 component values of the cmyk, assumes compoents between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
public Color getColor(float[] f) {
return alternative2(f);
}
/**
* Ah yes the many possible ways to go from cmyk to rgb. Everybody has
* an opinion but no one has the solution that is 100%
*/
/**
* @param f 4 component values of the cmyk, assumes compoents between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
private static Color alternative1(float[] f) {
float c = f[3];
float m = f[2];
float y = f[1];
float k = f[0];
float r = 1.0f - Math.min(1.0f, c + k);
float g = 1.0f - Math.min(1.0f, m + k);
float b = 1.0f - Math.min(1.0f, y + k);
return new Color(r, g, b);
}
/**
* @param f 4 component values of the cmyk, assumes components between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
private static Color alternative3(float[] f) {
float c = f[3];
float m = f[2];
float y = f[1];
float k = f[0];
float r = 1.0f - Math.min(1.0f, (c * (1 - k)) + k);
float g = 1.0f - Math.min(1.0f, (m * (1 - k)) + k);
float b = 1.0f - Math.min(1.0f, (y * (1 - k)) + k);
return new Color(r, g, b);
}
/**
* Auto cad color model
* var R=Math.round((1-C)*(1-K)*255);
* var B=Math.round((1-Y)*(1-K)*255);
* var G=Math.round((1-M)*(1-K)*255);
*
* @param f 4 component values of the cmyk, assumes compoents between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
private static Color getAutoCadColor(float[] f) {
float c = f[3];
float m = f[2];
float y = f[1];
float k = f[0];
int red = Math.round((1.0f - c) * (1.0f - k) * 255);
int blue = Math.round((1.0f - y) * (1.0f - k) * 255);
int green = Math.round((1.0f - m) * (1.0f - k) * 255);
return new Color(red, green, blue);
}
/**
* GNU Ghost Script algorithm or so they say.
* <p/>
* rgb[0] = colors * (255 - cyan)/255;
* rgb[1] = colors * (255 - magenta)/255;
* rgb[2] = colors * (255 - yellow)/255;
*
* @param f 4 component values of the cmyk, assumes compoents between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
private static Color getGhostColor(float[] f) {
int cyan = (int) (f[3] * 255);
int magenta = (int) (f[2] * 255);
int yellow = (int) (f[1] * 255);
int black = (int) (f[0] * 255);
float colors = 255 - black;
float[] rgb = new float[3];
rgb[0] = colors * (255 - cyan) / 255;
rgb[1] = colors * (255 - magenta) / 255;
rgb[2] = colors * (255 - yellow) / 255;
return new Color((int) rgb[0], (int) rgb[1], (int) rgb[2]);
}
/**
* Adobe photo shop algorithm or so they say.
* <p/>
* cyan = Math.min(255, cyan + black); //black is from K
* magenta = Math.min(255, magenta + black);
* yellow = Math.min(255, yellow + black);
* rgb[0] = 255 - cyan;
* rgb[1] = 255 - magenta;
* rgb[2] = 255 - yellow;
*
* @param f 4 component values of the cmyk, assumes compoents between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
private static Color getAdobeColor(float[] f) {
int cyan = (int) (f[3] * 255);
int magenta = (int) (f[2] * 255);
int yellow = (int) (f[1] * 255);
int black = (int) (f[0] * 255);
cyan = Math.min(255, cyan + black); //black is from K
magenta = Math.min(255, magenta + black);
yellow = Math.min(255, yellow + black);
int[] rgb = new int[3];
rgb[0] = 255 - cyan;
rgb[1] = 255 - magenta;
rgb[2] = 255 - yellow;
return new Color(rgb[0], rgb[1], rgb[2]);
}
/**
* Current runner for conversion that looks closest to acrobat.
* The algorithm is a little expensive but it does the best approximation.
*
* @param f 4 component values of the cmyk, assumes compoents between
* 0.0 and 1.0
* @return valid rgb colour object.
*/
private static Color alternative2(float[] f) {
float inCyan = f[3];
float inMagenta = f[2];
float inYellow = f[1];
float inBlack = f[0];
double c, m, y, aw, ac, am, ay, ar, ag, ab;
c = Math.min(1.0, inCyan + inBlack);
m = Math.min(1.0, inMagenta + inBlack);
y = Math.min(1.0, inYellow + inBlack);
aw = (1 - c) * (1 - m) * (1 - y);
ac = c * (1 - m) * (1 - y);
am = (1 - c) * m * (1 - y);
ay = (1 - c) * (1 - m) * y;
ar = (1 - c) * m * y;
ag = c * (1 - m) * y;
ab = c * m * (1 - y);
float outRed = (float) (aw + 0.9137 * am + 0.9961 * ay + 0.9882 * ar);
float outGreen = (float) (aw + 0.6196 * ac + ay + 0.5176 * ag);
float outBlue = (float) (aw + 0.7804 * ac + 0.5412 * am + 0.0667 * ar + 0.2118 * ag + 0.4863 * ab);
return new Color(outRed, outGreen, outBlue);
}
}