2011-02-01 4 views
10

RGB와 CMYK 간의 변환 계산 솔루션을 구현하려고합니다. 그 반대의 경우도 마찬가지입니다. 해당 페이지의 복사/파스타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}; 
     } 
    } 
+0

모두가 항상 빠른 대답을 원하며, 쓸모가 없습니다. – Eric

+0

이 솔루션은 어떻게 당신을 위해 효과를 냈습니까? ICC_Colorspace가 없으면 그 일에 착수하려고 시도한 것을 볼 수 있었습니까? – TacB0sS

답변

6

Lea Verou는 RGB에서 CMYK로 매핑하는 알고리즘이 없으므로 색상 공간 정보를 사용해야한다고 말했습니다. Adobe는 다운로드 용 1에 사용할 수있는 몇 가지 ICC 색상 프로파일을 가지고 있지만 라이센스가 어떻게되어 있는지 확실하지 않습니다.

당신은 일을 할 것이다 다음과 같은 색상 프로파일 뭔가가 있으면 : 위해

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(); 
     } 
    } 
} 
-1

Here은 당신 여기

에 동일한 질문입니다 :

/** 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; 
+8

-1 :이 변환 공식의 결과가 너무 좋지 않아 결과가 거의 쓸모가 없습니다. 그들이 그물에 온통 게시된다는 사실은 더 나아지지 않습니다. 그들을 더 많이 퍼 뜨리지 마세요. – Codo

4

정확하게에 RGB에서 값을 변환하려면 여기에 지금까지 무엇을 가지고 CMYK 및 그 반대로, 포토샵에서와 마찬가지로 ICC 색상 프로파일을 사용해야합니다. 인터 웹에서 찾을 수있는 간단한 알고리즘 솔루션 (예 : 위에 게시 된 것과 같은)은 부적절하고 CMYK 색상 영역 외부의 색상을 생성합니다 (예 : CMYK (100, 0, 0, 0)을 rgb , 255, 255) 이것은 분명히 rgb (0, 255, 255)가 CMYK로 재현 될 수 없으므로 잘못되었습니다. ICC 색상 프로파일을 사용하여 색상을 변환하는 경우 java.awt.color.ICC_ColorSpacejava.awt.color.ICC_Profile 클래스를 살펴보십시오. Adobe는 색상 프로파일 파일 자체를 무료로 배포합니다.

+0

JDK 7의 ICC 클래스입니까? Java 6 doco에서 이들에 대한 참조를 찾을 수 없습니다. –

+0

답변 됨 링크로 편집 됨. 내가 아는 한, 그들은 새로운 것이 아니며 (2 년 전에 사용 했었습니다) 어떤 외부 라이브러리에서는 내장되어 있습니다. –

0

가 제대로 CMYK 이미지를 ICC 프로파일로 color space information을 포함해야 표시 할 수 있습니다. 경우

ICC_Profile iccProfile = Sanselan.getICCProfile(new File("filename.jpg")); 
ColorSpace cs = new ICC_ColorSpace(iccProfile);  

이미지에 첨부 된 ICC 프로파일이 없다, 나는 기본적으로 Adobe profiles을 사용 : 그래서 가장 좋은 방법은 쉽게 Sanselan로 추출 할 수있는 ICC 프로파일을 사용하는 것입니다.

이제 문제는 ImageIO를 사용하여 사용자 정의 색 공간으로 JPEG 파일을로드 할 수 없다는 것입니다. 일부 색 공간 또는 그와 같은 색조를 지원하지 않는다고 예외를 throw하지 못하기 때문입니다. 당신이 필요로하는 곳

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를 사용할 수 있으며 변환 된 색상이됩니다 Hense 당신은 래스터 작업을해야합니다.

실제로 이미지를 항상 거꾸로 뒤집은 후에도 이미지가 너무 밝아서 색상 값이 반전 된 일부 이미지 (카메라로 찍은 다음 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); 
    } 

: 난 아직 아무 생각이 없지만 정확히 어떻게 (I 픽셀 값을 반전해야하는 경우), 나는이 값을 보정하는 알고리즘을 사용하고 픽셀에 의해 컬러 픽셀을 변환 할 때 알아보십시오 꽤 확실한 RasterOp 또는 ColorConvertOp를 사용하여 대화를보다 효율적으로 만들 수는 있지만 이것이 나를 위해 충분했습니다.

이미지에 삽입되거나 Adobe에서 무료로 제공되는 ICC 프로파일을 사용할 수 있으므로 이러한 단순화 된 CMYK-RGB 변환 알고리즘을 사용할 필요가 없습니다. 완성 된 이미지가 아닌 경우 결과 이미지가 더 멋지게 보입니다 (포함 된 프로필 포함).

3

더 좋은 방법은 그것을 할 수 있습니다 :

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(); } 
-1

가 여기 내 방법입니다. 원래 색상에서 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); 
} 
+0

여전히 "잘못된"색상 변환입니다. RGB 및 CMYK 값이 어떤 색인지 알지 못하면 변환 할 수 없습니다. 게시하기 전에 4 년간 답변 한 답변에 설명 된대로 ICC 프로파일로 작업해야합니다. –