首页 > 解决方案 > 如何正确地将调色板应用于图像?

问题描述

因此,我被赋予了重新编写一个程序的任务,该程序将图像转换为 3 种不同尺寸,其中 1 是应用了特定调色板的 256 色图像。原始源代码丢失。

调整大小我开始工作,但我在应用调色板时遇到问题。调色板存储为 JASC-PAL 文件。

这是我的代码,基于我的假设,即您只是加载文件、循环图像的当前调色板并替换颜色。

private List<Color> ColourPalette = new List<Color>();
void LoadColourPalette()
    {
        using (StreamReader sr = new StreamReader("HH.PAL"))
        {
            // skip first 3 lines
            sr.ReadLine();
            sr.ReadLine();
            sr.ReadLine();

            while (sr.Peek() != -1)
            {
                var readLine = sr.ReadLine();

                if(string.IsNullOrWhiteSpace(readLine))
                    continue;

                var colourBytes = readLine.Split(' ');

                ColourPalette.Add(
                    Color.FromArgb(int.Parse(colourBytes[0]),
                        int.Parse(colourBytes[1]),
                        int.Parse(colourBytes[2])
                        ));

            }
        }
    }

加载文件并应用调色板。

byte[] bytes;

using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    using (var thumbnail = System.Drawing.Image.FromStream(fs))
    {
       var imagePalette = thumbnail.Palette;

       for (int i = 0; i < imagePalette.Entries.Length; i++)
           imagePalette.Entries[i] = ColourPalette[i];

       thumbnail.Palette = imagePalette;

       using (MemoryStream memory = new MemoryStream())
       {
           thumbnail.Save(memory, ImageFormat.Bmp);
           bytes = memory.ToArray();
       }
    }
}

using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
{
   fs.Write(bytes, 0, bytes.Length);
}

当我查看图像时,它看起来完全错误。看起来更像是有人扔掉了像素化的油漆哈哈。我无法上传图片,但为了让您了解,图片是放在桌子上的一个白盘子。桌子应该像黑色/深蓝色的阴影,但它们是浅棕色和一些绿色的阴影。

因此,我拍摄了一张已应用调色板的图像,提取了调色板并保存到 JASC-PAL 格式的文件中。当我与我提供的调色板文件进行比较时,我可以看到它们完美匹配。

显然还有更多内容,但我似乎无法找到任何关于此事的内容。

标签: c#bitmapcolor-palette

解决方案


我会假设您的源图像是 24 位或 32 位颜色。即每个像素对于每个红绿和蓝通道都有一个字节。调色板图像不能这样工作。相反,它只有一个字节,用作查找表的 in 索引。

因此,要找到正确的索引,您需要在调色板中进行搜索以找到与实际像素颜色最相似的颜色。我认为您不能将 8 位位图用作 的渲染目标Graphics.FromImage,因此您可能需要自己进行此处理,但可能有可用的库可以为您完成。

使用调色位图不再常见,因为任何尺寸减小通常可以通过使用现代图像压缩算法更有效地实现。

老实说,我不确定如果您只是设置常规 24 位位图的调色板会发生什么,但显然结果不正确,因此可能不相关。


推荐阅读