質問
RGBとCMYKの間の変換を計算するためのソリューションを実装しようとしています。その逆も同様です。これが私がこれまでに持っているものです:
public static int[] rgbToCmyk(int red, int green, int blue)
{
int black = Math.min(Math.min(255 - red, 255 - green), 255 - blue);
if (black!=255) {
int cyan = (255-red-black)/(255-black);
int magenta = (255-green-black)/(255-black);
int yellow = (255-blue-black)/(255-black);
return new int[] {cyan,magenta,yellow,black};
} else {
int cyan = 255 - red;
int magenta = 255 - green;
int yellow = 255 - blue;
return new int[] {cyan,magenta,yellow,black};
}
}
public static int[] cmykToRgb(int cyan, int magenta, int yellow, int black)
{
if (black!=255) {
int R = ((255-cyan) * (255-black)) / 255;
int G = ((255-magenta) * (255-black)) / 255;
int B = ((255-yellow) * (255-black)) / 255;
return new int[] {R,G,B};
} else {
int R = 255 - cyan;
int G = 255 - magenta;
int B = 255 - yellow;
return new int[] {R,G,B};
}
}
解決
Lea Verouが言ったように、RGBからCMYKにマッピングするアルゴリズムがないため、カラースペース情報を使用する必要があります。 Adobeには、ダウンロード可能なICCカラープロファイルがいくつかあります1, 、しかし、彼らがどのようにライセンスされているかはわかりません。
カラープロファイルを作成したら、次のようなものがジョブを行います。
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.IOException;
import java.util.Arrays;
public class ColorConv {
final static String pathToCMYKProfile = "C:\\UncoatedFOGRA29.icc";
public static float[] rgbToCmyk(float... rgb) throws IOException {
if (rgb.length != 3) {
throw new IllegalArgumentException();
}
ColorSpace instance = new ICC_ColorSpace(ICC_Profile.getInstance(pathToCMYKProfile));
float[] fromRGB = instance.fromRGB(rgb);
return fromRGB;
}
public static float[] cmykToRgb(float... cmyk) throws IOException {
if (cmyk.length != 4) {
throw new IllegalArgumentException();
}
ColorSpace instance = new ICC_ColorSpace(ICC_Profile.getInstance(pathToCMYKProfile));
float[] fromRGB = instance.toRGB(cmyk);
return fromRGB;
}
public static void main(String... args) {
try {
float[] rgbToCmyk = rgbToCmyk(1.0f, 1.0f, 1.0f);
System.out.println(Arrays.toString(rgbToCmyk));
System.out.println(Arrays.toString(cmykToRgb(rgbToCmyk[0], rgbToCmyk[1], rgbToCmyk[2], rgbToCmyk[3])));
} catch (IOException e) {
e.printStackTrace();
}
}
}
他のヒント
値をRGBからCMYKに正確に変換するには、Photoshopのように、ICCカラープロファイルを使用する必要があります。インターウェブ(上記のような)にあるすべての単純なアルゴリズムソリューション(上記のようなものと同様)は、CMYKカラー域の外側にある色を生成します(たとえば、CMYK(100、0、0、0)をRGBに変換します(0) 、255、255)RGB(0、255、255)をCMYKで再現できないため、明らかに間違っています)。を調べます java.awt.color.icc_colorspace と java.awt.color.icc_profile ICCカラープロファイルを使用して色を変換するためのクラス。カラープロファイル自体については、Adobeはそれらを無料で配布します。
それを行うためのより良い方法:
try {
// The "from" CMYK colorspace
ColorSpace cmykColorspace = new ICC_ColorSpace(ICC_Profile.getInstance("icc/CoatedFOGRA27.icc"));
// The "to" RGB colorspace
ColorSpace rgbColorspace = new ICC_ColorSpace(ICC_Profile.getInstance("icc/AdobeRGB1998.icc"));
// Bring in to CIEXYZ colorspace (refer to Java documentation: http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/color/ColorSpace.html)
float[] ciexyz = cmykColorspace.toCIEXYZ(cmyk);
float[] thisColorspace = rgbColorspace.fromCIEXYZ(ciexyz);
float[] rgb = thisColorspace;
Color c = new Color(rgb[0], rgb[1], rgb[2]);
// Format RGB as Hex and return
return String.format("#%06x", c.getRGB() & 0xFFFFFF);
} catch (IOException e) { e.printStackTrace(); }
正しく表示するには、CMYK画像を含める必要があります カラースペース情報 ICCプロファイルとして。したがって、最良の方法は、で簡単に抽出できるICCプロファイルを使用することです サンセラン:
ICC_Profile iccProfile = Sanselan.getICCProfile(new File("filename.jpg"));
ColorSpace cs = new ICC_ColorSpace(iccProfile);
画像にICCプロファイルが添付されていない場合、私は使用します アドビプロファイル デフォルトとして。
問題は、ImageIOを使用してJPEGファイルをカスタムカラースペースでロードできないことです。例外をスローできないため、そのような色の空間やsthingをサポートしていないと不平を言っています。ハンセットあなたはラスターを使用する必要があります:
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new ByteArrayInputStream(data));
Raster srcRaster = decoder.decodeAsRaster();
BufferedImage result = new BufferedImage(srcRaster.getWidth(), srcRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster resultRaster = result.getRaster();
ColorConvertOp cmykToRgb = new ColorConvertOp(cs, result.getColorModel().getColorSpace(), null);
cmykToRgb.filter(srcRaster, resultRaster);
その後、使用できます result
必要な場所では、色が変換されます。
しかし実際には、何らかの形で逆の色の値を備えたいくつかの画像(カメラで撮影され、Photoshopで処理された)に出くわしたので、結果の画像は常に反転し、再び明るすぎた後でさえ、それらはあまりにも明るくなりました。正確に使用するとき(ピクセル値を反転する必要がある場合)を確認する方法はまだわかりませんが、これらの値を修正し、ピクセルでカラーピクセルを変換するアルゴリズムがあります。
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new ByteArrayInputStream(data));
Raster srcRaster = decoder.decodeAsRaster();
BufferedImage ret = new BufferedImage(srcRaster.getWidth(), srcRaster.getHeight(), BufferedImage.TYPE_INT_RGB);
WritableRaster resultRaster = ret.getRaster();
for (int x = srcRaster.getMinX(); x < srcRaster.getWidth(); ++x)
for (int y = srcRaster.getMinY(); y < srcRaster.getHeight(); ++y) {
float[] p = srcRaster.getPixel(x, y, (float[])null);
for (int i = 0; i < p.length; ++i)
p[i] = 1 - p[i] / 255f;
p = cs.toRGB(p);
for (int i = 0; i < p.length; ++i)
p[i] = p[i] * 255f;
resultRaster.setPixel(x, y, p);
}
RasteropまたはColorConvertopを使用して会話をより効率的にすることができると確信していますが、これで十分でした。
真剣に、これらの単純化されたCMYKからRGB変換アルゴリズムを使用する必要はありません。これは、画像に埋め込まれている、またはAdobeから無料で利用できるICCプロファイルを使用できるためです。結果の画像は、完璧ではない場合は(埋め込みプロファイルを使用して)見栄えが良くなります。
public static String makeCMYKString(int color) {
double red = Color.red(color);
double green = Color.green(color);
double blue = Color.blue(color);
double red1 = red / 255;
double green1 = green / 255;
double blue1 = blue / 255;
double max = (Math.max(Math.max(red1, green1), blue1));
double K = 1 - max;
double C = (1 - red1 - K) / (1 - K);
double M = (1 - green1 - K) / (1 - K);
double Y = (1 - blue1 - K) / (1 - K);
double CMYK[] = {C, M, Y, K};
String cmyk = "CMYK = (" + Math.round(C * 100) + " , " + Math.round(M * 100) + " , " + Math.round(Y * 100) + " , " + Math.round(K * 100) + ")";
return cmyk;
}
ここ あなたと同じ質問です
これがそのページのコピー/パスタです:
/** CMYK to RGB conversion */
/* Adobe PhotoShop algorithm */
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;
/* GNU Ghostscript algorithm -- this is better*/
int colors = 255 - black;
rgb[0] = colors * (255 - cyan)/255;
rgb[1] = colors * (255 - magenta)/255;
rgb[2] = colors * (255 - yellow)/255;
これが私のやり方です。 RGBの色を元の色から再変換したことに留意してください。
public static String getCMYK(int c){
float computedC = 0;
float computedM = 0;
float computedY = 0;
float computedK = 0;
int r = (c >> 16) & 0xFF;
int g = (c >> 8) & 0xFF;
int b = (c >> 0) & 0xFF;
// BLACK
if (r==0 && g==0 && b==0) {
computedK = 1;
return "0 0 0 100";
}
computedC = 1 - (r/255f);
computedM = 1 - (g/255f);
computedY = 1 - (b/255f);
float minCMY = Math.min(computedC,Math.min(computedM,computedY));
if (1 - minCMY != 0){
computedC = (computedC - minCMY) / (1 - minCMY) ;
computedM = (computedM - minCMY) / (1 - minCMY) ;
computedY = (computedY - minCMY) / (1 - minCMY) ;
}
computedK = minCMY;
return (int)(computedC*100f) + " " + (int)(computedM*100f) + " " + (int)(computedY*100f) + " " + (int)(computedK*100f);
}