2011-08-02 36 views
2

我正在使用此代码从bmp文件中获取像素。我已经阅读了前面几行的标题和调色板,所以我的FILE *指向像素数组的起始部分。 它读取第一行OK,返回1000这是它应该的,但是当它尝试读取第二行像素时,它返回0.Fread返回0,从BMP文件读取像素

这是接收FILE *,读取像素行和尝试将它们保存到bmp_type中。 fila_alineada是对齐的行大小,必须这样做是因为填充。

bool leer_pixels_8bpp( FILE *fbmp, bmp_t *imagen, 
          const uint32_t fila_alineada, 
          const bool btopdown){ 
int32_t i; 
long x, y; 
int32_t height, width, contador; 
uint8_t *ptmp; 

uint8_t bufferfila[fila_alineada]; 

height = imagen->infoheader.height; 
width = imagen->infoheader.width; 
contador = height; 

i = btopdown ? 1 : -1; 
y = btopdown ? 0 : (height - 1); 

for (; contador--; y += i) /* row loop */ 
{ 
    /* reading row */ 
    if (fread(bufferfila, sizeof(uint8_t), fila_alineada, fbmp) != fila_alineada) 
    { /* HERE is the PROBLEM, it reads ok once, but in the second loop it returns 0 */ 
     fprintf(stderr, "Error reading pixels row.\n"); 
     return false; 
    } 

    ptmp = bufferfila; 
     /* saving pixels into bmp_t */ 
    for (x = 0L; x < width; x++) 
    { 
     imagen->pixels[y][x] = imagen->paleta.colores[ *ptmp++ ]; 
    } 

} 

return true; 

}

我已经与型动物BMP的尝试!问题出现在这里还是应该考虑查看整个代码? 希望有人可以帮助我,在此先感谢。

+0

你确定它返回0,还是返回一个不同于''fila_alineada''的值?如果是这种情况,那么预计已经达到文件结尾... – Fred

+0

if(fread)块之后你能注释掉代码吗?如果指针遭到破坏,fread可能会失败。 – Shash316

+0

嘿家伙感谢您的帮助,我设法让它工作。 我使用的开关调用leer_1bpp/8bpp/24bpp(3种不同的功能),具体取决于每个像素的文件位。但是我错过了每个交换机上的'中断'。 Dot知道如何,但它现在工作。 我想检查调试它看到fread的值,但由于某种原因kdbg说在当前上下文中没有符号fread,在我把这些休息之前它显示了整个fread(.........)返回值。 无论如何,它正在阅读好,因为我已经把一些ftells看看它已经读了多少字节,一切都很好。 谢谢! – nitrnitr

回答

2

从您的代码看来,您并没有读取图片的width ...而是您读取的数量为fila_alineada。你提到fila_alineada是因为“填充”而对齐的行大小,但BMP文件应该只在末尾有足够的填充以将每行扩展到4个字节的倍数......尽管这很容易通过将实际像素阵列数据大小除以图像中的行数,从BITMAPINFOHEADER计算得出。像素阵列数据大小存储在标头偏移0x22处。正如我确信你已经正确推断的那样,高度是偏移量0x16。因此,参数fila_alineada非常多余(即,您可以将其删除),并且您可能正在错误地计算此值。我只是简单地使用标题中的信息来计算必要的缓冲区大小,以将信息保存在图像的给定行中。其次,如果您只是试图将文件中的BITMAPINFOHEADER信息复制到一个具有代表性的头结构的缓冲区中,请记住编译器可能填充了用于字节对齐目的的结构...因此,对于您不应该简单地从文件中读取整个头文件,然后尝试使用memcpy()将缓冲区写入BITMAPINFOHEADER结构中。您应该从文件中逐个读取标题值,并将这些值分别存储到代表BITMAPINFOHEADER的任何结构中。否则,如果你执行前者,只需读取文件的前N个字节,并将其复制到结构中,由于字节对齐问题,最终可能会复制不正确的值,因此所有您尝试从该结构读回的值将不会表示与您的位图文件相关联的值。

+0

感谢您的回答,我已经解决了上述问题,无论如何,我会回答你! :) 1)我正在使用fila_alineada,正如我所说的,以计算每行必须读取的数量。如果我有一个8bpp bmp,宽度为45像素,第一行应该有360位。如你所说,行大小应该是4个字节(32位)。由于360不是32的倍数,所以我做的是:bitsperrow = width * bitsperpixel if(bitsperrow%32) bitsperrow + = 32 - (bitsperrow%32) – nitrnitr

+0

我做的是:bitsperrow = width * bitsperpixel; (bitsperrow%32)bitsperrow + = 32 - (bitsperrow%32)} 然后我将bitsperrow除以8以获得该行上的字节数量(fila_alineada)。 这只是3行! 约2),是的,我意识到这一点,infoheader不是一个对齐的结构,我不得不读取第一个bmp的魔术数字,然后阅读其他的,它工作正常。 在阅读完printf后,我已经用printf打印了这两个头文件,并且它们可以工作! 再次感谢:) – nitrnitr

+0

您的计算看起来不错,但只是说,您不必跳过那些箍环...只需使用BITMAPINFOHEADER字段偏移量0x22来获取像素数据的字节数,然后除以像素行的数量......这将给你每行的字节数,而不必计算任何填充偏移量。 – Jason