UI对阿里云OSS取色的色彩不满意,让后端取色,下面的取色代码1M图片毫秒级,而且效果很好
public class MedianCutColorExtractor {
public static void main(String[] args) {
try {
BufferedImage img = ImageIO.read(new File("someThing/thread_1.jpg"));
Color dominantColor = getDominantColor(img, 1000);
System.out.println("Dominant Color: " + dominantColor.toString());
} catch (IOException e) {
System.out.println("Image file not found.");
}
}
public static Color getDominantColor(BufferedImage img, int maxPixels) {
int width = img.getWidth();
int height = img.getHeight();
int totalPixels = width * height;
if (totalPixels > maxPixels) {
double scaleFactor = Math.sqrt((double) maxPixels / totalPixels);
width = (int) (width * scaleFactor);
height = (int) (height * scaleFactor);
img = resizeImage(img, width, height);
}
List<Color> colors = new ArrayList<>();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
colors.add(new Color(img.getRGB(x, y)));
}
}
return medianCut(colors, 1).get(0);
}
private static BufferedImage resizeImage(BufferedImage img, int width, int height) {
BufferedImage resizedImage = new BufferedImage(width, height, img.getType());
Graphics2D g = resizedImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
private static List<Color> medianCut(List<Color> colors, int level) {
if (colors.isEmpty()) {
return Collections.emptyList();
}
if (level == 0) {
return Collections.singletonList(getAverageColor(colors));
}
int[] minMax = getMinMax(colors);
int longestAxis = getLongestAxis(minMax);
sortColorsByAxis(colors, longestAxis);
int median = colors.size() / 2;
List<Color> left = colors.subList(0, median);
List<Color> right = colors.subList(median, colors.size());
List<Color> result = new ArrayList<>();
result.addAll(medianCut(left, level - 1));
result.addAll(medianCut(right, level - 1));
return result;
}
private static int[] getMinMax(List<Color> colors) {
int minRed = 255, maxRed = 0;
int minGreen = 255, maxGreen = 0;
int minBlue = 255, maxBlue = 0;
for (Color color : colors) {
minRed = Math.min(minRed, color.getRed());
maxRed = Math.max(maxRed, color.getRed());
minGreen = Math.min(minGreen, color.getGreen());
maxGreen = Math.max(maxGreen, color.getGreen());
minBlue = Math.min(minBlue, color.getBlue());
maxBlue = Math.max(maxBlue, color.getBlue());
}
return new int[]{minRed, maxRed, minGreen, maxGreen, minBlue, maxBlue};
}
private static int getLongestAxis(int[] minMax) {
int redRange = minMax[1] - minMax[0];
int greenRange = minMax[3] - minMax[2];
int blueRange = minMax[5] - minMax[4];
if (redRange >= greenRange && redRange >= blueRange) {
return 0;
} else if (greenRange >= redRange && greenRange >= blueRange) {
return 1;
} else {
return 2;
}
}
private static void sortColorsByAxis(List<Color> colors, int axis) {
Comparator<Color> comparator;
switch (axis) {
case 0: // Red axis
comparator = Comparator.comparingInt(Color::getRed);
break;
case 1: // Green axis
comparator = Comparator.comparingInt(Color::getGreen);
break;
default: // Blue axis
comparator = Comparator.comparingInt(Color::getBlue);
break;
}
colors.sort(comparator);
}
private static Color getAverageColor(List<Color> colors) {
int redSum = 0;
int greenSum = 0;
int blueSum = 0;
int count = colors.size();
for (Color color : colors) {
redSum += color.getRed();
greenSum += color.getGreen();
blueSum += color.getBlue();
}
return new Color(redSum / count, greenSum / count, blueSum / count);
}
}