我需要采取全彩色JPG图像和重新映射它的颜色到一个索引调色板。调色板将由从数据库填充的特定颜色组成。我需要将图像的每种颜色映射到它在索引中的“最接近”值。我相信有不同的算法来比较和计算“最接近”的值。仅查找.NET托管代码库的C#。
(它将在一个流程中使用,其中我们有大约120种特定颜色的按钮,并且我们希望将任何图像映射到这120种颜色以生成拼贴画)。
发布于 2009-11-10 04:44:49
对于GDI,没有任何东西能帮到你。对于微软来说,索引图像似乎是一项太落后的技术。你所能做的就是读写索引图像文件。
在量化图像中的颜色时,通常有两个步骤:
1)找到图像的最佳调色板(颜色量化)
2)将源solors映射到找到的调色板(颜色映射)
据我所知,你已经在数据库中有调色板,这意味着最难的部分已经为你完成了。您所需要做的就是将24位颜色映射到提供的调色板颜色。如果你没有起始调色板,那么你必须使用量化算法自己计算它:八叉树或中值切割是最广为人知的。Median提供了更好的结果,但更慢,更难实现和微调。
要映射颜色,在您的情况下,最简单的算法是计算从源颜色到所有调色板颜色的距离,并选取最近的颜色。
float ColorDistanceSquared(Color c1, Color c2)
{
float deltaR = c2.R - c1.R;
float deltaG = c2.G - c1.G;
float deltaB = c2.B - c1.B;
return deltaR*deltaR + deltaG*deltaG + deltaB*deltaB;
}你也可以仔细考虑通道,让蓝色的权重更小,不要太过分,否则它会产生可怕的结果,特别是30/59/11根本不会起作用:
float ColorDistanceSquared(Color c1, Color c2)
{
float deltaR = (c2.R - c1.R) * 3;
float deltaG = (c2.G - c1.G) * 3;
float deltaB = (c2.B - c1.B) * 2;
return deltaR*deltaR + deltaG*deltaG + deltaB*deltaB;
}调用所有源颜色和调色板颜色并找到最小值。如果你在地图中缓存你的结果,这将会非常快。
此外,源颜色很少适合调色板颜色,以至于不会在图像中产生条带和普通区域以及细节丢失。为了避免这种情况,您可以使用抖动。误差扩散抖动是最简单的算法,也是给出最佳结果的算法。
一旦你映射了你的颜色,你将不得不手动锁定一个位图并在其中写入索引,因为.Net不允许你写入索引图像。
发布于 2009-11-06 07:28:52
这个过程被称为Quantization。因为每种颜色代表3个打包的值,你需要使用八叉树来解决这个问题。
查看这个包含示例代码的article。
本文的重点是获取图像的最终调色板,但您的过程将与第二部分相反,只减少与给定调色板接近的最常用的颜色。
发布于 2009-11-06 10:59:40
我不得不在一个大型的.NET项目中这样做。框架中没有提供任何解决方案,但是这篇文章很快将我带到了一个解决方案:http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/6103.aspx
https://stackoverflow.com/questions/1684362
复制相似问题