Fread返回0,从BMP文件中读取像素

时间:2011-08-02 02:07:41

标签: c pixels bmp

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

这是接收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's!问题是在这里还是应该考虑审查整个代码? 希望有人可以帮助我,提前谢谢。

1 个答案:

答案 0 :(得分:2)

从您的代码中可以看出,您没有阅读图片width的内容......而是您正在阅读fila_alineada的数量。你提到由于“填充”,fila_alineada是对齐的行大小,但是BMP文件最后应该只有足够的填充以将每行扩展到4个字节的倍数...这应该是一个值虽然可以通过将实际像素阵列数据大小除以图像中的行数来轻松地从BITMAPINFOHEADER计算出来。像素阵列数据大小存储在标题中的偏移量0x22处。我确定你已经正确推导出的高度是偏移量0x16。因此,参数fila_alineada几乎是多余的(即,您可以删除它),并且您可能错误地计算此值。我只想使用标题中的信息来计算将信息保存在图像的给定行中所需的缓冲区大小。

其次,如果您只是尝试将文件中的BITMAPINFOHEADER信息复制到一个代表性的标头结构缓冲区中,请记住编译器可能已填充结构以进行字节对齐...因此为了安全起见原因你不应该简单地从文件中读取整个头,然后尝试使用memcpy()将缓冲区写入BITMAPINFOHEADER结构。您应该从文件中逐个读取标头值,并将这些值分别存储到代表BITMAPINFOHEADER的任何结构中。否则,如果您执行前者,只需尝试读取文件的前N个字节,并将其复制到结构中,您可能最终因为字节对齐问题而复制不正确的值,因此所有您尝试从该结构读回的值不代表与位图文件关联的值。