Cross platform super fast single header c++ library to get image size and format without loading/decoding.
The imageinfo don't get image format by file ext name, but infer by file header bytes and character.
As few I/O times as possible! Read as few bytes as possible!
Some test image files are from image-size. Many thanks to @netroy.
Rust version: imageinfo-rs
- avif
- bmp
- cur
- dds
- gif
- hdr (pic)
- heic (heif)
- icns
- ico
- jp2
- jpeg (jpg)
- jpx
- ktx
- png
- psd
- svg
- tga
- tiff (tif)
- webp
- more coming...
cmake -B build .
cmake --build build -- all
cmake --build build -- check
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars32.bat"
cmake -G "NMake Makefiles" -B build .
cmake --build build -- all
cmake --build build -- check
auto imageInfo = getImageInfo<IIFilePathReader>("images/valid/jpg/sample.jpg");
std::cout << "File: " << file << "\n";
std::cout << " - Error : " << imageInfo.getErrorMsg() << "\n";
std::cout << " - Width : " << imageInfo.getWidth() << "\n";
std::cout << " - Height : " << imageInfo.getHeight() << "\n";
std::cout << " - Format : " << imageInfo.getFormat() << "\n";
std::cout << " - Ext : " << imageInfo.getExt() << "\n";
std::cout << " - Full Ext : " << imageInfo.getFullExt() << "\n";
std::cout << " - Mimetype : " << imageInfo.getMimetype() << "\n\n";
You can pass a file path and use IIFilePathReader
,
and there are some builtin reader IIFileReader
, IIFileStreamReader
, IIRawDataReader
FILE *file = fopen("images/valid/jpg/sample.jpg", "rb");
auto imageInfo = getImageInfo<IIFileReader>(file);
fclose(file);
std::ifstream file("images/valid/jpg/sample.jpg", std::ios::in);
auto imageInfo = getImageInfo<IIFileStreamReader>(file);
file.close();
// Suppose we already got data and size
// void *data;
// size_t size;
auto imageInfo = getImageInfo<IIRawDataReader>(IIRawData(data, size));
If you known the file is likely a JPEG, you can provide likely format
parameter to improve performance;
auto imageInfo = getImageInfo<IIFilePathReader>("images/valid/jpg/sample.jpg", II_FORMAT_JPEG);
First, take a look at IIFileReader
, all your need to do is define a class and implement size
and read
method. (not override)
class IIFileReader {
public:
explicit IIFileReader(FILE *file) : m_file(file) {}
inline size_t size() {
if (m_file != nullptr) {
fseek(m_file, 0, SEEK_END);
return ftell(m_file);
} else {
return 0;
}
}
inline void read(void *buf, off_t offset, size_t size) {
fseek(m_file, offset, SEEK_SET);
fread(buf, 1, size, m_file);
}
private:
FILE *m_file = nullptr;
};
Then, let's try to make a reader for Android assets file
class IIAndroidAssetFileReader {
public:
explicit IIAndroidAssetFileReader(AAsset *file) : m_file(file) {}
inline size_t size() {
if (m_file != nullptr) {
return AAsset_getLength(m_file);
} else {
return 0;
}
}
inline void read(void *buf, off_t offset, size_t size) {
AAsset_seek(m_file, offset, SEEK_SET);
AAsset_read(m_file, buf, size);
}
private:
AAsset *m_file = nullptr;
};
// Suppose we have a AAssetManager
// AAssetManager *manager;
// Open with AASSET_MODE_RANDOM mode to seek forward and backward
AAsset *file = AAssetManager_open(manager, "test.png", AASSET_MODE_RANDOM);
auto imageInfo = getImageInfo<IIAndroidAssetFileReader>(file);
AAsset_close(file);
Pretty easy?
Don't be stingy with your star : )