从.NET高回来,想要制作一个更快,更高效的图像库我想我会尝试手动完成所有操作最大控制 空气 学习经验,你知道吗?
所以,我正在阅读一些测试位图(.bmp扩展名)。在读取一些位图文件头时,我注意到大小块给了我负值。
我设法在某种程度上追查了这个问题,但我在调试方面并不是那么出色。当我用同一块代码替换我的get_u32
函数 - 内联 - 它给了我正确的大小。我想有一些隐式的类型转换正在进行中,但我无法说清楚。
这是相关代码
typedef struct IMGLIB_API{
unsigned short type;
unsigned long size;
unsigned short reserved1;
unsigned short reserved2;
unsigned long offbits;
} BITMAP_FILE_HEADER;
unsigned short get_u16(char b0, char b1){
return ((b1 << 8) | b0);
}
unsigned long get_u32(char b0, char b1, char b2, char b3){
return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
}
IMAGE_DATA bitmap_loader(const char* file_path){
IMAGE_DATA r;
ifstream ifs;
const unsigned short valid_formats[] = {
16973, // BM - Windows 3.1x, 95, NT, ...
16961, // BA - OS/2 struct bitmap array
17225, // CI - OS/2 struct color icon
17232, // CP - OS/2 const color pointer
18755, // IC - OS/2 struct icon
20564 // PT - OS/2 pointer
};
const int BMP_FILE_HEADER_SIZE = 14;
ifs.open(file_path, ifstream::in | ifstream::binary);
unsigned char* rhead = new unsigned char[BMP_FILE_HEADER_SIZE];
ifs.read((char*)rhead, BMP_FILE_HEADER_SIZE);
BITMAP_FILE_HEADER bmp_header;
bmp_header.type = get_u16(rhead[0], rhead[1]);
bmp_header.size = get_u32(rhead[2], rhead[3], rhead[4], rhead[5]); // - doesn't work
//bmp_header.size = (rhead[5] << 24) | (rhead[4] << 16) | (rhead[3] << 8) | rhead[2]; // - works
bmp_header.reserved1 = get_u16(rhead[6], rhead[7]);
bmp_header.reserved2 = get_u16(rhead[8], rhead[9]);
bmp_header.offbits = get_u32(rhead[10], rhead[11], rhead[12], rhead[13]); // correct, reports 54 bytes
// TODO: check if valid bitmap type
// TODO: read the dib header
// TODO: read in pixel data and decompress (if needed)
r.size = bmp_header.size;
r.type = img_type::IM_BITMAP;
ifs.close();
delete rhead;
rhead = 0;
return r;
}
例如,当加载大小为86 454字节的特定位图时,使用函数get_u32
时得到-74。我认为将return设置为unsigned,而struct member设置为unsigned意味着它不能被..签名。最好将自己重命名为Snow,因为显然我什么都不知道抱怨
随意提供有关优化/更好方法的一些提示。
答案 0 :(得分:2)
char
可以是已签名或未签名的。转换为更大类型符号时的签名字符扩展。当你对char进行数学运算时,它会转换为int
,这是一个更大的类型。
进行位操作时,默认为unsigned。
unsigned short get_u16(char b0, char b1){
return ((b1 << 8) | b0);
}
是问题的一个例子。 b0
可以延长标志。
实现可以将char视为已签名或未签名。