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