【问题标题】:Read RGB from bitmap - wrong values (of RGB); c++从位图读取 RGB - 错误值(RGB); C++
【发布时间】:2014-12-25 05:46:34
【问题描述】:

我想从 BMP 文件中读取所有像素的 RGB 值。 我有 C++ 代码,看起来像:

#include <iostream>
#include <fstream>

using namespace std;

int main () {
    FILE *streamIn;
    streamIn = fopen("./Untitled.bmp", "r");
    if (streamIn == (FILE *)0) {
        printf("File opening error ocurred. Exiting program.\n");
        return 0;
    }

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, streamIn);

    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

    int image[width*height][3];
    int i = 0;

    for(i=0;i<width*height;i++) {
        image[i][2] = getc(streamIn);
        image[i][1] = getc(streamIn);
        image[i][0] = getc(streamIn);
        printf("pixel %d : [%d,%d,%d]\n",i+1,image[i][0],image[i][1],image[i][2]);
    }

    fclose(streamIn);

    return 0;
}

和这样的图像(网格叠加):

这是 6x12 像素的文件,有两种颜色 - 黑色和白色。

我试图找出为什么在以图像作为参数执行上述代码后,我不仅得到 RGB 像素:[0,0,0] 和 [255,255,255],而且还得到 [0,248,0],[ 7,224,0] 等。

该文件的十六进制转储是:

0000-0010:  42 4d 9a 01-00 00 00 00-00 00 7a 00-00 00 6c 00  BM...... ..z...l.
0000-0020:  00 00 08 00-00 00 0c 00-00 00 01 00-18 00 00 00  ........ ........
0000-0030:  00 00 20 01-00 00 13 0b-00 00 13 0b-00 00 00 00  ........ ........
0000-0040:  00 00 00 00-00 00 42 47-52 73 00 00-00 00 00 00  ......BG Rs......
0000-0050:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00  ........ ........
0000-0060:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00  ........ ........
0000-0070:  00 00 00 00-00 00 00 00-00 00 02 00-00 00 00 00  ........ ........
0000-0080:  00 00 00 00-00 00 00 00-00 00 ff ff-ff ff ff ff  ........ ........
0000-0090:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-00a0:  ff ff ff ff-ff 00 00 00-00 00 00 00-00 00 00 00  ........ ........
0000-00b0:  00 00 00 00-00 00 00 ff-ff ff ff ff-ff 00 00 00  ........ ........
0000-00c0:  00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 ff  ........ ........
0000-00d0:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-00e0:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-00f0:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0100:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0110:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0120:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0130:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0140:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0150:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0160:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0170:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0180:  ff ff ff ff-ff ff ff ff-ff ff ff ff-ff ff ff ff  ........ ........
0000-0190:  ff ff 00 00-00 ff ff ff-00 00 00 ff-ff ff 00 00  ........ ........
0000-019a:  00 ff ff ff-00 00 00 ff-ff ff                    ........ ..

文件大小为 410 字节。它应该是 270 (6*12*3 + 54)。这意味着这个文件中有一些额外的信息。

【问题讨论】:

  • 6 像素宽的 BMP 图像在每行像素后都有填充。 (一行像素必须包含可被 4 整除的字节数,因此 6x3 在每 6 个像素之后有两个填充像素。您还应该查看适当的标题信息以确保您的 BMP 是 24 位 RGB位图。
  • 位图文件格式并不容易(它取决于图像格式如何写入磁盘)。那就是为什么 1) 为什么不使用 WinSDK 结构来处理 BMP? 2)它非常不便携(读取字节数组并访问未对齐的整数......)
  • 为了简洁起见:using namespace 是 C++,其余代码和标签为 C。是哪个?
  • @trojek:填充是存储为 24 位颜色的 BMP 文件的问题;在您的情况下,这可能不是问题。我真的怀疑你有单色位图或其他东西。检查标题中的颜色深度。
  • 您确定从正确的索引读取像素缓冲区吗?一些应用程序在 DIB (40) 标头之后添加数据位,因此,使实际像素从偏移量 52、54、56、102 或 140 等开始...编辑:并且 - 虽然有点“意外” - 那么位图压缩? (RLE、DXT...)

标签: c++ image bitmap rgb


【解决方案1】:

您的位图文件包括:

位图文件头:14 字节
42 4d 9a 01-00 00 00 00-00 00 7a 00-00 00

最后 4 个字节是 rgb 值开始的 偏移量7A = after 122 Bytes

DIB 标头 first 4 bytes 是大小:
6c 00 00 00 -&gt; 108 Bytes so BITMAPV4HEADER

接下来的 8 字节 是以像素为单位的宽度和高度:
08 00-00 00 0c 00-00 00 width height each 4 Bytes

所以你的位图不是 6x12 而是8x12!不需要填充,因为 8x3 = 24 是 4 的倍数。

实际像素来自0x7A - 0x199 从最后一行开始向上,从左到右,位图为:

文件大小正确:

file size = Bitmap File Header + DIB header + rgb Bytes = 14 + 108 + 8 * 12 * 3 = 410

读取图像中的特定像素:

加载整个位图文件

char *buff;
char rgb[8 * 12 * 3]; //for simplicity
fptr = fopen("....bmp", "rb");

fseek(fptr, 0, SEEK_END);
int file_Size = ftell(fptr);
fseek(fptr, 0, SEEK_SET);

buff = malloc(file_Size * sizeof(char));

fread(buff, sizeof(char), file_Size, fptr);

memmove(rgb, buff[0x7A], 8 * 12 * 3);

现在rgb 包含实际像素,但顺序是left->right and down->up,这意味着第一个像素是left bottom图片。

【讨论】:

  • 你是对的。我正在尝试不同的图像并且过去不是那个十六进制转储(从图像 8x12 而不是 6x12 像素)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 2012-12-04
相关资源
最近更新 更多