【问题标题】:Where can I find example of 24 bit bitmap image RLE在哪里可以找到 24 位图图像 RLE 的示例
【发布时间】:2016-05-01 04:16:43
【问题描述】:

我了解使用 RLE 可能无法很好地压缩 24 位位图图像。但是,我用 VHDL 编写了一个将 VGA 信号发送到显示器的数字电路。在测试台中,我想写下图像数据,然后使用 C 程序将其转换为位图文件。由于每个图像的大小为 800x600,因此最好将文件压缩并显着减小文件。位图格式支持游程编码压缩。

(1) 我一直在寻找 RLE 示例。但是,我找不到任何 24 位位图图像。你能举个例子吗?或者。是否有应用程序可以帮助我保存 24 位位图文件,以便我可以使用十六进制编辑器并了解如何保存格式?

(2) 此外,互联网上到处使用的 RLE 的唯一示例如下:

03 04 05 06 00 03 45 56 67 00 02 78 00 02 05 01
02 78 00 00 09 1E 00 01

该位图将展开如下(两位数值表示单个像素的颜色索引):

04 04 04
06 06 06 06 06
45 56 67
78 78
move current position 5 right and 1 down
78 78
end of line
1E 1E 1E 1E 1E 1E 1E 1E 1E
end of RLE bitmap

为什么 45 56 67 只扩展为相同的东西?

好的,我了解如何编写 24 位 RLE。我已经编写了程序,但是它生成的文件没有被paint-it识别。我不确定我机器上的paint-it 和其他应用程序是否无法识别 24 位 RLE 位图或我的程序生成的位图文件有误。因此:

#include <iostream>
#include <Windows.h>
#include <fstream>
#include <time.h>

using namespace std;

#pragma pack(push)
#pragma pack(1)

struct bitmap_file_header_struct {
    WORD    bfType;        // must be 'BM' 
    DWORD   bfSize;        // size of the whole .bmp file
    WORD    bfReserved1;   // must be 0
    WORD    bfReserved2;   // must be 0
    DWORD   bfOffBits;
} bitmap_file_header;

struct bitmap_file_info_struct {
    DWORD  biSize;            // size of the structure
    LONG   biWidth;           // image width
    LONG   biHeight;          // image height
    WORD   biPlanes;          // bitplanes
    WORD   biBitCount;        // resolution 
    DWORD  biCompression;     // compression
    DWORD  biSizeImage;       // size of the image
    LONG   biXPelsPerMeter;   // pixels per meter X
    LONG   biYPelsPerMeter;   // pixels per meter Y
    DWORD  biClrUsed;         // colors used
    DWORD  biClrImportant;    // important colors
} bitmap_file_info;

#pragma pack(pop)

int main()
{
    // image is 10 repeating pixels of value ff00ff followed by end of scaneline and end of rle
    unsigned char data[] = { 0x0A, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x01}; 

    bitmap_file_header.bfType = 0x4d42; // fixed for bitmap in windows
    bitmap_file_header.bfSize = sizeof(bitmap_file_header) + sizeof(bitmap_file_info) + sizeof(data); 
    bitmap_file_header.bfReserved1 = 0; // fixed 
    bitmap_file_header.bfReserved2 = 0; // fixed
    bitmap_file_header.bfOffBits = sizeof(bitmap_file_header) + sizeof(bitmap_file_info); //

    bitmap_file_info.biSize = sizeof(bitmap_file_info);
    bitmap_file_info.biWidth = 10;
    bitmap_file_info.biHeight = 1;
    bitmap_file_info.biPlanes = 1; // fixed
    bitmap_file_info.biBitCount = 24; // fixed for 24 bit image
    bitmap_file_info.biCompression = 4; // fixed, 4 used to set 24 bit run length encoding
    bitmap_file_info.biSizeImage = sizeof(data); // <-
    bitmap_file_info.biXPelsPerMeter = 0; // fixed
    bitmap_file_info.biYPelsPerMeter = 0; // fixed
    bitmap_file_info.biClrUsed = 0; // all colors used
    bitmap_file_info.biClrImportant = 0; // all colors are important

    std::ofstream myfile;
    myfile.open("output.bmp", ios::out | ios::binary);
    myfile.write((const char *)&bitmap_file_header, sizeof(bitmap_file_header));
    myfile.write((const char *)&bitmap_file_info, sizeof(bitmap_file_info));
    myfile.write((const char *)&data, sizeof(data));
    myfile.close(); 

    return 0;
}

【问题讨论】:

  • 要求我们推荐或查找书籍、工具、软件库、教程或其他场外资源的问题对于 Stack Overflow 来说是无关紧要的,因为它们往往会吸引固执己见的答案和垃圾邮件。相反,请描述问题以及迄今为止为解决该问题所做的工作。
  • 使用zlib,压缩位图,随心所欲。用 zlib 压缩是无损的。
  • 我也将研究 zlib。我第一次遇到 rle,即使在 VHDL 中也很简单。
  • 我刚刚添加了应该生成 24 位 RLE 图像的程序代码。我从 Pakhira Malay K 的“数字图像处理和模式识别”中找到了如何做 24 位 RLE 位图。

标签: c++ bitmap image-compression


【解决方案1】:

RLE 的最基本形式由 &lt;count&gt; &lt;value&gt; 形式的字节对(或帧)组成。显然,在这种形式中,您永远不会有一个为零的 &lt;count&gt; 字节。

这允许使用零作为控制代码,在数据中表示不同类型的帧。

您的特定示例已使用 WMF(Windows 元文件)RLE 格式进行编码。 WMF 允许以下额外类型的帧,所有这些都必须使用00 控制代码引入:

  • 01 - 数据流结束
  • 02 &lt;x&gt; &lt;y&gt; - 相对移动
  • 03 &lt;raw uncompressed data stream follows&gt; 00 - 原始未压缩数据将被空终止。

这解释了为什么您会在未压缩的输出中看到45 56 67

至于为什么格式使用这种方法? RLE 对不重复的数据进行编码效率低下。考虑45 56 67

  • 简单的方法将其呈现为01 45 01 56 01 67(6 个字节);
  • 扩展方法产生00 03 45 56 67 00(也是6个字节)。

如果您需要对01 02 03 04 05 06 07 08 09 0A 进行编码,则更好的例子是:

  • 这将需要使用基本帧的 20 个字节;
  • 但 13 个字节使用 00 03 &lt;data&gt; 00

【讨论】:

  • 微软所说的“绝对模式”是以空值终止的。如果第一个字节是 00,而第二个字节大于 2 (3-255),它将简单地复制许多后续字节(或 RLE4 的情况下的半字节)。为了确保一致性,末尾从图像数据开始填充到字边界,因此它将保持在 2 字节序列中。因此“00 03 45 56 67 00”被读取为将接下来的 3 个字节复制到输出。由于有 3 个字节(奇数),我们需要 1 个填充字节。 “00 06 12 32 15 17 81 91” 这个序列将复制 6 个字节。注意末尾没有没有填充字节
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-31
  • 2010-10-12
  • 1970-01-01
  • 2019-02-02
  • 2017-06-16
  • 2015-04-09
  • 1970-01-01
相关资源
最近更新 更多