按内存大小缩放bmp文件

时间:2014-06-26 15:18:41

标签: c bmp

我有一个bmp文件。我的目标是将文件缩小到总文件大小的70%。我已经将bmp标头和像素数组读入src_buffer。现在我有一个函数,它接入像素数组和src_buffer,位图的宽度(以像素为单位)src_width,位图的高度(以像素为单位)src_height和缩减因子{{1}作为输入。此函数在缩放到r,位图宽度(以像素为单位)dest_buffer和位图高度(以像素为单位)dest_width后写入其输出。 现在我想以bmp格式写回来。这是我遇到困难的地方。要回写,我发现很难填充dest_height structBITMAPINFOHEADER的数据成员。我还应该考虑其他什么。我已经阅读了关于像素阵列行之间的填充。我怎样才能实现它。我在C编码。我不想在这里编写代码的帮助。我想帮助编写一个BMP文件的确切算法。

1 个答案:

答案 0 :(得分:0)

如果你必须缩小bmp文件,我想出了究竟要做什么。我将只讨论24位bmp文件。一个24位的bmp文件由两个标题组成,后跟图像像素数组。 BMP文件中的第一个头称为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;

接下来是struct 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 bytes 在将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 bits