Java 之 获取图片主色调
1.创建RGB实体类
public class RGB { private int red; private int green; private int blue; public RGB(){} public RGB(int red,int green,int blue){ setRed(red); setBlue(blue); setGreen(green); } public int getRed() { return red; } public void setRed(int red) { if (red < 0) { this.red = 0; } else if (red > 255) { this.red = 255; } else { this.red = red; } } public int getGreen() { return green; } public void setGreen(int green) { if (green < 0) { this.green = 0; } else if (green > 255) { this.green = 255; } else { this.green = green; } } public int getBlue() { return blue; } public void setBlue(int blue) { if (blue < 0) { this.blue = 0; } else if (blue > 255) { this.blue = 255; } else { this.blue = blue; } } @Override public boolean equals(Object obj) { RGB theRGB = (RGB) obj; return this.getRed() == theRGB.getRed() && this.getGreen() == theRGB.getGreen() && this.getBlue() == theRGB.getBlue(); } @Override public int hashCode() { return this.getRed() * 1000000 + this.getGreen() * 1000 + this.getBlue(); } public String toString() { return "RGB {" + this.red + ", " + this.green + ", " + this.blue + "}"; } }
2.创建HSL实体类
public class HSL { private float h; /** 饱和度 */ private float s; /** 深度 */ private float l; public HSL() { } public HSL(float h, float s, float l) { setH(h); setS(s); setL(l); } public float getH() { return h; } public void setH(float h) { if (h < 0) { this.h = 0; } else if (h > 360) { this.h = 360; } else { this.h = h; } } public float getS() { return s; } public void setS(float s) { if (s < 0) { this.s = 0; } else if (s > 255) { this.s = 255; } else { this.s = s; } } public float getL() { return l; } public void setL(float l) { if (l < 0) { this.l = 0; } else if (l > 255) { this.l = 255; } else { this.l = l; } } @Override public boolean equals(Object obj) { HSL theHSL = (HSL) obj; return this.getH() == theHSL.getH() && this.getS() == theHSL.getS() && this.getL() == theHSL.getL(); } @Override public int hashCode() { return Float.valueOf(this.getH() * 1000000 + this.getS() * 1000 + this.getL()).intValue(); } public String toString() { return "HSL {" + h + ", " + s + ", " + l + "}"; } }
3.创建RGB与HSL转换器
public class ColorConverter { /** * @param rgb * @return */ public static HSL RGB2HSL(RGB rgb) { if (rgb == null) { return null; } int red = rgb.getRed(); int green = rgb.getGreen(); int blue = rgb.getBlue(); float var_Min = Math.min(red, Math.min(blue, green)); float var_Max = Math.max(red, Math.max(blue, green)); float del_Max = var_Max - var_Min; float H = 0; float S = 0; float L = (var_Max + var_Min) / 2; if (del_Max == 0) { H = 0; S = 0; } else { if (L < 128) { S = 256 * del_Max / (var_Max + var_Min); } else { S = 256 * del_Max / (512 - var_Max - var_Min); } float del_R = ((360 * (var_Max - red) / 6) + (360 * del_Max / 2)) / del_Max; float del_G = ((360 * (var_Max - green) / 6) + (360 * del_Max / 2)) / del_Max; float del_B = ((360 * (var_Max - blue) / 6) + (360 * del_Max / 2)) / del_Max; if (red == var_Max) { H = del_B - del_G; } else if (green == var_Max) { H = 120 + del_R - del_B; } else if (blue == var_Max) { H = 240 + del_G - del_R; } if (H < 0) { H += 360; } if (H >= 360) { H -= 360; } if (L >= 256) { L = 255; } if (S >= 256) { S = 255; } } return new HSL(H, S, L); } /** * @param hsl * @return */ public static RGB HSL2RGB(HSL hsl) { if (hsl == null) { return null; } float H = hsl.getH(); float S = hsl.getS(); float L = hsl.getL(); float R, G, B, var_1, var_2; if (S == 0) { R = L; G = L; B = L; } else { if (L < 128) { var_2 = (L * (256 + S)) / 256; } else { var_2 = (L + S) - (S * L) / 256; } if (var_2 > 255) { var_2 = Math.round(var_2); } if (var_2 > 254) { var_2 = 255; } var_1 = 2 * L - var_2; R = RGBFromHue(var_1, var_2, H + 120); G = RGBFromHue(var_1, var_2, H); B = RGBFromHue(var_1, var_2, H - 120); } R = R < 0 ? 0 : R; R = R > 255 ? 255 : R; G = G < 0 ? 0 : G; G = G > 255 ? 255 : G; B = B < 0 ? 0 : B; B = B > 255 ? 255 : B; return new RGB((int) Math.round(R), (int) Math.round(G), (int) Math.round(B)); } /** * @param a * @param b * @param h * @return */ public static float RGBFromHue(float a, float b, float h) { if (h < 0) { h += 360; } if (h >= 360) { h -= 360; } if (h < 60) { return a + ((b - a) * h) / 60; } if (h < 180) { return b; } if (h < 240) { return a + ((b - a) * (240 - h)) / 60; } return a; } }
4.获取主色调逻辑
public class HslTest { /** * 获取图片主色调的rgb值 * @param path * @return * @throws Exception */ public static RGB getMainRgb (String path) throws Exception{ Map<Float, Integer> hueCountMap = new HashMap<>(); Map<HSL, Integer> hslCountMap = new HashMap<>(); BufferedImage image = ImageIO.read(new URL(path)); // BufferedImage image = ImageIO.read(new File(path)); int width = image.getWidth(); int height = image.getHeight(); int minx = image.getMinX(); int miny = image.getMinY(); //计算各点的hsl值,并统计数量 for (int i = minx; i < width; i++) { for (int j = miny; j < height; j++) { int pixel = image.getRGB(i, j); Color color = new Color(pixel); RGB rgb = new RGB(color.getRed(), color.getGreen(), color.getBlue()); HSL hsl = ColorConverter.RGB2HSL(rgb); float h = computeHue(hsl.getH()); float s = computeSAndL(hsl.getS()); float l = computeSAndL(hsl.getL()); HSL newHSL = new HSL(h, s, l); //统计hue值数量 Integer count = hueCountMap.get(h); if(count == null){ hueCountMap.put(h, 1); }else{ hueCountMap.put(h, count + 1); } //统计HSL数量 count = hslCountMap.get(newHSL); if(count == null){ hslCountMap.put(newHSL, 1); }else{ hslCountMap.put(newHSL, count + 1); } } } //查找数量最多的hue值 float maxHue = 0; int maxCount = 0; for(Map.Entry<Float, Integer> entry : hueCountMap.entrySet()){ float hue = entry.getKey(); int count = entry.getValue(); if(count > maxCount){ maxCount = count; maxHue = hue; } } //查找maxHue中数量最多的hsl值 HSL maxHSL = null; maxCount = 0; for(Map.Entry<HSL, Integer> entry : hslCountMap.entrySet()){ HSL hsl = entry.getKey(); int count = entry.getValue(); if(hsl.getH() == maxHue && count > maxCount){ maxCount = count; maxHSL = hsl; } } //hsl转rgb RGB resultRGB = ColorConverter.HSL2RGB(maxHSL); return resultRGB; } /** * 按格子划分h值 * @param h * @return */ public static float computeHue (float h){ if(h <= 15){ return 0; } if(15 < h && h <= 45){ return 30; } if(45 < h && h <= 75){ return 60; } if(75 < h && h <= 105){ return 90; } if(105 < h && h <= 135){ return 120; } if(135 < h && h <= 165){ return 150; } if(165 < h && h <= 195){ return 180; } if(195 < h && h <= 225){ return 210; } if(225 < h && h <= 255){ return 240; } if(255 < h && h <= 285){ return 270; } if(285 < h && h <= 315){ return 300; } if(315 < h && h <= 345){ return 330; } if(345 < h){ return 360; } return 360; } /** * 按格子划分s和l值 * @param s * @return */ public static float computeSAndL (float s){ if(s <= 32){ return 0; } if(32 < s && s <= 96){ return 64; } if(96 < s && s <= 160){ return 128; } if(160 < s && s <= 224){ return 192; } if(s > 224){ return 255; } return 255; } }
5.测试
public static void main(String[] args) throws Exception { String path = "http://b-ssl.duitang.com/uploads/item/201805/19/20180519081907_wflza.jpg"; RGB rgb = HslTest.getMainRgb(path); System.out.println(rgb); }
运行后 RGB值 为 {240, 144, 192}
6.参考文档:
https://cloud.tencent.com/developer/article/1119452
http://www.what21.com/sys/view/java_java-gui_1456896004339.html