首頁 > Java > java教程 > 為什麼提供的用於顏色量化的 Java 程式碼很難有效地減少顏色,特別是在將顏色超過 256 的圖像減少到 256 時,導致明顯的錯誤,例如 re

為什麼提供的用於顏色量化的 Java 程式碼很難有效地減少顏色,特別是在將顏色超過 256 的圖像減少到 256 時,導致明顯的錯誤,例如 re

Susan Sarandon
發布: 2024-11-25 14:47:12
原創
878 人瀏覽過

Why does the provided Java code for color quantization struggle to effectively reduce colors, particularly when reducing images with more than 256 colors to 256, resulting in noticeable errors like reds turning blue?

有效的GIF/圖像顏色量化

在Java 編程中,顏色量化在優化圖像或GIF 文件的調色板方面起著至關重要的作用。此過程涉及減少顏色數量,同時保持原始影像的視覺可接受的表示。

問題陳述:

提供的程式碼在減少顏色方面似乎效率低下有效地。當將超過 256 種顏色的影像減少到 256 種顏色時,會產生明顯的錯誤,例如紅色變成藍色。這表明該演算法很難識別和保留圖像中的重要顏色。

推薦演算法:

  • 中值切割:演算法根據中位數顏色值遞歸地將顏色空間分為兩半,建立二元樹。然後,它選擇顏色變化最小的子樹作為葉節點,代表最終的調色板。
  • 基於群體: 演算法根據顏色在顏色中的總體(頻率)對顏色進行排序。圖像並透過選擇前「n」個最常見的顏色來建立調色板。
  • k-Means:此演算法將色彩空間分割為「k」個簇,其中每個簇由其平均色彩值表示。然後使用簇質心形成調色板。

範例實作:

以下是Java 中中值切割演算法的範例實作:

import java.util.Arrays;
import java.util.Comparator;
import java.awt.image.BufferedImage;

public class MedianCutQuantizer {

    public static void quantize(BufferedImage image, int colors) {
        int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
        Arrays.sort(pixels); // Sort pixels by red, green, and blue channel values

        // Create a binary tree representation of the color space
        TreeNode root = new TreeNode(pixels);

        // Recursively divide the color space and create the palette
        TreeNode[] palette = new TreeNode[colors];
        for (int i = 0; i < colors; i++) {
            palette[i] = root;
            root = divide(root);
        }

        // Replace pixels with their corresponding palette colors
        for (int i = 0; i < pixels.length; i++) {
            pixels[i] = getClosestColor(pixels[i], palette);
        }

        image.setRGB(0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth());
    }

    private static TreeNode divide(TreeNode node) {
        // Find the median color value
        int median = node.getMedianValue();

        // Create two new nodes, one for each half of the color range
        TreeNode left = new TreeNode();
        TreeNode right = new TreeNode();

        // Divide the pixels into two halves
        for (int i = node.start; i < node.end; i++) {
            if (node.pixels[i] <= median) {
                left.addPixel(node.pixels[i]);
            } else {
                right.addPixel(node.pixels[i]);
            }
        }

        return left.count > right.count ? left : right;
    }

    private static int getClosestColor(int pixel, TreeNode[] palette) {
        int minDistance = Integer.MAX_VALUE;
        int closestColor = 0;

        for (TreeNode node : palette) {
            int distance = getDistance(pixel, node.getAverageValue());
            if (distance < minDistance) {
                minDistance = distance;
                closestColor = node.getAverageValue();
            }
        }

        return closestColor;
    }

    // Utility methods

    private static int getDistance(int color1, int color2) {
        int r1 = (color1 >> 16) & 0xFF;
        int g1 = (color1 >> 8) & 0xFF;
        int b1 = color1 & 0xFF;

        int r2 = (color2 >> 16) & 0xFF;
        int g2 = (color2 >> 8) & 0xFF;
        int b2 = color2 & 0xFF;

        return (r1 - r2) * (r1 - r2) + (g1 - g2) * (g1 - g2) + (b1 - b2) * (b1 - b2);
    }

    private static class TreeNode {
        int start;
        int end;
        int count;
        int[] pixels;
        Integer averageValue;

        public TreeNode() {
            this(new int[0], 0, 0);
        }

        public TreeNode(int[] pixels, int start, int end) {
            this.pixels = pixels;
            this.start = start;
            this.end = end;

            count = end - start;
        }

        public int getMedianValue() {
            return pixels[(start + end) / 2];
        }

        public int getAverageValue() {
            if (averageValue == null) {
                int r = 0;
                int g = 0;
                int b = 0;

                for (int i = start; i < end; i++) {
                    int pixel = pixels[i];

                    r += (pixel >> 16) & 0xFF;
                    g += (pixel >> 8) & 0xFF;
                    b += pixel & 0xFF;
                }

                averageValue = (r / count) << 16 | (g / count) << 8 | b / count;
            }

            return averageValue;
        }

        public void addPixel(int pixel) {
            int[] newPixels = new int[pixels.length + 1];

            System.arraycopy(pixels, start, newPixels, start, end);
            newPixels[end] = pixel;

            pixels = newPixels;
            end++;
            count = end - start;

            averageValue = null;
        }
    }
}
登入後複製

使用此實作或其他類似演算法可以顯著改進Java 應用程式中的顏色量化過程,將影像顏色減少到256或更少時,可以獲得視覺上可接受的結果。

以上是為什麼提供的用於顏色量化的 Java 程式碼很難有效地減少顏色,特別是在將顏色超過 256 的圖像減少到 256 時,導致明顯的錯誤,例如 re的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板