| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.commons.imaging.color; |
| |
| import org.apache.commons.imaging.util.Debug; |
| |
| public abstract class ColorConversions |
| { |
| public static final ColorCieLab convertXYZtoCIELab(ColorXyz xyz) |
| { |
| return convertXYZtoCIELab(xyz.X, xyz.Y, xyz.Z); |
| } |
| |
| private static final double ref_X = 95.047; |
| private static final double ref_Y = 100.000; |
| private static final double ref_Z = 108.883; |
| |
| public static final ColorCieLab convertXYZtoCIELab(double X, double Y, double Z) |
| { |
| |
| double var_X = X / ref_X; //ref_X = 95.047 Observer= 2°, Illuminant= D65 |
| double var_Y = Y / ref_Y; //ref_Y = 100.000 |
| double var_Z = Z / ref_Z; //ref_Z = 108.883 |
| |
| if (var_X > 0.008856) |
| var_X = Math.pow(var_X, (1 / 3.0)); |
| else |
| var_X = (7.787 * var_X) + (16 / 116.0); |
| if (var_Y > 0.008856) |
| var_Y = Math.pow(var_Y, 1 / 3.0); |
| else |
| var_Y = (7.787 * var_Y) + (16 / 116.0); |
| if (var_Z > 0.008856) |
| var_Z = Math.pow(var_Z, 1 / 3.0); |
| else |
| var_Z = (7.787 * var_Z) + (16 / 116.0); |
| |
| double L = (116 * var_Y) - 16; |
| double a = 500 * (var_X - var_Y); |
| double b = 200 * (var_Y - var_Z); |
| return new ColorCieLab(L, a, b); |
| } |
| |
| public static final ColorXyz convertCIELabtoXYZ(ColorCieLab cielab) |
| { |
| return convertCIELabtoXYZ(cielab.L, cielab.a, cielab.b); |
| } |
| |
| public static final ColorXyz convertCIELabtoXYZ(double L, double a, double b) |
| { |
| double var_Y = (L + 16) / 116.0; |
| double var_X = a / 500 + var_Y; |
| double var_Z = var_Y - b / 200.0; |
| |
| if (Math.pow(var_Y, 3) > 0.008856) |
| var_Y = Math.pow(var_Y, 3); |
| else |
| var_Y = (var_Y - 16 / 116.0) / 7.787; |
| if (Math.pow(var_X, 3) > 0.008856) |
| var_X = Math.pow(var_X, 3); |
| else |
| var_X = (var_X - 16 / 116.0) / 7.787; |
| if (Math.pow(var_Z, 3) > 0.008856) |
| var_Z = Math.pow(var_Z, 3); |
| else |
| var_Z = (var_Z - 16 / 116.0) / 7.787; |
| |
| double X = ref_X * var_X; //ref_X = 95.047 Observer= 2°, Illuminant= D65 |
| double Y = ref_Y * var_Y; //ref_Y = 100.000 |
| double Z = ref_Z * var_Z; //ref_Z = 108.883 |
| |
| return new ColorXyz(X, Y, Z); |
| } |
| |
| public static final ColorHunterLab convertXYZtoHunterLab(ColorXyz xyz) |
| { |
| return convertXYZtoHunterLab(xyz.X, xyz.Y, xyz.Z); |
| } |
| |
| public static final ColorHunterLab convertXYZtoHunterLab(double X, |
| double Y, double Z) |
| { |
| double L = 10 * Math.sqrt(Y); |
| double a = 17.5 * (((1.02 * X) - Y) / Math.sqrt(Y)); |
| double b = 7 * ((Y - (0.847 * Z)) / Math.sqrt(Y)); |
| |
| return new ColorHunterLab(L, a, b); |
| } |
| |
| public static final ColorXyz convertHunterLabtoXYZ(ColorHunterLab cielab) |
| { |
| return convertHunterLabtoXYZ(cielab.L, cielab.a, cielab.b); |
| } |
| |
| public static final ColorXyz convertHunterLabtoXYZ(double L, double a, |
| double b) |
| { |
| double var_Y = L / 10; |
| double var_X = a / 17.5 * L / 10; |
| double var_Z = b / 7 * L / 10; |
| |
| double Y = Math.pow(var_Y, 2); |
| double X = (var_X + Y) / 1.02; |
| double Z = -(var_Z - Y) / 0.847; |
| |
| return new ColorXyz(X, Y, Z); |
| } |
| |
| public static final int convertXYZtoRGB(ColorXyz xyz) |
| { |
| return convertXYZtoRGB(xyz.X, xyz.Y, xyz.Z); |
| } |
| |
| public static final int convertXYZtoRGB(double X, double Y, double Z) |
| { |
| //Observer = 2°, Illuminant = D65 |
| double var_X = X / 100.0; //Where X = 0 ÷ 95.047 |
| double var_Y = Y / 100.0; //Where Y = 0 ÷ 100.000 |
| double var_Z = Z / 100.0; //Where Z = 0 ÷ 108.883 |
| |
| double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986; |
| double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415; |
| double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570; |
| |
| if (var_R > 0.0031308) |
| var_R = 1.055 * Math.pow(var_R, (1 / 2.4)) - 0.055; |
| else |
| var_R = 12.92 * var_R; |
| if (var_G > 0.0031308) |
| var_G = 1.055 * Math.pow(var_G, (1 / 2.4)) - 0.055; |
| else |
| var_G = 12.92 * var_G; |
| if (var_B > 0.0031308) |
| var_B = 1.055 * Math.pow(var_B, (1 / 2.4)) - 0.055; |
| else |
| var_B = 12.92 * var_B; |
| |
| double R = (var_R * 255); |
| double G = (var_G * 255); |
| double B = (var_B * 255); |
| |
| return convertRGBtoRGB(R, G, B); |
| } |
| |
| public static final ColorXyz convertRGBtoXYZ(int rgb) |
| { |
| int r = 0xff & (rgb >> 16); |
| int g = 0xff & (rgb >> 8); |
| int b = 0xff & (rgb >> 0); |
| |
| double var_R = r / 255.0; //Where R = 0 ÷ 255 |
| double var_G = g / 255.0; //Where G = 0 ÷ 255 |
| double var_B = b / 255.0; //Where B = 0 ÷ 255 |
| |
| if (var_R > 0.04045) |
| var_R = Math.pow((var_R + 0.055) / 1.055, 2.4); |
| else |
| var_R = var_R / 12.92; |
| if (var_G > 0.04045) |
| var_G = Math.pow((var_G + 0.055) / 1.055, 2.4); |
| else |
| var_G = var_G / 12.92; |
| if (var_B > 0.04045) |
| var_B = Math.pow((var_B + 0.055) / 1.055, 2.4); |
| else |
| var_B = var_B / 12.92; |
| |
| var_R = var_R * 100; |
| var_G = var_G * 100; |
| var_B = var_B * 100; |
| |
| // Observer. = 2°, Illuminant = D65 |
| double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805; |
| double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722; |
| double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505; |
| |
| return new ColorXyz(X, Y, Z); |
| } |
| |
| public static final ColorCmy convertRGBtoCMY(int rgb) |
| { |
| int R = 0xff & (rgb >> 16); |
| int G = 0xff & (rgb >> 8); |
| int B = 0xff & (rgb >> 0); |
| |
| // RGB values = 0 ÷ 255 |
| // CMY values = 0 ÷ 1 |
| |
| double C = 1 - (R / 255.0); |
| double M = 1 - (G / 255.0); |
| double Y = 1 - (B / 255.0); |
| |
| return new ColorCmy(C, M, Y); |
| } |
| |
| public static final int convertCMYtoRGB(ColorCmy cmy) |
| { |
| // From Ghostscript's gdevcdj.c: |
| // * Ghostscript: R = (1.0 - C) * (1.0 - K) |
| // * Adobe: R = 1.0 - min(1.0, C + K) |
| // and similarly for G and B. |
| // This is Ghostscript's formula with K = 0. |
| |
| // CMY values = 0 ÷ 1 |
| // RGB values = 0 ÷ 255 |
| |
| double R = (1 - cmy.C) * 255.0; |
| double G = (1 - cmy.M) * 255.0; |
| double B = (1 - cmy.Y) * 255.0; |
| |
| return convertRGBtoRGB(R, G, B); |
| } |
| |
| public static final ColorCmyk convertCMYtoCMYK(ColorCmy cmy) |
| { |
| // Where CMYK and CMY values = 0 ÷ 1 |
| |
| double C = cmy.C; |
| double M = cmy.M; |
| double Y = cmy.Y; |
| |
| double var_K = 1.0; |
| |
| if (C < var_K) |
| var_K = C; |
| if (M < var_K) |
| var_K = M; |
| if (Y < var_K) |
| var_K = Y; |
| if (var_K == 1) |
| { //Black |
| C = 0; |
| M = 0; |
| Y = 0; |
| } |
| else |
| { |
| C = (C - var_K) / (1 - var_K); |
| M = (M - var_K) / (1 - var_K); |
| Y = (Y - var_K) / (1 - var_K); |
| } |
| return new ColorCmyk(C, M, Y, var_K); |
| } |
| |
| public static final ColorCmy convertCMYKtoCMY(ColorCmyk cmyk) |
| { |
| return convertCMYKtoCMY(cmyk.C, cmyk.M, cmyk.Y, cmyk.K); |
| } |
| |
| public static final ColorCmy convertCMYKtoCMY(double C, double M, double Y, |
| double K) |
| { |
| // Where CMYK and CMY values = 0 ÷ 1 |
| |
| C = (C * (1 - K) + K); |
| M = (M * (1 - K) + K); |
| Y = (Y * (1 - K) + K); |
| |
| return new ColorCmy(C, M, Y); |
| } |
| |
| public static final int convertCMYKtoRGB(int c, int m, int y, int k) |
| // throws ImageReadException, IOException |
| { |
| double C = c / 255.0; |
| double M = m / 255.0; |
| double Y = y / 255.0; |
| double K = k / 255.0; |
| |
| return convertCMYtoRGB(convertCMYKtoCMY(C, M, Y, K)); |
| } |
| |
| public static final ColorHsl convertRGBtoHSL(int rgb) |
| { |
| |
| int R = 0xff & (rgb >> 16); |
| int G = 0xff & (rgb >> 8); |
| int B = 0xff & (rgb >> 0); |
| |
| double var_R = (R / 255.0); //Where RGB values = 0 ÷ 255 |
| double var_G = (G / 255.0); |
| double var_B = (B / 255.0); |
| |
| double var_Min = Math.min(var_R, Math.min(var_G, var_B)); //Min. value of RGB |
| double var_Max = Math.max(var_R, Math.max(var_G, var_B)); //Max. value of RGB |
| double del_Max = var_Max - var_Min; //Delta RGB value |
| |
| double L = (var_Max + var_Min) / 2.0; |
| |
| double H, S; |
| // Debug.debug("del_Max", del_Max); |
| if (del_Max == 0) //This is a gray, no chroma... |
| { |
| H = 0; //HSL results = 0 ÷ 1 |
| S = 0; |
| } |
| else |
| //Chromatic data... |
| { |
| // Debug.debug("L", L); |
| |
| if (L < 0.5) |
| S = del_Max / (var_Max + var_Min); |
| else |
| S = del_Max / (2 - var_Max - var_Min); |
| |
| // Debug.debug("S", S); |
| |
| double del_R = (((var_Max - var_R) / 6) + (del_Max / 2)) / del_Max; |
| double del_G = (((var_Max - var_G) / 6) + (del_Max / 2)) / del_Max; |
| double del_B = (((var_Max - var_B) / 6) + (del_Max / 2)) / del_Max; |
| |
| if (var_R == var_Max) |
| H = del_B - del_G; |
| else if (var_G == var_Max) |
| H = (1 / 3.0) + del_R - del_B; |
| else if (var_B == var_Max) |
| H = (2 / 3.0) + del_G - del_R; |
| else |
| { |
| Debug.debug("uh oh"); |
| H = 0; // cmc |
| } |
| |
| // Debug.debug("H1", H); |
| |
| if (H < 0) |
| H += 1; |
| if (H > 1) |
| H -= 1; |
| |
| // Debug.debug("H2", H); |
| } |
| |
| return new ColorHsl(H, S, L); |
| } |
| |
| public static int convertHSLtoRGB(ColorHsl hsl) |
| { |
| return convertHSLtoRGB(hsl.H, hsl.S, hsl.L); |
| } |
| |
| public static int convertHSLtoRGB(double H, double S, double L) |
| { |
| double R, G, B; |
| |
| if (S == 0) //HSL values = 0 ÷ 1 |
| { |
| R = L * 255; //RGB results = 0 ÷ 255 |
| G = L * 255; |
| B = L * 255; |
| } |
| else |
| { |
| double var_2; |
| |
| if (L < 0.5) |
| var_2 = L * (1 + S); |
| else |
| var_2 = (L + S) - (S * L); |
| |
| double var_1 = 2 * L - var_2; |
| |
| R = 255 * convertHuetoRGB(var_1, var_2, H + (1 / 3.0)); |
| G = 255 * convertHuetoRGB(var_1, var_2, H); |
| B = 255 * convertHuetoRGB(var_1, var_2, H - (1 / 3.0)); |
| } |
| |
| return convertRGBtoRGB(R, G, B); |
| } |
| |
| private static double convertHuetoRGB(double v1, double v2, double vH) //Function Hue_2_RGB |
| { |
| if (vH < 0) |
| vH += 1; |
| if (vH > 1) |
| vH -= 1; |
| if ((6 * vH) < 1) |
| return (v1 + (v2 - v1) * 6 * vH); |
| if ((2 * vH) < 1) |
| return (v2); |
| if ((3 * vH) < 2) |
| return (v1 + (v2 - v1) * ((2 / 3.0) - vH) * 6); |
| return (v1); |
| } |
| |
| public static final ColorHsv convertRGBtoHSV(int rgb) |
| { |
| int R = 0xff & (rgb >> 16); |
| int G = 0xff & (rgb >> 8); |
| int B = 0xff & (rgb >> 0); |
| |
| double var_R = (R / 255.0); //RGB values = 0 ÷ 255 |
| double var_G = (G / 255.0); |
| double var_B = (B / 255.0); |
| |
| double var_Min = Math.min(var_R, Math.min(var_G, var_B)); //Min. value of RGB |
| double var_Max = Math.max(var_R, Math.max(var_G, var_B)); //Max. value of RGB |
| double del_Max = var_Max - var_Min; //Delta RGB value |
| |
| double V = var_Max; |
| |
| double H, S; |
| if (del_Max == 0) //This is a gray, no chroma... |
| { |
| H = 0; //HSV results = 0 ÷ 1 |
| S = 0; |
| } |
| else |
| //Chromatic data... |
| { |
| S = del_Max / var_Max; |
| |
| double del_R = (((var_Max - var_R) / 6) + (del_Max / 2)) / del_Max; |
| double del_G = (((var_Max - var_G) / 6) + (del_Max / 2)) / del_Max; |
| double del_B = (((var_Max - var_B) / 6) + (del_Max / 2)) / del_Max; |
| |
| if (var_R == var_Max) |
| H = del_B - del_G; |
| else if (var_G == var_Max) |
| H = (1 / 3.0) + del_R - del_B; |
| else if (var_B == var_Max) |
| H = (2 / 3.0) + del_G - del_R; |
| else |
| { |
| Debug.debug("uh oh"); |
| H = 0; // cmc; |
| } |
| |
| if (H < 0) |
| H += 1; |
| if (H > 1) |
| H -= 1; |
| } |
| |
| return new ColorHsv(H, S, V); |
| } |
| |
| public static int convertHSVtoRGB(ColorHsv HSV) |
| { |
| return convertHSVtoRGB(HSV.H, HSV.S, HSV.V); |
| } |
| |
| public static int convertHSVtoRGB(double H, double S, double V) |
| { |
| double R, G, B; |
| |
| if (S == 0) //HSV values = 0 ÷ 1 |
| { |
| R = V * 255; |
| G = V * 255; |
| B = V * 255; |
| } |
| else |
| { |
| double var_h = H * 6; |
| if (var_h == 6) |
| var_h = 0; //H must be < 1 |
| double var_i = Math.floor(var_h); //Or ... var_i = floor( var_h ) |
| double var_1 = V * (1 - S); |
| double var_2 = V * (1 - S * (var_h - var_i)); |
| double var_3 = V * (1 - S * (1 - (var_h - var_i))); |
| |
| double var_r, var_g, var_b; |
| |
| if (var_i == 0) |
| { |
| var_r = V; |
| var_g = var_3; |
| var_b = var_1; |
| } |
| else if (var_i == 1) |
| { |
| var_r = var_2; |
| var_g = V; |
| var_b = var_1; |
| } |
| else if (var_i == 2) |
| { |
| var_r = var_1; |
| var_g = V; |
| var_b = var_3; |
| } |
| else if (var_i == 3) |
| { |
| var_r = var_1; |
| var_g = var_2; |
| var_b = V; |
| } |
| else if (var_i == 4) |
| { |
| var_r = var_3; |
| var_g = var_1; |
| var_b = V; |
| } |
| else |
| { |
| var_r = V; |
| var_g = var_1; |
| var_b = var_2; |
| } |
| |
| R = var_r * 255; //RGB results = 0 ÷ 255 |
| G = var_g * 255; |
| B = var_b * 255; |
| } |
| |
| return convertRGBtoRGB(R, G, B); |
| } |
| |
| public static final int convertCMYKtoRGB_Adobe(int sc, int sm, int sy, int sk) |
| // throws ImageReadException, IOException |
| { |
| int red = 255 - (sc + sk); |
| int green = 255 - (sm + sk); |
| int blue = 255 - (sy + sk); |
| |
| return convertRGBtoRGB(red, green, blue); |
| } |
| |
| private static double cube(double f) |
| { |
| return f * f * f; |
| } |
| |
| private static double square(double f) |
| { |
| return f * f; |
| } |
| |
| public static final int convertCIELabtoARGBTest(int cieL, int cieA, int cieB) |
| { |
| double X, Y, Z; |
| |
| { |
| |
| double var_Y = ((cieL * 100.0 / 255.0) + 16.0) / 116.0; |
| double var_X = cieA / 500.0 + var_Y; |
| double var_Z = var_Y - cieB / 200.0; |
| |
| double var_x_cube = cube(var_X); |
| double var_y_cube = cube(var_Y); |
| double var_z_cube = cube(var_Z); |
| |
| if (var_y_cube > 0.008856) |
| var_Y = var_y_cube; |
| else |
| var_Y = (var_Y - 16 / 116.0) / 7.787; |
| |
| if (var_x_cube > 0.008856) |
| var_X = var_x_cube; |
| else |
| var_X = (var_X - 16 / 116.0) / 7.787; |
| |
| if (var_z_cube > 0.008856) |
| var_Z = var_z_cube; |
| else |
| var_Z = (var_Z - 16 / 116.0) / 7.787; |
| |
| // double ref_X = 95.047; |
| // double ref_Y = 100.000; |
| // double ref_Z = 108.883; |
| |
| X = ref_X * var_X; //ref_X = 95.047 Observer= 2°, Illuminant= D65 |
| Y = ref_Y * var_Y; //ref_Y = 100.000 |
| Z = ref_Z * var_Z; //ref_Z = 108.883 |
| |
| } |
| |
| double R, G, B; |
| { |
| double var_X = X / 100; //X = From 0 to ref_X |
| double var_Y = Y / 100; //Y = From 0 to ref_Y |
| double var_Z = Z / 100; //Z = From 0 to ref_Y |
| |
| double var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986; |
| double var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415; |
| double var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570; |
| |
| if (var_R > 0.0031308) |
| var_R = 1.055 * Math.pow(var_R, (1 / 2.4)) - 0.055; |
| else |
| var_R = 12.92 * var_R; |
| if (var_G > 0.0031308) |
| var_G = 1.055 * Math.pow(var_G, (1 / 2.4)) - 0.055; |
| else |
| var_G = 12.92 * var_G; |
| |
| if (var_B > 0.0031308) |
| var_B = 1.055 * Math.pow(var_B, (1 / 2.4)) - 0.055; |
| else |
| var_B = 12.92 * var_B; |
| |
| R = (var_R * 255); |
| G = (var_G * 255); |
| B = (var_B * 255); |
| } |
| |
| return convertRGBtoRGB(R, G, B); |
| } |
| |
| private static final int convertRGBtoRGB(double R, double G, double B) |
| { |
| int red = (int) Math.round(R); |
| int green = (int) Math.round(G); |
| int blue = (int) Math.round(B); |
| |
| red = Math.min(255, Math.max(0, red)); |
| green = Math.min(255, Math.max(0, green)); |
| blue = Math.min(255, Math.max(0, blue)); |
| |
| int alpha = 0xff; |
| int rgb = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); |
| |
| return rgb; |
| } |
| |
| private static final int convertRGBtoRGB(int red, int green, int blue) |
| { |
| red = Math.min(255, Math.max(0, red)); |
| green = Math.min(255, Math.max(0, green)); |
| blue = Math.min(255, Math.max(0, blue)); |
| |
| int alpha = 0xff; |
| int rgb = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); |
| |
| return rgb; |
| } |
| |
| public static ColorCieLch convertCIELabtoCIELCH(ColorCieLab cielab) |
| { |
| return convertCIELabtoCIELCH(cielab.L, cielab.a, cielab.b); |
| } |
| |
| public static ColorCieLch convertCIELabtoCIELCH(double L, double a, double b) |
| { |
| double var_H = Math.atan2(b, a); //Quadrant by signs |
| |
| if (var_H > 0) |
| var_H = (var_H / Math.PI) * 180.0; |
| else |
| var_H = 360 - radian_2_degree(Math.abs(var_H)); |
| |
| // L = L; |
| double C = Math.sqrt(square(a) + square(b)); |
| double H = var_H; |
| |
| return new ColorCieLch(L, C, H); |
| } |
| |
| public static ColorCieLab convertCIELCHtoCIELab(ColorCieLch cielch) |
| { |
| return convertCIELCHtoCIELab(cielch.L, cielch.C, cielch.H); |
| } |
| |
| public static ColorCieLab convertCIELCHtoCIELab(double L, double C, double H) |
| { |
| // Where CIE-H° = 0 ÷ 360° |
| |
| // CIE-L* = CIE-L; |
| double a = Math.cos(degree_2_radian(H)) * C; |
| double b = Math.sin(degree_2_radian(H)) * C; |
| |
| return new ColorCieLab(L, a, b); |
| } |
| |
| public static double degree_2_radian(double degree) |
| { |
| return degree * Math.PI / 180.0; |
| } |
| |
| public static double radian_2_degree(double radian) |
| { |
| return radian * 180.0 / Math.PI; |
| } |
| |
| public static ColorCieLuv convertXYZtoCIELuv(ColorXyz xyz) |
| { |
| return convertXYZtoCIELuv(xyz.X, xyz.Y, xyz.Z); |
| } |
| |
| public static ColorCieLuv convertXYZtoCIELuv(double X, double Y, double Z) |
| { |
| // problems here with div by zero |
| |
| double var_U = (4 * X) / (X + (15 * Y) + (3 * Z)); |
| double var_V = (9 * Y) / (X + (15 * Y) + (3 * Z)); |
| |
| // Debug.debug("var_U", var_U); |
| // Debug.debug("var_V", var_V); |
| |
| double var_Y = Y / 100.0; |
| // Debug.debug("var_Y", var_Y); |
| |
| if (var_Y > 0.008856) |
| var_Y = Math.pow(var_Y, (1 / 3.0)); |
| else |
| var_Y = (7.787 * var_Y) + (16 / 116.0); |
| |
| double ref_X = 95.047; //Observer= 2°, Illuminant= D65 |
| double ref_Y = 100.000; |
| double ref_Z = 108.883; |
| |
| // Debug.debug("var_Y", var_Y); |
| |
| double ref_U = (4 * ref_X) / (ref_X + (15 * ref_Y) + (3 * ref_Z)); |
| double ref_V = (9 * ref_Y) / (ref_X + (15 * ref_Y) + (3 * ref_Z)); |
| |
| // Debug.debug("ref_U", ref_U); |
| // Debug.debug("ref_V", ref_V); |
| |
| double L = (116 * var_Y) - 16; |
| double u = 13 * L * (var_U - ref_U); |
| double v = 13 * L * (var_V - ref_V); |
| |
| return new ColorCieLuv(L, u, v); |
| } |
| |
| public static ColorXyz convertCIELuvtoXYZ(ColorCieLuv cielch) |
| { |
| return convertCIELuvtoXYZ(cielch.L, cielch.u, cielch.v); |
| } |
| |
| public static ColorXyz convertCIELuvtoXYZ(double L, double u, double v) |
| { |
| // problems here with div by zero |
| |
| double var_Y = (L + 16) / 116; |
| if (Math.pow(var_Y, 3) > 0.008856) |
| var_Y = Math.pow(var_Y, 3); |
| else |
| var_Y = (var_Y - 16 / 116) / 7.787; |
| |
| double ref_X = 95.047; //Observer= 2°, Illuminant= D65 |
| double ref_Y = 100.000; |
| double ref_Z = 108.883; |
| |
| double ref_U = (4 * ref_X) / (ref_X + (15 * ref_Y) + (3 * ref_Z)); |
| double ref_V = (9 * ref_Y) / (ref_X + (15 * ref_Y) + (3 * ref_Z)); |
| double var_U = u / (13 * L) + ref_U; |
| double var_V = v / (13 * L) + ref_V; |
| |
| double Y = var_Y * 100; |
| double X = -(9 * Y * var_U) / ((var_U - 4) * var_V - var_U * var_V); |
| double Z = (9 * Y - (15 * var_V * Y) - (var_V * X)) / (3 * var_V); |
| |
| return new ColorXyz(X, Y, Z); |
| } |
| } |