我有一个应用程序索引视频中出现的前16种颜色。
我正在尝试编写另一个允许用户选择颜色的应用程序,然后应用程序找到该颜色出现的所有视频。
问题是因为我只为每个视频索引16种颜色,所以用户选择RGB颜色。这种颜色被索引的概率非常低,因此几乎总是我的应用程序没有返回任何结果。
我想到了一种可以使这项工作的方法 - 我可以索引视频中出现的颜色并将它们转换为最接近的8位颜色。
然后当用户选择RGB颜色时,我可以将用户选择转换为相同的8位最接近的颜色。
这样我总能有比赛。
我现在唯一的主要问题是如何将RGB颜色转换为最接近的8位颜色?
要转换为Web安全调色板,您需要将每个r,g,b组件的范围从0-255转换为0-5并将它们组合:
color = (r*6/256)*36 + (g*6/256)*6 + (b*6/256)
您需要做的是将RGB转换为HSB(色调饱和度亮度)值。 HSB是3字节,就像RGB一样,区别在于HSB值可以比RGB更容易比较。
您的下一步是决定“重要性”加权。例如,如果您关心的只是“颜色/色调”,而不是饱和度或亮度,那么您可以丢弃S和B字节,只使用颜色字节。
如果是我和我被限制为8位,我将使用4位颜色信息(16种不同颜色),3位饱和度(8种不同值)和1位亮度信息(亮或暗)。
本文介绍如何在Java中执行HSB:
http://java.sys-con.com/node/43559
本文的源代码在Java中有一个RGB到HSB转换器。
一种可能性是简单地将24位颜色缩小为8位颜色空间。正如cHao所提到的,你可以将RRRGGGBB用于你的8位数字。然后,可以通过简单的缩放算法计算每个颜色分量,例如:
byte red = (originalColor.red * 8) / 256;
byte green = (originalColor.green * 8) / 256;
byte blue = (originalColor.blue * 4) / 256;
8,4和254是每个颜色分量中可能值的数量。在原始的24位颜色中,红色,绿色和蓝色都可以有256个可能的值,因此这是缩放方程的除数。在示例8位颜色中,红色和绿色各3位(8个可能值),蓝色2位(4个可能值)。
获得这三个组件后,您可以将它们与一些简单的位移算术结合起来:
byte eightBitColor = (red << 5) | (green << 2) | blue;
然后,您可以简单地比较这些8位颜色。它们的分辨率大大降低可能对您有所帮助。
或者,您可以执行类似Tyler建议的操作,并首先转换为HSB或HSV,并仅比较色调(取决于您是否需要亮度和饱和度信息)。根据您的目标,这可能实际上是一个更理想的解决方案。
编辑:修改缩放算法以修复Mark Ransom指出的缺点。
你熟悉吗? 弗洛伊德 - 斯坦伯格犹豫不决?这用于将高阶颜色转换为低阶颜色,例如24位RGB至3位(8色)RGB或将RGB图像限制为8位(256色)以进行GIF转换。
该算法在链接的维基百科页面上描述。
如果要转换,请尝试此算法
24 bpp图像到8 bpp图像:
for y = 0 to ImageHeight - 1
for x = 0 to ImageWidth - 1
GetPixel(x,y,red,grn,blu)
{read RGB data from 24bpp file}
d0 = red^2 + grn^2 + blu^2
ColorIndex = 0
for cl = 0 to 255
GetPaletteData(p_red,p_gre,p_blu)
{read RGB data from 8bpp palette}
d = (red - p_red)^2 + (grn - p_grn)^2 + (blu - p_blu)^2
if d0 >= d then
ColorIndex = cl
d0 = d
end if
next cl
{use ColorIndex to create your 8bpp file}
next x
next y
在此步骤之前,请阅读有关维基百科或其他来源的8bpp文件的更多信息。
祝你好运!