跨平台高性能的C++单个头文件库,在不加载/解码图片的情况下,获取图片文件类型和大小。
imageinfo 并不是通过扩展名来识别图片格式,而是通过文件头和文件格式特征来判断图片格式。
尽可能少的I/O次数!读取尽可能少的字节数!
部分测试图片文件来源于 image-size ,感谢 @netroy
Rust 版本: imageinfo-rs
imageinfo 已经重构,如果你使用的是旧版本,请查看 v1
分支。
- avif
- bmp
- cur
- dds
- gif
- hdr (pic)
- heic (heif)
- icns
- ico
- jpeg2000 code stream (j2k, j2c, jpc, jhc)
- jpeg2000 (jp2, jpx, jph)
- jpeg (jpg)
- ktx
- png
- psd
- qoi
- svg
- tga
- tiff (tif)
- webp
- 更多...
imageinfo 可以通过 vcpkg 安装
vcpgk install imageinfo
cmake -B build .
cmake --build build -- all
cmake --build build -- check
打开 Visual Studio Command Prompt 并执行下面的命令
cmake -G "NMake Makefiles" -B build .
cmake --build build -- all
cmake --build build -- check
const char *file = "images/valid/jpg/sample.jpg";
auto info = imageinfo::parse<imageinfo::FilePathReader>(file);
std::cout << "File: " << file << "\n";
std::cout << " - Error : " << info.error_msg() << "\n";
std::cout << " - Width : " << info.size().width << "\n";
std::cout << " - Height : " << info.size().height << "\n";
std::cout << " - Format : " << info.format() << "\n";
std::cout << " - Ext : " << info.ext() << "\n";
std::cout << " - Full Ext : " << info.full_ext() << "\n";
std::cout << " - Mimetype : " << info.mimetype() << "\n\n";
可以使用 imageinfo::FilePathReader
然后直接传入文件路径,
不同类型可以使用不同的 Reader, 如 imageinfo::FileReader
, imageinfo::FileStreamReader
, imageinfo::RawDataReader
FILE *file = fopen("images/valid/jpg/sample.jpg", "rb");
auto info = imageinfo::parse<imageinfo::FileReader>(file);
fclose(file);
std::ifstream file("images/valid/jpg/sample.jpg", std::ios::in | std::ios::binary);
auto info = imageinfo::parse<imageinfo::FileStreamReader>(file);
file.close();
// 假设已经得到了 data 和 size
// void *data;
// size_t size;
auto info = imageinfo::parse<imageinfo::RawDataReader>(imageinfo::RawData(data, size));
如果你事先知道一个文件大概率是JPEG格式, 你可以提供额外的 likely_formats
参数来提升性能;
auto imageInfo = imageinfo::parse<imageinfo::FilePathReader>("images/valid/jpg/sample.jpg", {II_FORMAT_JPEG});
首先,来看一下 imageinfo::FileReader
, 要做的只是定义一个类,然后实现 size
和 read
方法。(非override)
class FileReader {
public:
explicit FileReader(FILE *file) : file_(file) {}
inline size_t size() {
if (file_ != nullptr) {
fseek(file_, 0, SEEK_END);
return ftell(file_);
} else {
return 0;
}
}
inline void read(void *buf, off_t offset, size_t size) {
fseek(file_, offset, SEEK_SET);
fread(buf, 1, size, file_);
}
private:
FILE *file_ = nullptr;
};
然后,让我们来尝试实现一个Android assets文件的Reader
class AndroidAssetFileReader {
public:
explicit AndroidAssetFileReader(AAsset *file) : file_(file) {}
inline size_t size() {
if (file_ != nullptr) {
return AAsset_getLength(file_);
} else {
return 0;
}
}
inline void read(void *buf, off_t offset, size_t size) {
AAsset_seek(file_, offset, SEEK_SET);
AAsset_read(file_, buf, size);
}
private:
AAsset *file_ = nullptr;
};
// 假设已经得到了 AAssetManager
// AAssetManager *manager;
// 以 AASSET_MODE_RANDOM 模式打开以支持双向seek
AAsset *file = AAssetManager_open(manager, "test.png", AASSET_MODE_RANDOM);
auto imageInfo = imageinfo::parse<imageinfo::AndroidAssetFileReader>(file);
AAsset_close(file);
很简单不是吗?
请不要吝啬你的Star : )