int LCUI_ReadBMPHeader(LCUI_ImageReader reader) { size_t n; uint16_t buffer[8]; LCUI_BMPReader bmp_reader = reader->data; INFOHEADER *info = &bmp_reader->info; reader->header.type = LCUI_UNKNOWN_IMAGE; if (reader->type != LCUI_BMP_READER) { return -EINVAL; } n = reader->fn_read(reader->stream_data, buffer, 14); /* 受到字节对齐影响,直接将读到的写到结构体变量里会让最后一个成员 * 变量的值不正常,因此需要手动为其成员变量赋值 */ BMPHeader_Init(&bmp_reader->header, buffer); if (n < 14 || bmp_reader->header.type != 0x4D42) { return -2; } n = reader->fn_read(reader->stream_data, info, sizeof(INFOHEADER)); if (n < sizeof(INFOHEADER)) { return -2; } reader->header.width = info->width; reader->header.height = info->height; reader->header.type = LCUI_BMP_IMAGE; if (info->bits == 24) { reader->header.color_type = LCUI_COLOR_TYPE_RGB; reader->header.bit_depth = 24; } return 0; }
int LCUI_ReadBMP( LCUI_ImageReader reader, LCUI_Graph *graph ) { size_t n, row, bytes_per_row; unsigned char *buffer, *dest; LCUI_BMPReader bmp_reader = reader->data; INFOHEADER *info = &bmp_reader->info; if( reader->type != LCUI_BMP_READER ) { return -EINVAL; } if( reader->header.type == LCUI_UNKNOWN_IMAGE ) { if( LCUI_ReadBMPHeader( reader ) != 0 ) { return -ENODATA; } } /* 信息头中的偏移位置是相对于起始处,需要减去当前已经偏移的位置 */ n = bmp_reader->header.offset - bmp_reader->info.size - 14; reader->fn_skip( reader->stream_data, n ); if( 0 != Graph_Create( graph, info->width, info->height ) ) { return -ENOMEM; } /* 暂时不实现其它色彩类型处理 */ if( info->bits != 24 ) { return -ENOSYS; } bytes_per_row = (info->bits * info->width + 31) / 32 * 4; if( bytes_per_row < graph->bytes_per_row ) { return -EINVAL; } buffer = malloc( bytes_per_row ); if( !buffer ) { return -ENOMEM; } /* 从最后一行开始保存 */ dest = graph->bytes + graph->bytes_per_row * (graph->height - 1); for( row = 0; row < info->height; ++row ) { n = reader->fn_read( reader->stream_data, buffer, bytes_per_row ); if( n < bytes_per_row ) { break; } memcpy( dest, buffer, graph->bytes_per_row ); dest -= graph->bytes_per_row; if( reader->fn_prog ) { reader->fn_prog( reader->prog_arg, 100.0f * row / info->height ); } } free( buffer ); return 0; }