从C中的BMP文件中读取数据



我在从bmp文件中读取像素时遇到问题。它可能是在行的末尾有填充或base64填充的东西。我不知道。我已经为此挣扎了几天,无法继续前进,因为下一个任务需要解决这个问题。我只分享代码的重要部分,因为读取bmp标头工作正常(测试有0次失败(。

bmp.c

struct pixel* read_data(FILE* stream, const struct bmp_header* header){
if(stream == NULL || header == NULL){
return 0;
}
// w == 1 && p == 1;   w == 2 && p == 2;   w == 3 && p == 3;   w == 4 && p == 0  
int padding = header->width % 4; 
int num_of_pixels = header->width * header->height;
struct pixel* Pixel[num_of_pixels];
fseek(stream, 54, SEEK_SET); //move 54B (header size)
int index_p = 0;
for(int i = 0; i < header->height; i++){
for(int j = 0; j < header->width; j++){
Pixel[index_p] = malloc(sizeof(struct pixel));
fread(&(Pixel[index_p]->blue), 1, 1, stream); 
fread(&(Pixel[index_p]->green), 1, 1, stream); 
fread(&(Pixel[index_p]->red), 1, 1, stream); 
index_p++;
}
fseek(stream, padding, SEEK_CUR);  //padding at the end of row
}
return *Pixel;
}

bmp.h

struct pixel {
uint8_t blue;
uint8_t green;
uint8_t red;
//uint8_t alpha;
} __attribute__((__packed__));
/**
* Read the pixels
*
* Reads the data (pixels) from stream representing the image. If the stream
* is not open or header is not provided, returns `NULL`.
*
* @param stream opened stream, where the image data are located
* @param header the BMP header structure
* @return the pixels of the image or `NULL` if stream or header are broken
*/
struct pixel* read_data(FILE* stream, const struct bmp_header* header);

标题(如果需要((基本上我们只使用24位颜色(

struct bmp_header{
uint16_t type;              // "BM" (0x42, 0x4D)
uint32_t size;              // file size
uint16_t reserved1;         // not used (0)
uint16_t reserved2;         // not used (0)
uint32_t offset;            // offset to image data (54B)
uint32_t dib_size;          // DIB header size (40B)
uint32_t width;             // width in pixels
uint32_t height;            // height in pixels
uint16_t planes;            // 1
uint16_t bpp;               // bits per pixel (24)
uint32_t compression;       // compression type (0/1/2) 0
uint32_t image_size;        // size of picture in bytes, 0
uint32_t x_ppm;             // X Pixels per meter (0)
uint32_t y_ppm;             // X Pixels per meter (0)
uint32_t num_colors;        // number of colors (0)
uint32_t important_colors;  // important colors (0)
} __attribute__((__packed__));

main.c我不需要为被调用的函数分配任何变量,因为我们有一个测试程序,我只需要在主中调用它们

int main(){
struct bmp_header* header;
FILE *stream = fopen("./assets/square.2x3.bmp", "rb");
header = read_bmp_header(stream);
read_data(stream, header);
read_bmp(stream);
struct bmp_image* image;
image = malloc(sizeof(struct bmp_image));
free_bmp_image(image);  
fclose(stream);
return 0;
}

测试(还有更多的测试,但这应该足够了(

1: 
FILE* stream = "Qk0+AAAAAAAAADYAAAAoAAAAAgAAAAEAAAABABgAAAAAAAgAAAAjLgAAIy4AAAAAAAAAAAAA/wAAAP8AAAA="; // base64 encoded stream
struct bmp_header* header = read_bmp_header(stream);
fseek(stream, offset, SEEK_SET);
Assertion 'read_data(stream, header) == "/wAAAP8A"' failed. [got "/wAAFctV"]
2: 
FILE* stream = "Qk1GAAAAAAAAADYAAAAoAAAAAgAAAAIAAAABABgAAAAAABAAAAAjLgAAIy4AAAAAAAAAAAAA/wAAAAAAAAAAAP8A/wAAAA=="; // base64 encoded stream
struct bmp_header* header = read_bmp_header(stream);
fseek(stream, offset, SEEK_SET);
Assertion 'read_data(stream, header) == "/wAAAAAAAAD/AP8A"' failed. [got "/wAAAAAAAAAAAAAA"]

因此,在"=="之后是预期的结果,括号中是我的代码的结果。正如我提到的,它可能是有填充的东西,因为它开始得很好,但结束得不好。谢谢你的帮助。

简短回答:将填充设置为(4-((3*width)%4))%4

长答案

您的代码包括:

int padding = header->width % 4; 
//Some lines of code
fseek(stream, padding, SEEK_CUR);

在位图中,添加填充,直到每一行都是4字节的倍数。您将填充作为width % 4

首先,每个像素占用3个字节(对于rgb(。所以应该是(3*width)%4。接下来,我们需要从4个字节中减去它(因为填充是4-pixels occupied(。所以填充应该是4-((3*width)%4)。另一个小的修改是,如果(3*width)%4==0,那么填充将变为4(而我们期望它为0(。所以我们采取另一个mod4只是为了确保

所以填充会变成(4-((3*width)%4))%4

编辑:

正如用户Craig Estey在评论中指出的那样,最好使用sizeof(struct pixel(而不是3

相关内容

  • 没有找到相关文章

最新更新