Fread возвращает 0, считывая пиксели из BMP-файла


Я использую этот код, чтобы получить пиксели из файла bmp. Я уже читал заголовки и палитру в предыдущих строках, поэтому мой файл * указывает на начало массива пикселей. Он считывает первую строку OK, возвращает 1000, что и должно быть, но когда он пытается прочитать вторую строку пикселей, он возвращает 0.

Это функция, которая получает файл *, считывает строки пикселей и пытается сохранить их в 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;

}

Я пробовал с разными БМП! Проблема здесь, или я должен рассмотреть возможность пересмотра всего кода? Надеюсь, кто-нибудь мне поможет, заранее спасибо.

1 2

1 ответ:

Из вашего кода кажется, что вы не читаете, что такое width изображения ... скорее Вы читаете количество fila_alineada. Вы упомянули, что fila_alineada был выровнен размер строки из-за" заполнения", но BMP-файлы должны иметь только достаточное заполнение в конце, чтобы расширить каждую строку до кратного 4-байта ... это должно быть значение, хотя оно легко вычисляется из BITMAPINFOHEADER путем деления фактического размера данных массива пикселей на количество строк в изображении. Пиксель-массив размер данных хранится в заголовке со смещением 0x22. Высота, как я уверен, вы правильно определили, находится на смещении 0x16. Таким образом, аргумент fila_alineada в значительной степени избыточен (т. е. вы можете удалить его), и вы можете вычислить это значение неправильно. Я бы просто использовал информацию в заголовке, чтобы вычислить размер буфера, необходимого для сохранения информации в заданной строке изображения.

Во-вторых, если вы просто попытались скопировать информацию BITMAPINFOHEADER из файла в буфер, который является некоторой репрезентативной структурой заголовка, имейте в виду, что компилятор, возможно, добавил структуру для целей выравнивания байтов ... поэтому из соображений безопасности вы не должны просто читать весь заголовок из файла, а затем пытаться использовать memcpy() для записи буфера в структуру BITMAPINFOHEADER. Вы должны прочитать значения заголовка по одному из файла и сохранить эти значения по отдельности в любой структуре, представляющей BITMAPINFOHEADER. В противном случае, если вы в первом случае, просто попытавшись прочитать первые N байтов файла и скопировать их в структуру, вы можете в конечном итоге из-за проблем с выравниванием байтов скопировать неверные значения, и поэтому все значения, которые вы пытаетесь прочитать из этой структуры, не будут представлять значения, связанные с вашим растровым файлом.