Mariusz Sieroń 6 лет назад
Родитель
Сommit
fe07e1d195
1 измененных файлов с 142 добавлено и 9 удалено
  1. 142 9
      assira/src/main/java/net/ranides/assira/awt/ColorUtils.java

+ 142 - 9
assira/src/main/java/net/ranides/assira/awt/ColorUtils.java

@@ -7,6 +7,7 @@
 package net.ranides.assira.awt;
 
 import java.awt.Color;
+import java.awt.color.ColorSpace;
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -57,13 +58,25 @@ public final class ColorUtils {
             return String.format(Locale.ROOT, "rgb(%d,%d,%d)", color.getRed(), color.getGreen(), color.getBlue() );
         }
     }
+
+    public static Color parse(String value) {
+        if(6 == value.length() && value.matches("[0-9a-fA-F]{6}")) {
+            return fromCSS_S6(value);
+        }
+        if(3 == value.length() && value.matches("[0-9a-fA-F]{3}")) {
+            return fromCSS_S3(value);
+        }
+        return fromCSS(value);
+    }
     
     public static Color fromCSS(String value) {
         if(7 == value.length() && value.startsWith("#")) {
-            return fromCSS_H6(value);
+            // NOPMD
+            return fromCSS_S6(value.substring(1));
         }
         if(4 == value.length() && value.startsWith("#")) {
-            return fromCSS_H3(value);
+            // NOPMD
+            return fromCSS_S3(value.substring(1));
         }
         if(value.startsWith("rgb")) {
             Matcher hit = RE_RGBA.matcher(value);
@@ -77,19 +90,18 @@ public final class ColorUtils {
                 return fromCSS_HSLA(hit);
             }
         }
-
         throw new IllegalArgumentException("Invalid color: " + value);
     }
 
 
-    private static Color fromCSS_H6(String value) { // NOPMD
-        return new Color(Integer.parseInt(value.substring(1),16));
+    private static Color fromCSS_S6(String value) { // NOPMD
+        return new Color(Integer.parseInt(value,16));
     }
 
-    private static Color fromCSS_H3(String value) { // NOPMD
-        int r = 17*ord(value.charAt(1)); 
-        int g = 17*ord(value.charAt(2));
-        int b = 17*ord(value.charAt(3));
+    private static Color fromCSS_S3(String value) { // NOPMD
+        int r = 17*ord(value.charAt(0));
+        int g = 17*ord(value.charAt(1));
+        int b = 17*ord(value.charAt(2));
         return new Color(r,g,b);
 
     }
@@ -132,5 +144,126 @@ public final class ColorUtils {
         }
         throw new IllegalArgumentException("Invalid digit: " + c);
     }
+
+    private static class CIELab extends ColorSpace {
+
+        private static final long serialVersionUID = 5027741380892134289L;
+
+        private static final ColorSpace CIEXYZ = ColorSpace.getInstance(ColorSpace.CS_CIEXYZ);
+
+        private static final double N = 4.0 / 29.0;
+
+        private static class Holder {
+            static final CIELab INSTANCE = new CIELab();
+        }
+
+        public static CIELab getInstance() {
+            return Holder.INSTANCE;
+        }
+
+        @Override
+        public float[] fromCIEXYZ(float[] colorvalue) {
+            double l = f(colorvalue[1]);
+            double L = 116.0 * l - 16.0;
+            double a = 500.0 * (f(colorvalue[0]) - l);
+            double b = 200.0 * (l - f(colorvalue[2]));
+            return new float[] {(float) L, (float) a, (float) b};
+        }
+
+        @Override
+        public float[] fromRGB(float[] rgbvalue) {
+            float[] xyz = CIEXYZ.fromRGB(rgbvalue);
+            return fromCIEXYZ(xyz);
+        }
+
+        @Override
+        public float getMaxValue(int component) {
+            return 128f;
+        }
+
+        @Override
+        public float getMinValue(int component) {
+            return (component == 0)? 0f: -128f;
+        }
+
+        @Override
+        public String getName(int idx) {
+            return String.valueOf("Lab".charAt(idx));
+        }
+
+        @Override
+        public float[] toCIEXYZ(float[] colorvalue) {
+            double i = (colorvalue[0] + 16.0) * (1.0 / 116.0);
+            double X = fInv(i + colorvalue[1] * (1.0 / 500.0));
+            double Y = fInv(i);
+            double Z = fInv(i - colorvalue[2] * (1.0 / 200.0));
+            return new float[] {(float) X, (float) Y, (float) Z};
+        }
+
+        @Override
+        public float[] toRGB(float[] colorvalue) {
+            float[] xyz = toCIEXYZ(colorvalue);
+            return CIEXYZ.toRGB(xyz);
+        }
+
+        CIELab() {
+            super(ColorSpace.TYPE_Lab, 3);
+        }
+
+        private static double f(double x) {
+            if (x > 216.0 / 24389.0) {
+                return Math.cbrt(x);
+            } else {
+                return (841.0 / 108.0) * x + N;
+            }
+        }
+
+        private static double fInv(double x) {
+            if (x > 6.0 / 29.0) {
+                return x*x*x;
+            } else {
+                return (108.0 / 841.0) * (x - N);
+            }
+        }
+
+        private Object readResolve() {
+            return getInstance();
+        }
+
+    }
+
+    public static double distance(Color a, Color b) {
+        return distance(a.getRGBColorComponents(new float[3]), b.getRGBColorComponents(new float[3]));
+    }
+
+    public static double distance(LABColor a, LABColor b) {
+        return distance(a.components, b.components);
+    }
+
+    private static double distance(float[] a, float[] b) {
+        double sum = 0;
+        for(int i=0, n= a.length; i<n; i++) {
+            sum += (a[i]-b[i])*(a[i]-b[i]);
+        }
+        return Math.sqrt(sum);
+    }
+
+    public static class LABColor {
+
+        private float[] components;
+
+        public LABColor(float[] components) {
+            this.components = components;
+        }
+
+        public LABColor(Color color) {
+            components = color.getColorComponents(CIELab.getInstance(), new float[3]);
+        }
+
+        public LABColor(int r, int g, int b) {
+            components = new Color(r,g,b).getColorComponents(CIELab.getInstance(), new float[3]);
+        }
+
+    }
     
 }