diff --git a/include/bimg/bimg.h b/include/bimg/bimg.h index 134935d..b1f4f56 100644 --- a/include/bimg/bimg.h +++ b/include/bimg/bimg.h @@ -9,7 +9,7 @@ #include // uint32_t #include // NULL -#define BIMG_API_VERSION UINT32_C(4) +#define BIMG_API_VERSION UINT32_C(5) namespace bx { @@ -460,6 +460,7 @@ namespace bimg bool imageParse( ImageContainer& _imageContainer , bx::ReaderSeekerI* _reader + , bx::Error* _err ); /// @@ -467,6 +468,7 @@ namespace bimg ImageContainer& _imageContainer , const void* _data , uint32_t _size + , bx::Error* _err = NULL ); /// @@ -474,6 +476,7 @@ namespace bimg bx::AllocatorI* _allocator , const void* _src , uint32_t _size + , bx::Error* _err ); /// @@ -481,6 +484,7 @@ namespace bimg bx::AllocatorI* _allocator , const void* _src , uint32_t _size + , bx::Error* _err ); /// @@ -488,6 +492,7 @@ namespace bimg bx::AllocatorI* _allocator , const void* _src , uint32_t _size + , bx::Error* _err ); /// diff --git a/include/bimg/decode.h b/include/bimg/decode.h index 3b9e53b..a575880 100644 --- a/include/bimg/decode.h +++ b/include/bimg/decode.h @@ -16,6 +16,7 @@ namespace bimg , const void* _data , uint32_t _size , TextureFormat::Enum _dstFormat = TextureFormat::Count + , bx::Error* _err = NULL ); } // namespace bimg diff --git a/src/image.cpp b/src/image.cpp index 06709fa..e16dea9 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -252,14 +252,13 @@ namespace bimg const uint16_t minBlockX = blockInfo.minBlockX; const uint16_t minBlockY = blockInfo.minBlockY; - _width = bx::uint16_max(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth); + _width = bx::uint16_max(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth )*blockWidth); _height = bx::uint16_max(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight); _depth = bx::uint16_max(1, _depth); - uint32_t max = bx::uint32_max(_width, bx::uint32_max(_height, _depth) ); - uint32_t numMips = bx::uint32_max(1, uint8_t(bx::flog2(float(max) ) ) ); + uint8_t numMips = calcNumMips(true, _width, _height, _depth); - return uint8_t(numMips); + return numMips; } uint32_t imageGetSize(TextureInfo* _info, uint16_t _width, uint16_t _height, uint16_t _depth, bool _cubeMap, bool _hasMips, uint16_t _numLayers, TextureFormat::Enum _format) @@ -904,10 +903,10 @@ namespace bimg return output; } - typedef bool (*ParseFn)(ImageContainer&, bx::ReaderSeekerI*); + typedef bool (*ParseFn)(ImageContainer&, bx::ReaderSeekerI*, bx::Error*); template - ImageContainer* imageParseT(bx::AllocatorI* _allocator, const void* _src, uint32_t _size) + ImageContainer* imageParseT(bx::AllocatorI* _allocator, const void* _src, uint32_t _size, bx::Error* _err) { bx::MemoryReader reader(_src, _size); @@ -916,7 +915,7 @@ namespace bimg ImageContainer imageContainer; if (magicT != magic - || !parseFnT(imageContainer, &reader) ) + || !parseFnT(imageContainer, &reader, _err) ) { return NULL; } @@ -1747,7 +1746,7 @@ namespace bimg _depth = bx::uint16_max(1, _depth); _numLayers = bx::uint16_max(1, _numLayers); - const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height) : 1; + const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height, _depth) : 1; uint32_t size = imageGetSize(NULL, _width, _height, _depth, _cubeMap, _hasMips, _numLayers, _format); ImageContainer* imageContainer = (ImageContainer*)BX_ALLOC(_allocator, size + sizeof(ImageContainer) ); @@ -1994,9 +1993,8 @@ namespace bimg { 32, { 0xffffffff, 0x00000000, 0x00000000, 0x00000000 }, TextureFormat::R32U }, }; - bool imageParseDds(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader) + bool imageParseDds(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader, bx::Error* _err) { - bx::Error* _err = NULL; BX_ERROR_SCOPE(_err); int32_t total = 0; @@ -2012,12 +2010,17 @@ namespace bimg uint32_t flags; total += bx::read(_reader, flags, _err); - if (!_err->isOk() - || (flags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) != (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) + if (!_err->isOk() ) { return false; } + if ( (flags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) != (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT) ) + { + BX_ERROR_SET(_err, BIMG_ERROR, "DDS: Invalid flags."); + return false; + } + uint32_t height; total += bx::read(_reader, height, _err); @@ -2081,18 +2084,24 @@ namespace bimg total += bx::read(_reader, miscFlags2, _err); } - if (!_err->isOk() - || (caps[0] & DDSCAPS_TEXTURE) == 0) + if (!_err->isOk() ) { return false; } + if ( (caps[0] & DDSCAPS_TEXTURE) == 0) + { + BX_ERROR_SET(_err, BIMG_ERROR, "DDS: Unsupported caps."); + return false; + } + bool cubeMap = 0 != (caps[1] & DDSCAPS2_CUBEMAP); if (cubeMap) { if ( (caps[1] & DSCAPS2_CUBEMAP_ALLSIDES) != DSCAPS2_CUBEMAP_ALLSIDES) { // partial cube map is not supported. + BX_ERROR_SET(_err, BIMG_ERROR, "DDS: Incomplete cubemap."); return false; } } @@ -2144,6 +2153,12 @@ namespace bimg } } + if (TextureFormat::Unknown == format) + { + BX_ERROR_SET(_err, BIMG_ERROR, "DDS: Unknown texture format."); + return false; + } + _imageContainer.m_allocator = NULL; _imageContainer.m_data = NULL; _imageContainer.m_size = 0; @@ -2160,12 +2175,12 @@ namespace bimg _imageContainer.m_ktxLE = false; _imageContainer.m_srgb = srgb; - return TextureFormat::Unknown != format; + return true; } - ImageContainer* imageParseDds(bx::AllocatorI* _allocator, const void* _src, uint32_t _size) + ImageContainer* imageParseDds(bx::AllocatorI* _allocator, const void* _src, uint32_t _size, bx::Error* _err) { - return imageParseT(_allocator, _src, _size); + return imageParseT(_allocator, _src, _size, _err); } // KTX @@ -2380,8 +2395,10 @@ namespace bimg { KTX_RGB, TextureFormat::RGB8 }, }; - bool imageParseKtx(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader) + bool imageParseKtx(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + uint8_t identifier[8]; bx::read(_reader, identifier); @@ -2478,9 +2495,9 @@ namespace bimg return TextureFormat::Unknown != format; } - ImageContainer* imageParseKtx(bx::AllocatorI* _allocator, const void* _src, uint32_t _size) + ImageContainer* imageParseKtx(bx::AllocatorI* _allocator, const void* _src, uint32_t _size, bx::Error* _err) { - return imageParseT(_allocator, _src, _size); + return imageParseT(_allocator, _src, _size, _err); } // PVR3 @@ -2564,8 +2581,10 @@ namespace bimg { PVR3_RGB10A2, PVR3_CHANNEL_TYPE_ANY, TextureFormat::RGB10A2 }, }; - bool imageParsePvr3(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader) + bool imageParsePvr3(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + uint32_t flags; bx::read(_reader, flags); @@ -2634,27 +2653,29 @@ namespace bimg return TextureFormat::Unknown != format; } - ImageContainer* imageParsePvr3(bx::AllocatorI* _allocator, const void* _src, uint32_t _size) + ImageContainer* imageParsePvr3(bx::AllocatorI* _allocator, const void* _src, uint32_t _size, bx::Error* _err) { - return imageParseT(_allocator, _src, _size); + return imageParseT(_allocator, _src, _size, _err); } - bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader) + bool imageParse(ImageContainer& _imageContainer, bx::ReaderSeekerI* _reader, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + uint32_t magic; - bx::read(_reader, magic); + bx::read(_reader, magic, _err); if (DDS_MAGIC == magic) { - return imageParseDds(_imageContainer, _reader); + return imageParseDds(_imageContainer, _reader, _err); } else if (KTX_MAGIC == magic) { - return imageParseKtx(_imageContainer, _reader); + return imageParseKtx(_imageContainer, _reader, _err); } else if (PVR3_MAGIC == magic) { - return imageParsePvr3(_imageContainer, _reader); + return imageParsePvr3(_imageContainer, _reader, _err); } else if (BIMG_CHUNK_MAGIC_TEX == magic) { @@ -2685,17 +2706,21 @@ namespace bimg _imageContainer.m_ktxLE = false; _imageContainer.m_srgb = false; - return true; + return _err->isOk(); } BX_TRACE("Unrecognized image format (magic: 0x%08x)!", magic); + BX_ERROR_SET(_err, BIMG_ERROR, "Unrecognized image format."); + return false; } - bool imageParse(ImageContainer& _imageContainer, const void* _data, uint32_t _size) + bool imageParse(ImageContainer& _imageContainer, const void* _data, uint32_t _size, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + bx::MemoryReader reader(_data, _size); - return imageParse(_imageContainer, &reader); + return imageParse(_imageContainer, &reader, _err); } void imageDecodeToBgra8(void* _dst, const void* _src, uint32_t _width, uint32_t _height, uint32_t _dstPitch, TextureFormat::Enum _srcFormat) diff --git a/src/image_decode.cpp b/src/image_decode.cpp index 3067d74..006e689 100644 --- a/src/image_decode.cpp +++ b/src/image_decode.cpp @@ -67,8 +67,10 @@ BX_PRAGMA_DIAGNOSTIC_POP(); namespace bimg { - static ImageContainer* imageParseLodePng(bx::AllocatorI* _allocator, const void* _data, uint32_t _size) + static ImageContainer* imageParseLodePng(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + static uint8_t pngMagic[] = { 0x89, 0x50, 0x4E, 0x47, 0x0d, 0x0a }; if (0 != bx::memCmp(_data, pngMagic, sizeof(pngMagic) ) ) @@ -225,8 +227,10 @@ namespace bimg return output; } - static ImageContainer* imageParseTinyExr(bx::AllocatorI* _allocator, const void* _data, uint32_t _size) + static ImageContainer* imageParseTinyExr(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + EXRVersion exrVersion; int result = ParseEXRVersionFromMemory(&exrVersion, (uint8_t*)_data, _size); if (TINYEXR_SUCCESS != result) @@ -362,8 +366,10 @@ namespace bimg return output; } - static ImageContainer* imageParseStbImage(bx::AllocatorI* _allocator, const void* _data, uint32_t _size) + static ImageContainer* imageParseStbImage(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, bx::Error* _err) { + BX_ERROR_SCOPE(_err); + const int isHdr = stbi_is_hdr_from_memory((const uint8_t*)_data, (int)_size); void* data; @@ -406,14 +412,16 @@ namespace bimg return output; } - ImageContainer* imageParse(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, TextureFormat::Enum _dstFormat) + ImageContainer* imageParse(bx::AllocatorI* _allocator, const void* _data, uint32_t _size, TextureFormat::Enum _dstFormat, bx::Error* _err) { - ImageContainer* input = imageParseDds (_allocator, _data, _size) ; - input = NULL == input ? imageParseKtx (_allocator, _data, _size) : input; - input = NULL == input ? imageParsePvr3 (_allocator, _data, _size) : input; - input = NULL == input ? imageParseLodePng (_allocator, _data, _size) : input; - input = NULL == input ? imageParseTinyExr (_allocator, _data, _size) : input; - input = NULL == input ? imageParseStbImage(_allocator, _data, _size) : input; + BX_ERROR_SCOPE(_err); + + ImageContainer* input = imageParseDds (_allocator, _data, _size, _err) ; + input = NULL == input ? imageParseKtx (_allocator, _data, _size, _err) : input; + input = NULL == input ? imageParsePvr3 (_allocator, _data, _size, _err) : input; + input = NULL == input ? imageParseLodePng (_allocator, _data, _size, _err) : input; + input = NULL == input ? imageParseTinyExr (_allocator, _data, _size, _err) : input; + input = NULL == input ? imageParseStbImage(_allocator, _data, _size, _err) : input; if (NULL == input) { diff --git a/tools/texturec/texturec.cpp b/tools/texturec/texturec.cpp index 97df238..6e6a56f 100644 --- a/tools/texturec/texturec.cpp +++ b/tools/texturec/texturec.cpp @@ -25,7 +25,7 @@ #include #define BIMG_TEXTUREC_VERSION_MAJOR 1 -#define BIMG_TEXTUREC_VERSION_MINOR 3 +#define BIMG_TEXTUREC_VERSION_MINOR 4 struct Options { @@ -80,7 +80,12 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData const uint8_t* inputData = (uint8_t*)_inputData; bimg::ImageContainer* output = NULL; - bimg::ImageContainer* input = bimg::imageParse(_allocator, inputData, _inputSize); + bimg::ImageContainer* input = bimg::imageParse(_allocator, inputData, _inputSize, bimg::TextureFormat::Count, _err); + + if (!_err->isOk() ) + { + return NULL; + } if (NULL != input) {