diff --git a/3rdparty/stb/stb_image.h b/3rdparty/stb/stb_image.h index 11faed7..c1a396d 100644 --- a/3rdparty/stb/stb_image.h +++ b/3rdparty/stb/stb_image.h @@ -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) diff --git a/src/bimg_p.h b/src/bimg_p.h index 0fdee3b..004ab5b 100644 --- a/src/bimg_p.h +++ b/src/bimg_p.h @@ -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 diff --git a/src/config.h b/src/config.h index 0540af9..c60e2f0 100644 --- a/src/config.h +++ b/src/config.h @@ -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 diff --git a/src/image_decode.cpp b/src/image_decode.cpp index e8592b2..d3e2be1 100644 --- a/src/image_decode.cpp +++ b/src/image_decode.cpp @@ -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 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 @@ -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 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, diff --git a/src/image_decode_wic.cpp b/src/image_decode_wic.cpp index 4461ae6..adb62f7 100644 --- a/src/image_decode_wic.cpp +++ b/src/image_decode_wic.cpp @@ -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 @@ -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(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(ole32Dll, "CoInitializeEx"); - coUninitialize = bx::dlsym(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(_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(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(m_ole32Dll, "CoInitializeEx"); + PFN_CoUninitialize coUninitialize = bx::dlsym(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(_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)