首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从32 BPP转换为8 BPP索引(C#)

从32 BPP转换为8 BPP索引(C#)
EN

Stack Overflow用户
提问于 2009-11-06 07:21:08
回答 4查看 1.8K关注 0票数 6

我需要采取全彩色JPG图像和重新映射它的颜色到一个索引调色板。调色板将由从数据库填充的特定颜色组成。我需要将图像的每种颜色映射到它在索引中的“最接近”值。我相信有不同的算法来比较和计算“最接近”的值。仅查找.NET托管代码库的C#。

(它将在一个流程中使用,其中我们有大约120种特定颜色的按钮,并且我们希望将任何图像映射到这120种颜色以生成拼贴画)。

EN

回答 4

Stack Overflow用户

发布于 2009-11-10 04:44:49

对于GDI,没有任何东西能帮到你。对于微软来说,索引图像似乎是一项太落后的技术。你所能做的就是读写索引图像文件。

在量化图像中的颜色时,通常有两个步骤:

1)找到图像的最佳调色板(颜色量化)

2)将源solors映射到找到的调色板(颜色映射)

据我所知,你已经在数据库中有调色板,这意味着最难的部分已经为你完成了。您所需要做的就是将24位颜色映射到提供的调色板颜色。如果你没有起始调色板,那么你必须使用量化算法自己计算它:八叉树或中值切割是最广为人知的。Median提供了更好的结果,但更慢,更难实现和微调。

要映射颜色,在您的情况下,最简单的算法是计算从源颜色到所有调色板颜色的距离,并选取最近的颜色。

代码语言:javascript
复制
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根本不会起作用:

代码语言:javascript
复制
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不允许你写入索引图像。

票数 3
EN

Stack Overflow用户

发布于 2009-11-06 07:28:52

这个过程被称为Quantization。因为每种颜色代表3个打包的值,你需要使用八叉树来解决这个问题。

查看这个包含示例代码的article

本文的重点是获取图像的最终调色板,但您的过程将与第二部分相反,只减少与给定调色板接近的最常用的颜色。

票数 2
EN

Stack Overflow用户

发布于 2009-11-06 10:59:40

我不得不在一个大型的.NET项目中这样做。框架中没有提供任何解决方案,但是这篇文章很快将我带到了一个解决方案:http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/6103.aspx

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1684362

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档