【问题标题】:Apply color palette to picture将调色板应用于图片
【发布时间】:2014-12-15 08:39:01
【问题描述】:

我需要为.img 二进制图像文件制定压缩算法。图像可以说是 512x512。我正在使用BinaryReader 逐像素获取二进制文件,并将其保存在short[,] 中。它是这样的:

br1 = new BinaryReader(File.Open(openFileDialog1.FileName, FileMode.Open));
short[,] num = new short[512, 512];
for (int i = 0; i < 512; i++)
    for (int j = 0; j < 512; j++)
    {
         num[i, j] = (short)br1.ReadInt16();
    }

我不明白如何使用调色板(导入的 .pal 文件)将 [-2048,2047] 之间的值转换为位图。

我非常感谢任何帮助、建议、代码、教程等。 提前致谢。

【问题讨论】:

  • 您需要做的第一件事是确定要创建的图像格式。有一些基于调色板的格式将(8 位或 16 位)指针保存到调色板结构中,还有一些基于像素的格式,它在每​​个像素(24 位)中保存 RGB 值。后者更容易创建。在任何一种情况下,您还需要了解二进制数据所代表的颜色含义。 - 不管你多么“努力”,你都无法超越 PNG 或 JPG 压缩,不过..
  • 我想创建基于调色板的图片,我拥有的信息是 [-2048, 2047] 之间的值。我需要这部分,以便在开始使用我的算法压缩它之前,我可以在 pictureBox 中显示 .img 二进制文件。
  • 好的,但是这些值是什么意思?灰度值?
  • 嗯,在发布我的答案后,我注意到您正在谈论一个 .pal 文件。所以如果你真的想要一个颜色文件,这个文件必须映射到值。它有多大?你知道什么吗,比如条目的类型和数量?请注意,对调色板大小的所有限制仍然适用,无论它们指向哪种颜色:最多 256 种颜色是可能的!

标签: c# compression color-palette


【解决方案1】:

这是一个示例,它从一个数据源创建一个基于 8 位调色板的图像,该数据源获取 -2048 - +2047 范围内的值。请注意,这是一个 12 位的值范围,因此实际上需要一个 16 位的调色板。

但是,这不受支持。甚至 RGB 都不支持它们,任何非专业显卡也不支持。

如果您需要全方位的精度,您将不得不使用外部工具。

您可以尝试使用位抖动来执行基于 RGB 的解决方案,通过改变 R、G 和 B 值来模拟 4096 个灰度值。

   using System.Drawing.Imaging;
   using System.Runtime.InteropServices;
   //..   

    // 8-bit grayscale
    Bitmap bmp = new Bitmap(512,512, PixelFormat.Format8bppIndexed);

    List<Color> colors = new List<Color>();

    byte[] data = new byte[512 * 512];

    for (int y = 0; y < 512; y++)
    for (int x = 0; x < 512; x++)
    {
        int v = getValue() + 2048;      // replace by your data reader!

        int r = v >> 4;                 // < here we lose 4 bits!
        int g = r;
        int b = r;
        Color c = Color.FromArgb(r, g, b);
        int cIndex = 0;
        if (colors.Contains(c)) cIndex = colors.IndexOf(c);
        else { colors.Add(c); cIndex = colors.Count; }

        //bmp.SetPixel(x,y,c);    // this would be used for rgb formats!
        data[y * 512 + x] = (byte) cIndex;
    }

    // prepare a locked image memory area
    var bmpData = bmp.LockBits(
                new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.WriteOnly, bmp.PixelFormat);

    // move our data in
    Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
    bmp.UnlockBits(bmpData);

    // create the palette
    var pal = bmp.Palette;
    for (int i = 0; i < colors.Count; i++) pal.Entries[i] = colors[i];
    bmp.Palette = pal;

    // display
    pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
    pictureBox1.Image = bmp;

【讨论】:

  • 嘿TaW。非常感谢您的回答。我设法以某种方式清除了一些东西...... [-2048, 2047] 的值是来自托盘的颜色索引,其中包含 4096 种颜色。因此,我将逐字节读取 .pal 文件,并将每个字节分配给 R、G 和 B,并且在开始时,我将有一些颜色索引,即第一种颜色 = 索引 0001,第二种 = 0002 ...我打算使用 setPixel 函数将 em 设置为位图。感谢您的帮助,很多事情对我来说真的不清楚,但我设法弄明白了。
  • 是的。我使用二进制阅读器并从 .pal 文件中读取值并将它们放入 Color.FromArgb 中。比我从 ushort 数组中的 .img 二进制文件中读取值,我得到的值介于 0 和 4096(调色板中的元素数)之间,并使用 setPixel 绘制图片。
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 2021-08-15
  • 2014-02-08
  • 1970-01-01
  • 2019-01-16
  • 2018-04-30
  • 1970-01-01
  • 2021-05-16
相关资源
最近更新 更多