簡體   English   中英

將顏色 object“四舍五入”到最接近的顏色常數的最佳方法是什么?

[英]What's the best way to “round” a Color object to the nearest Color Constant?

我將檢索像素的確切顏色,並希望將該確切顏色與像Color.blue這樣的常數相關聯。 有沒有一種簡單的方法可以“四舍五入”到最近的顏色常數? 此外,有沒有辦法定義自己的顏色常數?

基本方法是通過簡單地將樣品與每種顏色進行比較來找到與您的樣品最接近的標准顏色。 當然,問題在於定義“最接近”。 最明顯的是在 RGB 空間中使用歐幾里得距離。 問題是這個距離與我們對“最接近的顏色”的感知不太吻合。 可以在本文中找到對這個問題的討論,以及一個很好的(易於計算的)度量(包括偽代碼!)。

編輯:以防萬一該論文的鏈接失效(或者如果您很懶並且願意在不了解代碼的作用的情況下使用代碼),這是我的 Java 版本的“顏色距離函數”,該論文建議為“低-cost approximation” 到他們推薦的距離 function(RGB 空間中的加權歐幾里得距離):

double colorDistance(Color c1, Color c2)
{
    int red1 = c1.getRed();
    int red2 = c2.getRed();
    int rmean = (red1 + red2) >> 1;
    int r = red1 - red2;
    int g = c1.getGreen() - c2.getGreen();
    int b = c1.getBlue() - c2.getBlue();
    return Math.sqrt((((512+rmean)*r*r)>>8) + 4*g*g + (((767-rmean)*b*b)>>8));
}

請注意,如果您只是要對顏色距離進行排名,則可以省去對Math.sqrt()的調用,從而節省一些計算成本。

可能最好的方法是遍歷每個常量,並比較它們各自的 RGB 通道( getRedgetGreengetBlue )。 跟蹤最接近的那個。

Color color = new Color(...);
Color[] constantColors = new Color[] { Color.black, Color.blue, Color.cyan, Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, Color.orange, Color.pink, Color.red, Color.white, Color.yellow };
Color nearestColor = null;
Integer nearestDistance = new Integer(Integer.MAX_VALUE);

for (Color constantColor : constantColors) {
    if (nearestDistance > Math.sqrt(
            Math.pow(color.getRed() - constantColor.getRed(), 2)
            - Math.pow(color.getGreen() - constantColor.getGreen(), 2)
            - Math.pow(color.getBlue() - constantColor.getBlue(), 2)
        )
    ) {
        nearestColor = color;
    }
}

不,您不能將顏色常量添加到 class,但您可以創建自己的 class 來保存常量。

class MyColors {
    public static final Color heliotrope = new Color(...);
}

編輯:添加差異算法,感謝@Ted 的鏈接。

您可以將 Java 的內置顏色轉換與IndexColorModel一起使用,其中包含可能的 colors 的調色板。 在內部,class 在顏色分量上使用歐幾里得距離來確定最接近的顏色。

import java.awt.Color;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;

public class ColorConverter {
    private final Color[] colors;
    private final IndexColorModel colorModel;

    public ColorConverter(Color[] colors) {
        this.colors = colors;
        this.colorModel = createColorModel(colors);
    }

    private static IndexColorModel createColorModel(Color[] colors) {
        final int[] cmap = new int[colors.length];
        for (int i = 0; i<colors.length; i++) {
            cmap[i] = colors[i].getRGB();
        }
        final int bits = (int) Math.ceil(Math.log(cmap.length)/Math.log(2));
        return new IndexColorModel(bits, cmap.length, cmap, 0, false, -1, DataBuffer.TYPE_BYTE);
    }

    public Color nearestColor(Color color) {
        final byte index = ((byte[])colorModel.getDataElements(color.getRGB(), null))[0];
        return colors[index];
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM