c - 按内存大小缩放 bmp 文件

标签 c bmp

我有一个 bmp 文件。我的目标是将文件缩小到总文件大小的 70%。我已将 bmp header 和像素数组读入 src_buffer 中。现在我有一个函数,它接收像素数组和src_buffer,位图的宽度(以像素为单位)src_width,位图的高度(以像素为单位)src_height 和缩减因子 r 作为输入。此函数在缩放到 dest_buffer、位图宽度(以像素为单位)dest_width 和位图高度(以像素为单位)dest_height 后写入输出。 现在我想把它写回bmp格式。这就是我面临困难的地方。回写一下,我发现填充 struct BITMAPINFOHEADERBITMAPFILEHEADER 的数据成员很困难。我还应该考虑什么?我读过有关像素阵列行之间的填充的内容。我怎样才能实现它。我正在用 C 进行编码。我不需要这里编码方面的帮助。我想帮助您了解编写 BMP 文件的精确算法。

最佳答案

我想出了如果必须缩小 bmp 文件到底该怎么做。我只讨论 24 位 bmp 文件。 24 位 bmp 文件由两个 header 和后跟图像像素数组组成。 BMP 文件中的第一个 header 称为 BITMAPFILEHEADER,总大小为 14 字节。看起来有点像这样。

typedef struct 
{ 
    uint16_t bfType; //2 bytes storing "BM". This means that it is bmp
    uint32_t bfSize; //4 bytes total file size of bmp. Including both the header and pixel array
    uint16_t bfReserved1; //Always 0
    uint16_t bfReserved2; //Always 0
    uint32_t bfOffBits;   // stores 54. (40 +14)Total size of the headers.
} __attribute__((__packed__)) 
BITMAPFILEHEADER;

接下来是 BITMAPINFOHEADER 结构体,总大小为 40 字节。以下是其声明

typedef struct
{
    uint32_t biSize; //40 bytes. Size of the header.
    int32_t biWidth; //Width of the bitmap image. How many pixel wide is the image. 
    int32_t biHeight; //Height of the bitmap image.
    uint16_t biPlanes; // Always 1.
    uint16_t biBitCount; //24 for 24 bit bitmap. Number of bit representing each pixel.
    uint32_t biCompression; 
    uint32_t biSizeImage; //Total size of bitmap pixel array including padding.
    int32_t biXPelsPerMeter; 
    int32_t biYPelsPerMeter; 
    uint32_t biClrUsed;
    uint32_t biClrImportant;
} __attribute__((__packed__))
BITMAPINFOHEADER; 

现在,这两个结构后面紧跟着像素阵列。单个像素由 3 个字节表示。说它是由

代表的
typedef struct
{
    uint8_t rgbtBlue;
    uint8_t rgbtGreen;
    BYTE  rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;

我们有一个以线性方式放置的 RGBTRIPLE 数组。准确地说,像素数由以下公式给出。

 BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight

存储任何图像信息所需的内存量由下式给出:

 BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight * sizeof(RGBTRIPLE)

因此,任何单行所需的内存为:

BITMAPINFOHEADER.biWidth * sizeof(RGBTRIPLE)

这里有一个问题,如果任何单行的总内存不是 4 字节的倍数,则会向该行添加填充,使其成为 4 的倍数。假设图像大小为 41X30。存储一行所需的字节数为 41*3 = 123bytes。因此,将以 bmp 格式向该行添加 1 个字节的填充。因此BITMAPINFOHEADER.biSizeImage = 30 * 124 = 3720 字节 将 bmp 解码为原始像素数组时,应始终记住删除这些填充。 同样,在写回 bmp 文件(编码)时,请确保添加这些额外的填充。 另请注意,

BITMAPINFOHEADER.biSizeImage = (BITMAPINFOHEADER.biWidth * sizeof(RGBTRIPLE) +padding) * BITMAPINFOHEADER.biHeight

或者可以用公式计算:

BITMAPINFOHEADER.biSizeImage = (((BITMAPINFOHEADER.biWidth * bmpiheader.biBitCount) + 31) / 32) * 4 * BITMAPINFOHEADER.biHeight

请注意,对于 24 位位图,BITMAPINFOHEADER.biBitCount = sizeof(RGBTRIPLE) * 8 = 24 位

关于c - 按内存大小缩放 bmp 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24434337/

相关文章:

c - 如何从 fgets 中检测空字符串

c - System V中x86_64的C中浮点值的调用约定是什么?

c++ - CUDA C++ 中的变量分配 - 无法分配设备变量

image - 从 Lua 中的 ICO 文件中读取 16x16 图像的 AND 掩码

c++ - 将十六进制数据输出到文件的正确方法是什么?

更改结构数组元素中的值

C - 段错误 - 链表的 insert_sort 函数

c - ELF 文件版本

c++ - 如何使用 CImage 正确加载灰度 BMP 的字符数组?

java - 如何从存储在 txt 文件中的 rgb 数据创建 bmp 文件?