Added BIMG_CONFIG_USE_WIC and BIMG_CONFIG_USE_STB_IMAGE. (#156)

This commit is contained in:
Branimir Karadžić
2026-10-01 13:16:44 -07:00
committed by GitHub
parent 6b08e87de2
commit c085da683d
5 changed files with 301 additions and 166 deletions

View File

@@ -1797,7 +1797,7 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PNM)
// nothing
#else
static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
@@ -1806,7 +1806,7 @@ static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
}
#endif
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD)
#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PNM)
// nothing
#else
static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)

View File

@@ -131,6 +131,25 @@ namespace bimg
, bx::Error* _err
);
///
bool imageInfoFinalize(
ImageContainer& _imageContainer
, ImageParser::Enum _parser
, TextureFormat::Enum _format
, uint32_t _width
, uint32_t _height
, bx::Error* _err
);
///
bool imageParseInfoWic(
bx::AllocatorI* _allocator
, ImageContainer& _imageContainer
, const void* _data
, uint32_t _size
, bx::Error* _err
);
} // namespace bimg
#endif // BIMG_P_H_HEADER_GUARD

View File

@@ -66,6 +66,25 @@
# define BIMG_CONFIG_PARSE_ENABLE 1
#endif // BIMG_CONFIG_PARSE_ENABLE
/// Use WIC (Windows Imaging Component) instead of the bundled decoders for PNG, JPEG, BMP and GIF.
/// Which of them it decodes is dictated by their `BIMG_CONFIG_PARSE_*`. Windows only.
///
#ifndef BIMG_CONFIG_USE_WIC
# define BIMG_CONFIG_USE_WIC 0
#endif // BIMG_CONFIG_USE_WIC
#if BIMG_CONFIG_USE_WIC && !BX_PLATFORM_WINDOWS
# undef BIMG_CONFIG_USE_WIC
# define BIMG_CONFIG_USE_WIC 0
#endif // BIMG_CONFIG_USE_WIC && !BX_PLATFORM_WINDOWS
/// Use stb_image for BMP, GIF, HDR, JPEG, PIC, PNM, PSD and TGA. When disabled those formats are
/// not parsed, except for BMP, GIF and JPEG when `BIMG_CONFIG_USE_WIC` decodes them.
///
#ifndef BIMG_CONFIG_USE_STB_IMAGE
# define BIMG_CONFIG_USE_STB_IMAGE 1
#endif // BIMG_CONFIG_USE_STB_IMAGE
/// AVIF (AV1 Image File Format) - image format based on AV1.
///
#ifndef BIMG_CONFIG_PARSE_AVIF
@@ -75,7 +94,7 @@
/// BMP (Windows Bitmap) - uncompressed raster image format.
///
#ifndef BIMG_CONFIG_PARSE_BMP
# define BIMG_CONFIG_PARSE_BMP BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_BMP (BIMG_CONFIG_PARSE_ENABLE && (BIMG_CONFIG_USE_WIC || BIMG_CONFIG_USE_STB_IMAGE) )
#endif // BIMG_CONFIG_PARSE_BMP
/// EXR (OpenEXR) - high dynamic range image format by ILM.
@@ -87,13 +106,13 @@
/// GIF (Graphics Interchange Format) - indexed-color image format with animation support.
///
#ifndef BIMG_CONFIG_PARSE_GIF
# define BIMG_CONFIG_PARSE_GIF BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_GIF (BIMG_CONFIG_PARSE_ENABLE && (BIMG_CONFIG_USE_WIC || BIMG_CONFIG_USE_STB_IMAGE) )
#endif // BIMG_CONFIG_PARSE_GIF
/// HDR (Radiance RGBE) - high dynamic range image format.
///
#ifndef BIMG_CONFIG_PARSE_HDR
# define BIMG_CONFIG_PARSE_HDR BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_HDR (BIMG_CONFIG_PARSE_ENABLE && BIMG_CONFIG_USE_STB_IMAGE)
#endif // BIMG_CONFIG_PARSE_HDR
/// HEIF (High Efficiency Image File Format) - image format based on HEVC.
@@ -105,13 +124,13 @@
/// JPEG (Joint Photographic Experts Group) - lossy compressed image format.
///
#ifndef BIMG_CONFIG_PARSE_JPEG
# define BIMG_CONFIG_PARSE_JPEG BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_JPEG (BIMG_CONFIG_PARSE_ENABLE && (BIMG_CONFIG_USE_WIC || BIMG_CONFIG_USE_STB_IMAGE) )
#endif // BIMG_CONFIG_PARSE_JPEG
/// PIC (Softimage) - image format used by Softimage 3D tools.
///
#ifndef BIMG_CONFIG_PARSE_PIC
# define BIMG_CONFIG_PARSE_PIC BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_PIC (BIMG_CONFIG_PARSE_ENABLE && BIMG_CONFIG_USE_STB_IMAGE)
#endif // BIMG_CONFIG_PARSE_PIC
/// PNG (Portable Network Graphics) - lossless compressed image format.
@@ -123,19 +142,19 @@
/// PNM (Portable Any Map) - family of simple image formats (PBM, PGM, PPM).
///
#ifndef BIMG_CONFIG_PARSE_PNM
# define BIMG_CONFIG_PARSE_PNM BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_PNM (BIMG_CONFIG_PARSE_ENABLE && BIMG_CONFIG_USE_STB_IMAGE)
#endif // BIMG_CONFIG_PARSE_PNM
/// PSD (Adobe Photoshop Document) - layered image format.
///
#ifndef BIMG_CONFIG_PARSE_PSD
# define BIMG_CONFIG_PARSE_PSD BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_PSD (BIMG_CONFIG_PARSE_ENABLE && BIMG_CONFIG_USE_STB_IMAGE)
#endif // BIMG_CONFIG_PARSE_PSD
/// TGA (Truevision TGA) - raster image format with optional RLE compression.
///
#ifndef BIMG_CONFIG_PARSE_TGA
# define BIMG_CONFIG_PARSE_TGA BIMG_CONFIG_PARSE_ENABLE
# define BIMG_CONFIG_PARSE_TGA (BIMG_CONFIG_PARSE_ENABLE && BIMG_CONFIG_USE_STB_IMAGE)
#endif // BIMG_CONFIG_PARSE_TGA
/// WebP - lossy and lossless image format by Google.
@@ -144,15 +163,27 @@
# define BIMG_CONFIG_PARSE_WEBP BIMG_CONFIG_PARSE_ENABLE
#endif // BIMG_CONFIG_PARSE_WEBP
/// WIC (Windows Imaging Component) - Windows-only backup decoder for common raster formats (PNG, JPEG, BMP, GIF).
///
#ifndef BIMG_CONFIG_PARSE_WIC
# define BIMG_CONFIG_PARSE_WIC (BIMG_CONFIG_PARSE_ENABLE && BX_PLATFORM_WINDOWS && (0 \
|| 0 == BIMG_CONFIG_PARSE_PNG \
|| 0 == BIMG_CONFIG_PARSE_JPEG \
|| 0 == BIMG_CONFIG_PARSE_BMP \
|| 0 == BIMG_CONFIG_PARSE_GIF \
) )
#endif // BIMG_CONFIG_PARSE_WIC
static_assert(!BIMG_CONFIG_PARSE_BMP || BIMG_CONFIG_USE_WIC || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_BMP requires BIMG_CONFIG_USE_WIC or BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_GIF || BIMG_CONFIG_USE_WIC || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_GIF requires BIMG_CONFIG_USE_WIC or BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_JPEG || BIMG_CONFIG_USE_WIC || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_JPEG requires BIMG_CONFIG_USE_WIC or BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_HDR || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_HDR requires BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_PIC || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_PIC requires BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_PNM || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_PNM requires BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_PSD || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_PSD requires BIMG_CONFIG_USE_STB_IMAGE.");
static_assert(!BIMG_CONFIG_PARSE_TGA || BIMG_CONFIG_USE_STB_IMAGE, "BIMG_CONFIG_PARSE_TGA requires BIMG_CONFIG_USE_STB_IMAGE.");
#if BIMG_CONFIG_USE_STB_IMAGE && !(0 \
|| (BIMG_CONFIG_PARSE_BMP && !BIMG_CONFIG_USE_WIC) \
|| (BIMG_CONFIG_PARSE_GIF && !BIMG_CONFIG_USE_WIC) \
|| (BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC) \
|| BIMG_CONFIG_PARSE_HDR \
|| BIMG_CONFIG_PARSE_PIC \
|| BIMG_CONFIG_PARSE_PNM \
|| BIMG_CONFIG_PARSE_PSD \
|| BIMG_CONFIG_PARSE_TGA \
)
# undef BIMG_CONFIG_USE_STB_IMAGE
# define BIMG_CONFIG_USE_STB_IMAGE 0
#endif // BIMG_CONFIG_USE_STB_IMAGE && !(...)
#endif // BIMG_CONFIG_H_HEADER_GUARD

View File

@@ -29,7 +29,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4702) // warning C4702: unreachable code
BX_PRAGMA_DIAGNOSTIC_POP()
#endif // BIMG_CONFIG_PARSE_EXR
#if BIMG_CONFIG_PARSE_PNG
#if BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
BX_PRAGMA_DIAGNOSTIC_PUSH();
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4127) // warning C4127: conditional expression is constant
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4267) // warning C4267: '=' : conversion from 'size_t' to 'unsigned short', possible loss of data
@@ -41,6 +41,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4334) // warning C4334: '<<' : result of 32 -
#define LODEPNG_NO_COMPILE_CPP
#include <lodepng/lodepng.cpp>
BX_PRAGMA_DIAGNOSTIC_POP();
#endif // BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
void* lodepng_malloc(size_t _size)
{
@@ -56,7 +57,6 @@ void lodepng_free(void* _ptr)
{
::free(_ptr);
}
#endif // BIMG_CONFIG_PARSE_PNG
#if BIMG_CONFIG_PARSE_HEIF
# include <libheif/heif.h>
@@ -90,22 +90,13 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4701) // warning C4701: potentially uninitiali
BX_PRAGMA_DIAGNOSTIC_POP();
#endif // BIMG_CONFIG_PARSE_WEBP
#define BIMG_USE_STB_IMAGE 0 \
|| BIMG_CONFIG_PARSE_JPEG \
|| BIMG_CONFIG_PARSE_BMP \
|| BIMG_CONFIG_PARSE_PSD \
|| BIMG_CONFIG_PARSE_TGA \
|| BIMG_CONFIG_PARSE_GIF \
|| BIMG_CONFIG_PARSE_HDR \
|| BIMG_CONFIG_PARSE_PIC \
|| 0
#if BIMG_USE_STB_IMAGE
#if BIMG_CONFIG_USE_STB_IMAGE
BX_PRAGMA_DIAGNOSTIC_PUSH();
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wint-to-pointer-cast")
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wmissing-field-initializers");
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wshadow");
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wsign-compare");
BX_PRAGMA_DIAGNOSTIC_IGNORED_CLANG_GCC("-Wunused-parameter");
BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wunused-but-set-variable");
BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Warray-bounds");
BX_PRAGMA_DIAGNOSTIC_IGNORED_GCC("-Wmisleading-indentation");
@@ -119,17 +110,13 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505); // unreferenced function with internal
#define STB_IMAGE_STATIC
#define STBI_NO_PNG // supported via LODEPNG
#if !BIMG_CONFIG_PARSE_JPEG
#if !BIMG_CONFIG_PARSE_JPEG || BIMG_CONFIG_USE_WIC
# define STBI_NO_JPEG
#endif // !BIMG_CONFIG_PARSE_JPEG
#endif // !BIMG_CONFIG_PARSE_JPEG || BIMG_CONFIG_USE_WIC
#if !BIMG_CONFIG_PARSE_BMP
#if !BIMG_CONFIG_PARSE_BMP || BIMG_CONFIG_USE_WIC
# define STBI_NO_BMP
#endif // !BIMG_CONFIG_PARSE_BMP
#if !BIMG_CONFIG_PARSE_PSD
# define STBI_NO_PSD
#endif // !BIMG_CONFIG_PARSE_PSD
#endif // !BIMG_CONFIG_PARSE_BMP || BIMG_CONFIG_USE_WIC
#if !BIMG_CONFIG_PARSE_PSD
# define STBI_NO_PSD
@@ -139,9 +126,9 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505); // unreferenced function with internal
# define STBI_NO_TGA
#endif // !BIMG_CONFIG_PARSE_TGA
#if !BIMG_CONFIG_PARSE_GIF
#if !BIMG_CONFIG_PARSE_GIF || BIMG_CONFIG_USE_WIC
# define STBI_NO_GIF
#endif // !BIMG_CONFIG_PARSE_GIF
#endif // !BIMG_CONFIG_PARSE_GIF || BIMG_CONFIG_USE_WIC
#if !BIMG_CONFIG_PARSE_HDR
# define STBI_NO_HDR
@@ -157,11 +144,11 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505); // unreferenced function with internal
#include <stb/stb_image.h>
BX_PRAGMA_DIAGNOSTIC_POP();
#endif // BIMG_USE_STB_IMAGE
#endif // BIMG_CONFIG_USE_STB_IMAGE
namespace bimg
{
#if BIMG_CONFIG_PARSE_PNG
#if BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
static uint32_t pngReadPackedSample(const uint8_t* _data, uint32_t _index, uint32_t _bitDepth)
{
const uint64_t bitOffset = uint64_t(_index)*_bitDepth;
@@ -173,7 +160,7 @@ namespace bimg
{
return uint8_t(_sample*255 / ( (1u<<_bitDepth)-1) );
}
#endif // BIMG_CONFIG_PARSE_PNG
#endif // BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
static ImageContainer* imageParseLodePng(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
{
@@ -186,7 +173,7 @@ namespace bimg
return NULL;
}
#if BIMG_CONFIG_PARSE_PNG
#if BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
ImageContainer* output = NULL;
bimg::TextureFormat::Enum format = bimg::TextureFormat::RGBA8;
uint32_t width = 0;
@@ -664,7 +651,7 @@ namespace bimg
BX_UNUSED(_allocator, _data, _size);
BX_ERROR_SET(_err, BIMG_ERROR, "PNG parsing is disabled (BIMG_CONFIG_PARSE_PNG).");
return NULL;
#endif // BIMG_CONFIG_PARSE_PNG
#endif // BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
}
#if BIMG_CONFIG_PARSE_EXR
@@ -924,7 +911,7 @@ namespace bimg
#endif // BIMG_CONFIG_PARSE_PNG
}
#if BIMG_USE_STB_IMAGE
#if BIMG_CONFIG_USE_STB_IMAGE
static ImageParser::Enum imageStbImageFormat(const void* _data, uint32_t _size)
{
const uint8_t* data = (const uint8_t*)_data;
@@ -973,13 +960,13 @@ namespace bimg
// TGA has no signature; stb_image probes it last.
return ImageParser::Tga;
}
#endif // BIMG_USE_STB_IMAGE
#endif // BIMG_CONFIG_USE_STB_IMAGE
static ImageContainer* imageParseStbImage(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
#if BIMG_USE_STB_IMAGE
#if BIMG_CONFIG_USE_STB_IMAGE
const int isHdr = stbi_is_hdr_from_memory( (const uint8_t*)_data, (int)_size);
void* data;
@@ -1067,7 +1054,7 @@ namespace bimg
return NULL;
}
#if BIMG_CONFIG_PARSE_JPEG
#if BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC
Orientation::Enum orientation = Orientation::R0;
bx::Error exifErr;
@@ -1193,7 +1180,7 @@ namespace bimg
BX_UNUSED(_allocator, _data, _size);
BX_ERROR_SET(_err, BIMG_ERROR, "JPEG parsing is disabled (BIMG_CONFIG_PARSE_JPEG).");
return NULL;
#endif // BIMG_CONFIG_PARSE_JPEG
#endif // BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC
}
static bool imageIsAvifBrand(const void* _data, uint32_t _size)
@@ -1510,7 +1497,7 @@ namespace bimg
#endif // BIMG_CONFIG_PARSE_WEBP
}
static bool imageInfoFinalize(ImageContainer& _imageContainer, ImageParser::Enum _parser, TextureFormat::Enum _format, uint32_t _width, uint32_t _height, bx::Error* _err)
bool imageInfoFinalize(ImageContainer& _imageContainer, ImageParser::Enum _parser, TextureFormat::Enum _format, uint32_t _width, uint32_t _height, bx::Error* _err)
{
if (0 == _width
|| 0 == _height
@@ -1562,7 +1549,7 @@ namespace bimg
return false;
}
#if BIMG_CONFIG_PARSE_PNG
#if BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
LodePNGState state;
lodepng_state_init(&state);
@@ -1650,7 +1637,7 @@ namespace bimg
BX_UNUSED(_data, _size);
BX_ERROR_SET(_err, BIMG_ERROR, "PNG parsing is disabled (BIMG_CONFIG_PARSE_PNG).");
return false;
#endif // BIMG_CONFIG_PARSE_PNG
#endif // BIMG_CONFIG_PARSE_PNG && !BIMG_CONFIG_USE_WIC
}
static bool imageParseInfoTinyExr(bx::AllocatorI* _allocator, ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err)
@@ -1739,7 +1726,7 @@ namespace bimg
#endif // BIMG_CONFIG_PARSE_EXR
}
#if BIMG_CONFIG_PARSE_JPEG
#if BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC
static Orientation::Enum imageParseJpegOrientation(const void* _data, uint32_t _size)
{
Orientation::Enum orientation = Orientation::R0;
@@ -1860,13 +1847,13 @@ namespace bimg
return orientation;
}
#endif // BIMG_CONFIG_PARSE_JPEG
#endif // BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC
static bool imageParseInfoStbImage(bx::AllocatorI* _allocator, ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err)
{
BX_UNUSED(_allocator);
#if BIMG_USE_STB_IMAGE
#if BIMG_CONFIG_USE_STB_IMAGE
int width = 0;
int height = 0;
int comp = 0;
@@ -1895,7 +1882,7 @@ namespace bimg
#else
BX_UNUSED(_imageContainer, _data, _size, _err);
return false;
#endif // BIMG_USE_STB_IMAGE
#endif // BIMG_CONFIG_USE_STB_IMAGE
}
static bool imageParseInfoJpeg(bx::AllocatorI* _allocator, ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err)
@@ -1909,7 +1896,7 @@ namespace bimg
return false;
}
#if BIMG_CONFIG_PARSE_JPEG && BIMG_USE_STB_IMAGE
#if BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC && BIMG_CONFIG_USE_STB_IMAGE
const Orientation::Enum orientation = imageParseJpegOrientation(_data, _size);
int width = 0;
@@ -1938,10 +1925,10 @@ namespace bimg
_imageContainer.m_orientation = orientation;
return true;
#else
BX_UNUSED(_data, _size);
BX_UNUSED(_imageContainer, _data, _size);
BX_ERROR_SET(_err, BIMG_ERROR, "JPEG parsing is disabled (BIMG_CONFIG_PARSE_JPEG).");
return false;
#endif // BIMG_CONFIG_PARSE_JPEG && BIMG_USE_STB_IMAGE
#endif // BIMG_CONFIG_PARSE_JPEG && !BIMG_CONFIG_USE_WIC && BIMG_CONFIG_USE_STB_IMAGE
}
static bool imageParseInfoSimpleWebp(bx::AllocatorI* _allocator, ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err)
@@ -2136,6 +2123,7 @@ namespace bimg
typedef bool (*ImageParseInfoFn)(bx::AllocatorI*, ImageContainer&, const void*, uint32_t, bx::Error*);
static const ImageParseInfoFn parsers[] =
{
imageParseInfoWic,
imageParseInfoLodePng,
imageParseInfoTinyExr,
imageParseInfoJpeg,

View File

@@ -5,7 +5,12 @@
#include "bimg_p.h"
#if BIMG_CONFIG_PARSE_WIC && BX_PLATFORM_WINDOWS
#if BIMG_CONFIG_USE_WIC && (0 \
|| BIMG_CONFIG_PARSE_PNG \
|| BIMG_CONFIG_PARSE_JPEG \
|| BIMG_CONFIG_PARSE_BMP \
|| BIMG_CONFIG_PARSE_GIF \
)
#include <bx/os.h>
@@ -24,6 +29,7 @@
if (NULL != (_ptr) ) \
{ \
(_ptr)->Release(); \
(_ptr) = NULL; \
} \
BX_MACRO_BLOCK_END
@@ -61,139 +67,225 @@ namespace bimg
return ImageParser::Count;
}
ImageContainer* imageParseWic(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
static bool wicIsEnabled(ImageParser::Enum _format)
{
BX_UNUSED(_err);
const ImageParser::Enum format = wicDetectFormat( (const uint8_t*)_data, _size);
if (false
|| (ImageParser::Png == format && BIMG_CONFIG_PARSE_PNG )
|| (ImageParser::Jpeg == format && BIMG_CONFIG_PARSE_JPEG)
|| (ImageParser::Bmp == format && BIMG_CONFIG_PARSE_BMP )
|| (ImageParser::Gif == format && BIMG_CONFIG_PARSE_GIF )
)
switch (_format)
{
case ImageParser::Png: return 0 != BIMG_CONFIG_PARSE_PNG;
case ImageParser::Jpeg: return 0 != BIMG_CONFIG_PARSE_JPEG;
case ImageParser::Bmp: return 0 != BIMG_CONFIG_PARSE_BMP;
case ImageParser::Gif: return 0 != BIMG_CONFIG_PARSE_GIF;
default: return false;
}
}
struct WicFrame
{
WicFrame()
: m_wicDll(NULL)
, m_ole32Dll(NULL)
, m_coUninitialize(NULL)
, m_factory(NULL)
, m_stream(NULL)
, m_decoder(NULL)
, m_frame(NULL)
, m_width(0)
, m_height(0)
{
return NULL;
}
void* wicDll = bx::dlopen("windowscodecs.dll");
if (NULL == wicDll)
~WicFrame()
{
return NULL;
}
WIC_RELEASE(m_frame);
WIC_RELEASE(m_decoder);
WIC_RELEASE(m_stream);
WIC_RELEASE(m_factory);
typedef HRESULT (WINAPI* PFN_DllGetClassObject)(REFCLSID, REFIID, LPVOID*);
PFN_DllGetClassObject dllGetClassObject = bx::dlsym<PFN_DllGetClassObject>(wicDll, "DllGetClassObject");
if (NULL == dllGetClassObject)
{
bx::dlclose(wicDll);
return NULL;
}
void* ole32Dll = bx::dlopen("ole32.dll");
typedef HRESULT (WINAPI* PFN_CoInitializeEx)(LPVOID, DWORD);
typedef void (WINAPI* PFN_CoUninitialize)(void);
PFN_CoUninitialize coUninitialize = NULL;
bool comNeedsUninit = false;
if (NULL != ole32Dll)
{
PFN_CoInitializeEx coInitializeEx = bx::dlsym<PFN_CoInitializeEx>(ole32Dll, "CoInitializeEx");
coUninitialize = bx::dlsym<PFN_CoUninitialize>(ole32Dll, "CoUninitialize");
if (NULL != coInitializeEx)
if (NULL != m_coUninitialize)
{
const HRESULT hr = coInitializeEx(NULL, COINIT_MULTITHREADED);
comNeedsUninit = (S_OK == hr || S_FALSE == hr) && NULL != coUninitialize;
m_coUninitialize();
}
if (NULL != m_ole32Dll)
{
bx::dlclose(m_ole32Dll);
}
if (NULL != m_wicDll)
{
bx::dlclose(m_wicDll);
}
}
IClassFactory* classFactory = NULL;
IWICImagingFactory* factory = NULL;
HRESULT hr = dllGetClassObject(kCLSID_WICImagingFactory, __uuidof(IClassFactory), (void**)&classFactory);
if (SUCCEEDED(hr) && NULL != classFactory)
bool open(const void* _data, uint32_t _size, bx::Error* _err)
{
classFactory->CreateInstance(NULL, __uuidof(IWICImagingFactory), (void**)&factory);
classFactory->Release();
}
ImageContainer* image = NULL;
if (NULL != factory)
{
IWICStream* stream = NULL;
IWICBitmapDecoder* decoder = NULL;
IWICBitmapFrameDecode* frame = NULL;
IWICFormatConverter* converter = NULL;
if (true
&& SUCCEEDED(factory->CreateStream(&stream) )
&& SUCCEEDED(stream->InitializeFromMemory( (WICInProcPointer)const_cast<void*>(_data), _size) )
&& SUCCEEDED(factory->CreateDecoderFromStream(stream, NULL, WICDecodeMetadataCacheOnDemand, &decoder) )
&& SUCCEEDED(decoder->GetFrame(0, &frame) )
&& SUCCEEDED(factory->CreateFormatConverter(&converter) )
&& SUCCEEDED(converter->Initialize(frame, kGUID_WICPixelFormat32bppRGBA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom) )
)
m_wicDll = bx::dlopen("windowscodecs.dll");
if (NULL == m_wicDll)
{
UINT width = 0;
UINT height = 0;
frame->GetSize(&width, &height);
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: windowscodecs.dll is not available.");
return false;
}
if (0 < width
&& 0 < height)
typedef HRESULT (WINAPI* PFN_DllGetClassObject)(REFCLSID, REFIID, LPVOID*);
PFN_DllGetClassObject dllGetClassObject = bx::dlsym<PFN_DllGetClassObject>(m_wicDll, "DllGetClassObject");
if (NULL == dllGetClassObject)
{
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: DllGetClassObject is not available.");
return false;
}
m_ole32Dll = bx::dlopen("ole32.dll");
if (NULL != m_ole32Dll)
{
typedef HRESULT (WINAPI* PFN_CoInitializeEx)(LPVOID, DWORD);
typedef void (WINAPI* PFN_CoUninitialize)(void);
PFN_CoInitializeEx coInitializeEx = bx::dlsym<PFN_CoInitializeEx>(m_ole32Dll, "CoInitializeEx");
PFN_CoUninitialize coUninitialize = bx::dlsym<PFN_CoUninitialize>(m_ole32Dll, "CoUninitialize");
if (NULL != coInitializeEx)
{
image = imageAlloc(_allocator, TextureFormat::RGBA8, width, height, 0, 1, false, false);
if (NULL != image)
const HRESULT hr = coInitializeEx(NULL, COINIT_MULTITHREADED);
if (S_OK == hr
|| S_FALSE == hr)
{
hr = converter->CopyPixels(NULL, width * 4, image->m_size, (BYTE*)image->m_data);
if (FAILED(hr) )
{
imageFree(image);
image = NULL;
}
else
{
image->m_parser = format;
bool hasAlpha = false;
const uint8_t* rgba = (const uint8_t*)image->m_data;
for (uint32_t ii = 3; ii < image->m_size; ii += 4)
{
if (0xff != rgba[ii])
{
hasAlpha = true;
break;
}
}
image->m_hasAlpha = hasAlpha;
}
m_coUninitialize = coUninitialize;
}
}
}
IClassFactory* classFactory = NULL;
if (SUCCEEDED(dllGetClassObject(kCLSID_WICImagingFactory, __uuidof(IClassFactory), (void**)&classFactory) )
&& NULL != classFactory)
{
classFactory->CreateInstance(NULL, __uuidof(IWICImagingFactory), (void**)&m_factory);
classFactory->Release();
}
if (NULL == m_factory)
{
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: Failed to create imaging factory.");
return false;
}
if (FAILED(m_factory->CreateStream(&m_stream) )
|| FAILED(m_stream->InitializeFromMemory( (BYTE*)const_cast<void*>(_data), _size) )
|| FAILED(m_factory->CreateDecoderFromStream(m_stream, NULL, WICDecodeMetadataCacheOnDemand, &m_decoder) )
|| FAILED(m_decoder->GetFrame(0, &m_frame) ) )
{
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: Failed to decode image.");
return false;
}
UINT width = 0;
UINT height = 0;
if (FAILED(m_frame->GetSize(&width, &height) )
|| 0 == width
|| 0 == height)
{
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: Invalid image size.");
return false;
}
m_width = width;
m_height = height;
return true;
}
void* m_wicDll;
void* m_ole32Dll;
void (WINAPI* m_coUninitialize)(void);
IWICImagingFactory* m_factory;
IWICStream* m_stream;
IWICBitmapDecoder* m_decoder;
IWICBitmapFrameDecode* m_frame;
uint32_t m_width;
uint32_t m_height;
};
ImageContainer* imageParseWic(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err)
{
BX_ERROR_SCOPE(_err);
const ImageParser::Enum format = wicDetectFormat( (const uint8_t*)_data, _size);
if (!wicIsEnabled(format) )
{
return NULL;
}
WicFrame wic;
if (!wic.open(_data, _size, _err) )
{
return NULL;
}
IWICFormatConverter* converter = NULL;
if (FAILED(wic.m_factory->CreateFormatConverter(&converter) )
|| FAILED(converter->Initialize(wic.m_frame, kGUID_WICPixelFormat32bppRGBA, WICBitmapDitherTypeNone, NULL, 0.0, WICBitmapPaletteTypeCustom) ) )
{
WIC_RELEASE(converter);
WIC_RELEASE(frame);
WIC_RELEASE(decoder);
WIC_RELEASE(stream);
WIC_RELEASE(factory);
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: Failed to convert image to RGBA8.");
return NULL;
}
if (comNeedsUninit)
ImageContainer* image = imageAlloc(_allocator, TextureFormat::RGBA8, wic.m_width, wic.m_height, 0, 1, false, false);
if (NULL == image)
{
coUninitialize();
WIC_RELEASE(converter);
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: Unsupported dimensions.");
return NULL;
}
if (NULL != ole32Dll)
const HRESULT hr = converter->CopyPixels(NULL, wic.m_width*4, image->m_size, (BYTE*)image->m_data);
WIC_RELEASE(converter);
if (FAILED(hr) )
{
bx::dlclose(ole32Dll);
imageFree(image);
BX_ERROR_SET(_err, BIMG_ERROR, "WIC: Failed to copy pixels.");
return NULL;
}
bx::dlclose(wicDll);
image->m_parser = format;
bool hasAlpha = false;
const uint8_t* rgba = (const uint8_t*)image->m_data;
for (uint32_t ii = 3; ii < image->m_size; ii += 4)
{
if (0xff != rgba[ii])
{
hasAlpha = true;
break;
}
}
image->m_hasAlpha = hasAlpha;
return image;
}
bool imageParseInfoWic(bx::AllocatorI* _allocator, ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err)
{
BX_UNUSED(_allocator);
BX_ERROR_SCOPE(_err);
const ImageParser::Enum format = wicDetectFormat( (const uint8_t*)_data, _size);
if (!wicIsEnabled(format) )
{
return false;
}
WicFrame wic;
if (!wic.open(_data, _size, _err) )
{
return false;
}
return imageInfoFinalize(_imageContainer, format, TextureFormat::RGBA8, wic.m_width, wic.m_height, _err);
}
} // namespace bimg
#else
@@ -205,6 +297,11 @@ namespace bimg
return NULL;
}
bool imageParseInfoWic(bx::AllocatorI* /*_allocator*/, ImageContainer& /*_imageContainer*/, const void* /*_data*/, uint32_t /*_size*/, bx::Error* /*_err*/)
{
return false;
}
} // namespace bimg
#endif // BIMG_CONFIG_PARSE_WIC && BX_PLATFORM_WINDOWS
#endif // BIMG_CONFIG_USE_WIC && (BIMG_CONFIG_PARSE_PNG || BIMG_CONFIG_PARSE_JPEG || BIMG_CONFIG_PARSE_BMP || BIMG_CONFIG_PARSE_GIF)