Kaynağa Gözat

Fixed mipmap calculation. Added more error handling.

Branimir Karadžić 8 yıl önce
ebeveyn
işleme
279ec6a2f3
5 değiştirilmiş dosya ile 88 ekleme ve 44 silme
  1. 6 1
      include/bimg/bimg.h
  2. 1 0
      include/bimg/decode.h
  3. 56 31
      src/image.cpp
  4. 18 10
      src/image_decode.cpp
  5. 7 2
      tools/texturec/texturec.cpp

+ 6 - 1
include/bimg/bimg.h

@@ -9,7 +9,7 @@
 #include <stdint.h> // uint32_t
 #include <stdlib.h> // 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
 		);
 
 	///

+ 1 - 0
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

+ 56 - 31
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<uint32_t magicT, ParseFn parseFnT>
-	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,9 +2010,14 @@ 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;
 		}
 
@@ -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<DDS_MAGIC, imageParseDds>(_allocator, _src, _size);
+		return imageParseT<DDS_MAGIC, imageParseDds>(_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<KTX_MAGIC, imageParseKtx>(_allocator, _src, _size);
+		return imageParseT<KTX_MAGIC, imageParseKtx>(_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<PVR3_MAGIC, imageParsePvr3>(_allocator, _src, _size);
+		return imageParseT<PVR3_MAGIC, imageParsePvr3>(_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)

+ 18 - 10
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)
 		{

+ 7 - 2
tools/texturec/texturec.cpp

@@ -25,7 +25,7 @@
 #include <string>
 
 #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)
 	{