天天看點

Java 利用 ICC 色彩空間 color space profile 實作 RGB 和 CMYK 顔色的互相轉換

Java 利用 ICC 色彩空間 color space profile 實作 RGB 和 CMYK 顔色的互相轉換

ICC_ColorSpace 支援相應的色彩空間标準,有日本、歐洲和美國标準,在其中還有 Web 和 Page 等多種出版物所使用的色彩空間标準,這裡以一部分印刷行業中使用的 Japan Coated 為例實作 RGB 和 CMYK 互換,至于其他工業标準的 ICC  Profile 則在 C:/Windows/System32/spool/drivers/color/ 目錄内,各位可根據自己的需要選擇相應的 ICC。

package color;

import java.awt.Color;
import java.awt.color.ColorSpace;
import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;

public class ColorConvert
{
  final static String strPathCMYKProfile = "C:/Windows/System32/spool/drivers/color/JapanColor2001Coated.icc";

  public static float[] rgb2cmyk(float... rgb) throws IOException
  {
    if (rgb.length != 3)
    {
      throw new IllegalArgumentException();
    }

    ColorSpace instance = new ICC_ColorSpace(ICC_Profile.getInstance(strPathCMYKProfile));
    float[] cmyk = instance.fromRGB(rgb);
    return cmyk;
  }

  public static float[] cmyk2rgb(float... cmyk) throws IOException
  {
    if (cmyk.length != 4)
    {
      throw new IllegalArgumentException();
    }

    ColorSpace instance = new ICC_ColorSpace(ICC_Profile.getInstance(strPathCMYKProfile));
    float[] fromRGB = instance.toRGB(cmyk);
    return fromRGB;
  }

  public static void main(String[] args)
  {
    try
    {

      // 以 color 對象輸入
      Color color = new Color(45, 45, 45);
      // float rgb1[] = { (float) 45 / 255, (float) 45 / 255, (float) 45 / 255 };
      float[] cmyk = rgb2cmyk(color.getRGBColorComponents(null));
      // [0.79394215, 0.7535668, 0.73749906, 0.50597394]
      // float[] cmyk = rgb2cmyk(rgb1);

      // 就結果而言,Color 對象輸入得到的更精确一些。
      System.out.println(Arrays.toString(cmyk));
      System.out.println(Arrays.toString(cmyk2rgb(cmyk[0], cmyk[1], cmyk[2], cmyk[3])));

      // 以 array float 輸入
      float rgb[] = { 45f / 255f, 45f / 255f, 45f / 255f };
      float[] cmyk2 = rgb2cmyk(rgb);

      System.out.println(Arrays.toString(cmyk2));
      System.out.println(Arrays.toString(cmyk2rgb(cmyk2[0], cmyk2[1], cmyk2[2], cmyk2[3])));

      // 四舍五入取整取 cmyk
      // BigDecimal dec = new BigDecimal(cmyk[0] * 100).setScale(0, BigDecimal.ROUND_HALF_UP);
      // cmyk[0] = (int) dec.floatValue();
      //
      // dec = new BigDecimal(cmyk[1] * 100).setScale(0, BigDecimal.ROUND_HALF_UP);
      // cmyk[1] = (int) dec.floatValue();
      //
      // dec = new BigDecimal(cmyk[2] * 100).setScale(0, BigDecimal.ROUND_HALF_UP);
      // cmyk[2] = (int) dec.floatValue();
      //
      // dec = new BigDecimal(cmyk[3] * 100).setScale(0, BigDecimal.ROUND_HALF_UP);
      // cmyk[3] = (int) dec.floatValue();

    }
    catch (IOException e)
    {
      e.printStackTrace();
    }

  }

}
           

色彩輸入可以使用 Color 對象,也可以使用 float[],Color 對象也是需要轉換得到 float[] 才真正進入函數進行操作,而比如 Photoshop 内的 RGB 值是 3 個 0~255 的整數,将3個RGB值分别除以 255 就得到了 float[] 内所需的參數,得到的換算結果則是一個小于等于1的浮點數,要得到類似 Photoshop 内 CMYK 的兩位數,乘以 100 即可。

Java 利用 ICC 色彩空間 color space profile 實作 RGB 和 CMYK 顔色的互相轉換

因傳參的精确度不一樣,得到的結果也将有誤差,而用 Color 對象,會更接近 Photoshop 的值,當然 Photoshop 也應當選擇對應的色彩空間後再進行比較。