在C / C ++中将1位bmp文件转换为数组

我希望将一个可变高度/宽度的1位bmp文件转换为一个值为0或1的简单二维数组。我没有任何代码和大多数库中的图像编辑经验发现涉及比我需要的更高的比特深度。 对此有任何帮助都会很棒。

这是读取单色.bmp文件的代码

#include  #include  #include  unsigned char *read_bmp(char *fname,int* _w, int* _h) { unsigned char head[54]; FILE *f = fopen(fname,"rb"); // BMP header is 54 bytes fread(head, 1, 54, f); int w = head[18] + ( ((int)head[19]) << 8) + ( ((int)head[20]) << 16) + ( ((int)head[21]) << 24); int h = head[22] + ( ((int)head[23]) << 8) + ( ((int)head[24]) << 16) + ( ((int)head[25]) << 24); // lines are aligned on 4-byte boundary int lineSize = (w / 8 + (w / 8) % 4); int fileSize = lineSize * h; unsigned char *img = malloc(w * h), *data = malloc(fileSize); // skip the header fseek(f,54,SEEK_SET); // skip palette - two rgb quads, 8 bytes fseek(f, 8, SEEK_CUR); // read data fread(data,1,fileSize,f); // decode bits int i, j, k, rev_j; for(j = 0, rev_j = h - 1; j < h ; j++, rev_j--) { for(i = 0 ; i < w / 8; i++) { int fpos = j * lineSize + i, pos = rev_j * w + i * 8; for(k = 0 ; k < 8 ; k++) img[pos + (7 - k)] = (data[fpos] >> k ) & 1; } } free(data); *_w = w; *_h = h; return img; } int main() { int w, h, i, j; unsigned char* img = read_bmp("test1.bmp", &w, &h); for(j = 0 ; j < h ; j++) { for(i = 0 ; i < w ; i++) printf("%c ", img[j * w + i] ? '0' : '1' ); printf("\n"); } return 0; } 

它是普通的C,所以没有指针转换 - 在C ++中使用它时要小心。

最大的问题是.bmp文件中的行是4字节对齐的,这对于单比特图像很重要。 因此我们将线尺寸计算为“width / 8 +(width / 8)%4”。 每个字节包含8个像素,而不是一个,因此我们使用基于k的循环。

我希望其他代码是显而易见的 - 很多人都被告知.bmp标题和pallete数据(我们跳过的8个字节)。

样本图片

预期产量:

 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 0 0 1 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 

以下c代码适用于任何大小的单色位图。 我假设您的位图位于缓冲区中,高度和宽度从文件初始化。 所以

 // allocate mem for global buffer if (!(img = malloc(h * w)) ) return(0); int i = 0, k, j, scanline; // calc the scanline. Monochrome images are // padded with 0 at every line end. This // makes them divisible by 4. scanline = ( w + (w % 8) ) >> 3; // account for the paddings if (scanline % 4) scanline += (4 - scanline % 4); // loop and set the img values for (i = 0, k = h - 1; i < h; i++) for (j = 0; j < w; j++) { img[j+i*w] = (buffer[(j>>3)+k*scanline]) & (0x80 >> (j % 8)); } 

希望这可以帮助。 将它转换为2D现在是一个微不足道的问题:但如果你迷失在这里是将1D数组转换为2D的数学假设r&c是行和列,w是宽度然后:。 c + r * w = r,c

如果你有进一步的言论打击我,我出去了!

让我们想一下a1x7单色位图,即这是一个7像素宽的直线位图。 将此图像存储在Windows操作系统上; 由于7不能被4整除,因此它将在其中填充额外的3个字节。

因此BITMAPINFOHEADER结构的biSizeImage将显示总共4个字节。 尽管如此,biHeight和biWidth成员将正确地指出真正的位图尺寸。

上面的代码将失败,因为7/8 = 0(通过四舍五入,就像所有c编译器一样)。 因此循环“i”将不会执行,因此将“k”。

这意味着向量“img”现在包含与“数据”中包含的像素不对应的垃圾值,即结果不正确。

如果它不满足基本情况,那么通过归纳推理,那么对于一般情况来说它很可能不会有很多好处。