2014-10-29 102 views
2

我想读取BMP文件中所有像素的RGB值。 我在C++代码,这看起来像:从位图读取RGB - 错误的值(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 pixels bitmap file with white and black colors - 24bit format

其是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)。这意味着这个文件中有一些额外的信息。

+0

你确定格式是24位BMP,而不是一个PNG重命名? – 2014-10-29 13:37:05

+6

6像素宽的BMP图像将在每行像素之后填充。 (一行像素必须包含可以被4整除的字节数,所以6x3在每个像素之后有两个填充像素,您还应该查看适当的头信息以确保您的BMP是24位RGB bitmap – 2014-10-29 13:38:54

+3

位图文件格式不是那么容易(它取决于图像格式是如何写在磁盘上的)这就是为什么1)为什么你不使用WinSDK结构的BMP? 2)它非常不可移植(读取一个字节数组并访问未对齐的整数...) – 2014-10-29 13:39:25

回答

5

位图文件包括:

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

最后4个字节是偏移,其中RGB值开始7A = after 122 Bytes

DIB header The first 4 bytes是大小:
6c 00 00 00 -> 108 Bytes so BITMAPV4HEADER

8字节是宽度和高度(像素):
08 00-00 00 0c 00-00 00 width height each 4 Bytes

所以你的位图6x128x12!有没有必要进行填充,因为8×3 = 24是4的

实际像素从0x7A - 0x199 从最后一排开始,并持续向上,从左至右多,位图是:

enter image description here

的文件大小是正确的:

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包含实际的像素,但顺序为左>右和下>起来意味着第一像素左下角的一个在的形象。

+0

你说得对。我正在尝试不同的图像和过去不是那个十六进制转储(从图像8x12不是6x12像素)。 – trojek 2014-10-30 20:31:01