Widen image size APIs to 32/64-bit to fix dimension truncation. (#131)

This commit is contained in:
Branimir Karadžić
2026-06-03 12:03:46 -07:00
committed by GitHub
parent a30057e440
commit 31fdd17215
7 changed files with 208 additions and 96 deletions

View File

@@ -274,17 +274,17 @@ namespace bimg
/// Returns number of mip-maps required for complete mip-map chain. /// Returns number of mip-maps required for complete mip-map chain.
uint8_t imageGetNumMips( uint8_t imageGetNumMips(
TextureFormat::Enum _format TextureFormat::Enum _format
, uint16_t _width , uint32_t _width
, uint16_t _height , uint32_t _height
, uint16_t _depth = 0 , uint32_t _depth = 0
); );
/// Returns image size. /// Returns image size.
uint32_t imageGetSize( uint64_t imageGetSize(
TextureInfo* _info TextureInfo* _info
, uint16_t _width , uint32_t _width
, uint16_t _height , uint32_t _height
, uint16_t _depth , uint32_t _depth
, bool _cubeMap , bool _cubeMap
, bool _hasMips , bool _hasMips
, uint16_t _numLayers , uint16_t _numLayers
@@ -476,10 +476,10 @@ namespace bimg
ImageContainer* imageAlloc( ImageContainer* imageAlloc(
bx::AllocatorI* _allocator bx::AllocatorI* _allocator
, TextureFormat::Enum _format , TextureFormat::Enum _format
, uint16_t _width , uint32_t _width
, uint16_t _height , uint32_t _height
, uint16_t _depth , uint32_t _depth
, uint16_t _numLayers , uint32_t _numLayers
, bool _cubeMap , bool _cubeMap
, bool _hasMips , bool _hasMips
, const void* _data = NULL , const void* _data = NULL

View File

@@ -80,7 +80,7 @@ namespace bimg
const Memory* m_mem; const Memory* m_mem;
}; };
inline uint8_t calcNumMips(bool _hasMips, uint16_t _width, uint16_t _height, uint16_t _depth = 1) inline uint8_t calcNumMips(bool _hasMips, uint32_t _width, uint32_t _height, uint32_t _depth = 1)
{ {
if (_hasMips) if (_hasMips)
{ {

View File

@@ -309,24 +309,24 @@ namespace bimg
return TextureFormat::Unknown; return TextureFormat::Unknown;
} }
uint8_t imageGetNumMips(TextureFormat::Enum _format, uint16_t _width, uint16_t _height, uint16_t _depth) uint8_t imageGetNumMips(TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _depth)
{ {
const ImageBlockInfo& blockInfo = getBlockInfo(_format); const ImageBlockInfo& blockInfo = getBlockInfo(_format);
const uint16_t blockWidth = blockInfo.blockWidth; const uint32_t blockWidth = blockInfo.blockWidth;
const uint16_t blockHeight = blockInfo.blockHeight; const uint32_t blockHeight = blockInfo.blockHeight;
const uint16_t minBlockX = blockInfo.minBlockX; const uint32_t minBlockX = blockInfo.minBlockX;
const uint16_t minBlockY = blockInfo.minBlockY; const uint32_t minBlockY = blockInfo.minBlockY;
_width = bx::max<uint16_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth )*blockWidth); _width = bx::max<uint32_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth )*blockWidth);
_height = bx::max<uint16_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight); _height = bx::max<uint32_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::max<uint16_t>(1, _depth); _depth = bx::max<uint32_t>(1, _depth);
uint8_t numMips = calcNumMips(true, _width, _height, _depth); uint8_t numMips = calcNumMips(true, _width, _height, _depth);
return 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) uint64_t imageGetSize(TextureInfo* _info, uint32_t _width, uint32_t _height, uint32_t _depth, bool _cubeMap, bool _hasMips, uint16_t _numLayers, TextureFormat::Enum _format)
{ {
const ImageBlockInfo& blockInfo = getBlockInfo(_format); const ImageBlockInfo& blockInfo = getBlockInfo(_format);
const uint8_t bpp = blockInfo.bitsPerPixel; const uint8_t bpp = blockInfo.bitsPerPixel;
@@ -336,16 +336,16 @@ namespace bimg
const uint16_t minBlockY = blockInfo.minBlockY; const uint16_t minBlockY = blockInfo.minBlockY;
const uint8_t blockSize = blockInfo.blockSize; const uint8_t blockSize = blockInfo.blockSize;
_width = bx::max<uint16_t>(1, _width); _width = bx::max<uint32_t>(1, _width);
_height = bx::max<uint16_t>(1, _height); _height = bx::max<uint32_t>(1, _height);
_depth = bx::max<uint16_t>(1, _depth); _depth = bx::max<uint32_t>(1, _depth);
const uint8_t numMips = calcNumMips(_hasMips, _width, _height, _depth); const uint8_t numMips = calcNumMips(_hasMips, _width, _height, _depth);
const uint32_t sides = _cubeMap ? 6 : 1; const uint32_t sides = _cubeMap ? 6 : 1;
uint32_t width = _width; uint32_t width = _width;
uint32_t height = _height; uint32_t height = _height;
uint32_t depth = _depth; uint32_t depth = _depth;
uint32_t size = 0; uint64_t size = 0;
for (uint32_t lod = 0; lod < numMips; ++lod) for (uint32_t lod = 0; lod < numMips; ++lod)
{ {
@@ -353,7 +353,7 @@ namespace bimg
uint32_t mipHeight = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight); uint32_t mipHeight = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);
depth = bx::max<uint32_t>(1, depth); depth = bx::max<uint32_t>(1, depth);
size += uint32_t(uint64_t(mipMidth/blockWidth * mipHeight/blockHeight * depth)*blockSize * sides); size += uint64_t(mipMidth/blockWidth * mipHeight/blockHeight * depth)*blockSize * sides;
width >>= 1; width >>= 1;
height >>= 1; height >>= 1;
@@ -365,13 +365,13 @@ namespace bimg
if (NULL != _info) if (NULL != _info)
{ {
_info->format = _format; _info->format = _format;
_info->width = _width; _info->width = uint16_t(_width);
_info->height = _height; _info->height = uint16_t(_height);
_info->depth = _depth; _info->depth = uint16_t(_depth);
_info->numMips = numMips; _info->numMips = numMips;
_info->numLayers = _numLayers; _info->numLayers = _numLayers;
_info->cubeMap = _cubeMap; _info->cubeMap = _cubeMap;
_info->storageSize = size; _info->storageSize = uint32_t(size);
_info->bitsPerPixel = bpp; _info->bitsPerPixel = bpp;
} }
@@ -1280,14 +1280,19 @@ namespace bimg
{ {
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, _dstFormat , _dstFormat
, uint16_t(_input.m_width) , _input.m_width
, uint16_t(_input.m_height) , _input.m_height
, uint16_t(_input.m_depth) , _input.m_depth
, _input.m_numLayers , _input.m_numLayers
, _input.m_cubeMap , _input.m_cubeMap
, _convertMips && 1 < _input.m_numMips , _convertMips && 1 < _input.m_numMips
); );
if (NULL == output)
{
return NULL;
}
output->m_orientation = _input.m_orientation; output->m_orientation = _input.m_orientation;
const uint16_t numSides = _input.m_numLayers * (_input.m_cubeMap ? 6 : 1); const uint16_t numSides = _input.m_numLayers * (_input.m_cubeMap ? 6 : 1);
@@ -1409,13 +1414,20 @@ namespace bimg
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, imageContainer.m_format , imageContainer.m_format
, uint16_t(imageContainer.m_width) , imageContainer.m_width
, uint16_t(imageContainer.m_height) , imageContainer.m_height
, uint16_t(imageContainer.m_depth) , imageContainer.m_depth
, imageContainer.m_numLayers , imageContainer.m_numLayers
, imageContainer.m_cubeMap , imageContainer.m_cubeMap
, 1 < imageContainer.m_numMips , 1 < imageContainer.m_numMips
); );
if (NULL == output)
{
BX_ERROR_SET(_err, BIMG_ERROR, "Image: Unsupported dimensions.");
return NULL;
}
output->m_srgb = imageContainer.m_srgb; output->m_srgb = imageContainer.m_srgb;
output->m_hasAlpha = imageContainer.m_hasAlpha; output->m_hasAlpha = imageContainer.m_hasAlpha;
@@ -1432,7 +1444,7 @@ namespace bimg
if (imageGetRawData(imageContainer, side, lod, _src, _size, mip) ) if (imageGetRawData(imageContainer, side, lod, _src, _size, mip) )
{ {
uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data); uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data);
bx::memCopy(dstData, mip.m_data, mip.m_size); bx::memCopy(dstData, mip.m_data, bx::min(mip.m_size, dstMip.m_size) );
} }
} }
} }
@@ -3368,21 +3380,41 @@ namespace bimg
} }
} }
ImageContainer* imageAlloc(bx::AllocatorI* _allocator, TextureFormat::Enum _format, uint16_t _width, uint16_t _height, uint16_t _depth, uint16_t _numLayers, bool _cubeMap, bool _hasMips, const void* _data) ImageContainer* imageAlloc(bx::AllocatorI* _allocator, TextureFormat::Enum _format, uint32_t _width, uint32_t _height, uint32_t _depth, uint32_t _numLayers, bool _cubeMap, bool _hasMips, const void* _data)
{ {
const ImageBlockInfo& blockInfo = getBlockInfo(_format); const ImageBlockInfo& blockInfo = getBlockInfo(_format);
const uint16_t blockWidth = blockInfo.blockWidth; const uint32_t blockWidth = blockInfo.blockWidth;
const uint16_t blockHeight = blockInfo.blockHeight; const uint32_t blockHeight = blockInfo.blockHeight;
const uint16_t minBlockX = blockInfo.minBlockX; const uint32_t minBlockX = blockInfo.minBlockX;
const uint16_t minBlockY = blockInfo.minBlockY; const uint32_t minBlockY = blockInfo.minBlockY;
_width = bx::max<uint16_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth); _width = bx::max<uint32_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth);
_height = bx::max<uint16_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight); _height = bx::max<uint32_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::max<uint16_t>(1, _depth); _depth = bx::max<uint32_t>(1, _depth);
_numLayers = bx::max<uint16_t>(1, _numLayers); _numLayers = bx::max<uint32_t>(1, _numLayers);
// Reject dimensions that don't fit in 16 bits. No GPU supports textures
// larger than 65535 in any dimension, and the image format/size helpers
// (and ImageContainer::m_numLayers) are 16-bit; allowing larger values
// would truncate and under-allocate, leading to heap overflow writes when
// pixel data is copied in.
if (_width > UINT16_MAX
|| _height > UINT16_MAX
|| _depth > UINT16_MAX
|| _numLayers > UINT16_MAX)
{
return NULL;
}
const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height, _depth) : 1; const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height, _depth) : 1;
uint32_t size = imageGetSize(NULL, _width, _height, _depth, _cubeMap, _hasMips, _numLayers, _format); uint64_t size = imageGetSize(NULL, _width, _height, _depth, _cubeMap, _hasMips, uint16_t(_numLayers), _format);
// ImageContainer::m_size/m_offset are 32-bit, so reject anything that
// can't be addressed within that range to avoid truncated allocations.
if (size > UINT32_MAX)
{
return NULL;
}
ImageContainer* imageContainer = (ImageContainer*)bx::alignedAlloc(_allocator, size + bx::alignUp(sizeof(ImageContainer), 16), 16); ImageContainer* imageContainer = (ImageContainer*)bx::alignedAlloc(_allocator, size + bx::alignUp(sizeof(ImageContainer), 16), 16);
@@ -3390,12 +3422,12 @@ namespace bimg
imageContainer->m_data = bx::alignPtr(imageContainer + 1, 0, 16); imageContainer->m_data = bx::alignPtr(imageContainer + 1, 0, 16);
imageContainer->m_format = _format; imageContainer->m_format = _format;
imageContainer->m_orientation = Orientation::R0; imageContainer->m_orientation = Orientation::R0;
imageContainer->m_size = size; imageContainer->m_size = uint32_t(size);
imageContainer->m_offset = 0; imageContainer->m_offset = 0;
imageContainer->m_width = _width; imageContainer->m_width = _width;
imageContainer->m_height = _height; imageContainer->m_height = _height;
imageContainer->m_depth = _depth; imageContainer->m_depth = _depth;
imageContainer->m_numLayers = _numLayers; imageContainer->m_numLayers = uint16_t(_numLayers);
imageContainer->m_numMips = numMips; imageContainer->m_numMips = numMips;
imageContainer->m_hasAlpha = false; imageContainer->m_hasAlpha = false;
imageContainer->m_cubeMap = _cubeMap; imageContainer->m_cubeMap = _cubeMap;
@@ -4885,9 +4917,9 @@ namespace bimg
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, imageContainer.m_format , imageContainer.m_format
, uint16_t(imageContainer.m_width) , imageContainer.m_width
, uint16_t(imageContainer.m_height) , imageContainer.m_height
, uint16_t(imageContainer.m_depth) , imageContainer.m_depth
, imageContainer.m_numLayers , imageContainer.m_numLayers
, imageContainer.m_cubeMap , imageContainer.m_cubeMap
, 1 < imageContainer.m_numMips , 1 < imageContainer.m_numMips
@@ -4914,7 +4946,7 @@ namespace bimg
if (imageGetRawData(imageContainer, side, lod, _src, _size, mip) ) if (imageGetRawData(imageContainer, side, lod, _src, _size, mip) )
{ {
uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data); uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data);
bx::memCopy(dstData, mip.m_data, mip.m_size); bx::memCopy(dstData, mip.m_data, bx::min(mip.m_size, dstMip.m_size) );
} }
} }
} }
@@ -5684,7 +5716,7 @@ namespace bimg
{ {
if (isCompressed(_srcFormat)) if (isCompressed(_srcFormat))
{ {
uint32_t size = imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, TextureFormat::RGBA8); uint64_t size = imageGetSize(NULL, _width, _height, 0, false, false, 1, TextureFormat::RGBA8);
void* temp = bx::alloc(_allocator, size); void* temp = bx::alloc(_allocator, size);
imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat); imageDecodeToRgba8(_allocator, temp, _src, _width, _height, _width*4, _srcFormat);
imageConvert(_allocator, dst, TextureFormat::R8, temp, TextureFormat::RGBA8, _width, _height, 1, _width*4, _dstPitch); imageConvert(_allocator, dst, TextureFormat::R8, temp, TextureFormat::RGBA8, _width, _height, 1, _width*4, _dstPitch);
@@ -5858,17 +5890,20 @@ namespace bimg
{ {
ImageContainer* rgba32f = imageAlloc(_allocator ImageContainer* rgba32f = imageAlloc(_allocator
, TextureFormat::RGBA32F , TextureFormat::RGBA32F
, uint16_t(_width) , _width
, uint16_t(_height) , _height
, uint16_t(1) , 1
, 1 , 1
, false , false
, false , false
); );
if (NULL != rgba32f)
{
imageDecodeToRgba32f(_allocator, rgba32f->m_data, _src, _width, _height, 1, _width*16, _srcFormat); imageDecodeToRgba32f(_allocator, rgba32f->m_data, _src, _width, _height, 1, _width*16, _srcFormat);
imageConvert(_allocator, _dst, TextureFormat::BGRA8, rgba32f->m_data, TextureFormat::RGBA32F, _width, _height, 1, _width*16, _dstPitch); imageConvert(_allocator, _dst, TextureFormat::BGRA8, rgba32f->m_data, TextureFormat::RGBA32F, _width, _height, 1, _width*16, _dstPitch);
imageFree(rgba32f); imageFree(rgba32f);
} }
}
else else
{ {
BX_WARN(false, "BC6 decoder is disabled (BIMG_CONFIG_DECODE_BC6)."); BX_WARN(false, "BC6 decoder is disabled (BIMG_CONFIG_DECODE_BC6).");
@@ -6198,7 +6233,7 @@ namespace bimg
image.data_type = ASTCENC_TYPE_U8; image.data_type = ASTCENC_TYPE_U8;
image.data = &_dst; image.data = &_dst;
const uint32_t size = imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, _srcFormat); const uint64_t size = imageGetSize(NULL, _width, _height, 0, false, false, 1, _srcFormat);
static const astcenc_swizzle swizzle static const astcenc_swizzle swizzle
{ //0123/rgba swizzle corresponds to ASTC_RGBA { //0123/rgba swizzle corresponds to ASTC_RGBA
@@ -6389,7 +6424,7 @@ namespace bimg
default: default:
if (isCompressed(_srcFormat) ) if (isCompressed(_srcFormat) )
{ {
uint32_t size = imageGetSize(NULL, uint16_t(_width), uint16_t(_height), 0, false, false, 1, TextureFormat::RGBA8); uint64_t size = imageGetSize(NULL, _width, _height, 0, false, false, 1, TextureFormat::RGBA8);
void* temp = bx::alloc(_allocator, size); void* temp = bx::alloc(_allocator, size);
imageDecodeToRgba8(_allocator, temp, src, _width, _height, _width*4, _srcFormat); imageDecodeToRgba8(_allocator, temp, src, _width, _height, _width*4, _srcFormat);
imageRgba8ToRgba32f(dst, _width, _height, _width*4, temp); imageRgba8ToRgba32f(dst, _width, _height, _width*4, temp);
@@ -6406,7 +6441,7 @@ namespace bimg
bool imageGetRawData(const ImageContainer& _imageContainer, uint16_t _side, uint8_t _lod, const void* _data, uint32_t _size, ImageMip& _mip) bool imageGetRawData(const ImageContainer& _imageContainer, uint16_t _side, uint8_t _lod, const void* _data, uint32_t _size, ImageMip& _mip)
{ {
uint32_t offset = _imageContainer.m_offset; uint64_t offset = _imageContainer.m_offset;
TextureFormat::Enum format = TextureFormat::Enum(_imageContainer.m_format); TextureFormat::Enum format = TextureFormat::Enum(_imageContainer.m_format);
bool hasAlpha = _imageContainer.m_hasAlpha; bool hasAlpha = _imageContainer.m_hasAlpha;
@@ -6459,7 +6494,7 @@ namespace bimg
for (uint16_t side = 0; side < numSides; ++side) for (uint16_t side = 0; side < numSides; ++side)
{ {
BX_ASSERT(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size); BX_ASSERT(offset <= _size, "Reading past size of data buffer! (offset %lld, size %d)", offset, _size);
if (side == _side if (side == _side
&& lod == _lod) && lod == _lod)
@@ -6514,7 +6549,7 @@ namespace bimg
{ {
const uint32_t mipSize = mipSizes[lod]; const uint32_t mipSize = mipSizes[lod];
BX_ASSERT(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size); BX_ASSERT(offset <= _size, "Reading past size of data buffer! (offset %lld, size %d)", offset, _size);
if (uint8_t(lod) == _lod) if (uint8_t(lod) == _lod)
{ {
@@ -6530,7 +6565,7 @@ namespace bimg
return true; return true;
} }
offset += mipSize * numSides; offset += uint64_t(mipSize) * numSides;
offset = ktx2AlignUp(offset, mipAlign); offset = ktx2AlignUp(offset, mipAlign);
} }
} }
@@ -6544,7 +6579,7 @@ namespace bimg
for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod) for (uint8_t lod = 0, num = _imageContainer.m_numMips; lod < num; ++lod)
{ {
BX_ASSERT(offset <= _size, "Reading past size of data buffer! (offset %d, size %d)", offset, _size); BX_ASSERT(offset <= _size, "Reading past size of data buffer! (offset %lld, size %d)", offset, _size);
uint32_t mipWidth = bx::max<uint32_t>(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth); uint32_t mipWidth = bx::max<uint32_t>(blockWidth * minBlockX, ( (width + blockWidth - 1) / blockWidth )*blockWidth);
uint32_t mipHeight = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight); uint32_t mipHeight = bx::max<uint32_t>(blockHeight * minBlockY, ( (height + blockHeight - 1) / blockHeight)*blockHeight);

View File

@@ -215,14 +215,20 @@ namespace bimg
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, _input.m_format , _input.m_format
, uint16_t(dstWidth) , dstWidth
, uint16_t(dstWidth) , dstWidth
, uint16_t(1) , 1
, 1 , 1
, true , true
, false , false
); );
if (NULL == output)
{
BX_ERROR_SET(_err, BIMG_ERROR, "Unsupported dimensions.");
return NULL;
}
const uint8_t* srcData = (const uint8_t*)_input.m_data; const uint8_t* srcData = (const uint8_t*)_input.m_data;
for (uint8_t side = 0; side < 6 && _err->isOk(); ++side) for (uint8_t side = 0; side < 6 && _err->isOk(); ++side)
@@ -350,14 +356,20 @@ namespace bimg
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, _input.m_format , _input.m_format
, uint16_t(dstWidth) , dstWidth
, uint16_t(dstWidth) , dstWidth
, uint16_t(1) , 1
, 1 , 1
, true , true
, false , false
); );
if (NULL == output)
{
BX_ERROR_SET(_err, BIMG_ERROR, "Unsupported dimensions.");
return NULL;
}
const uint8_t* srcData = (const uint8_t*)_input.m_data; const uint8_t* srcData = (const uint8_t*)_input.m_data;
for (uint8_t side = 0; side < 6 && _err->isOk(); ++side, srcData += step) for (uint8_t side = 0; side < 6 && _err->isOk(); ++side, srcData += step)
@@ -401,7 +413,12 @@ namespace bimg
const uint32_t dstPitch = dstWidth*16; const uint32_t dstPitch = dstWidth*16;
const float texelSize = 1.0f / float(dstWidth); const float texelSize = 1.0f / float(dstWidth);
ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, uint16_t(dstWidth), uint16_t(dstWidth), 1, 1, true, false); ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, dstWidth, dstWidth, 1, 1, true, false);
if (NULL == output)
{
return NULL;
}
for (uint8_t side = 0; side < 6; ++side) for (uint8_t side = 0; side < 6; ++side)
{ {
@@ -1033,7 +1050,12 @@ namespace bimg
return NULL; return NULL;
} }
ImageContainer* output = imageAlloc(_allocator, _image.m_format, uint16_t(_image.m_width), uint16_t(_image.m_height), uint16_t(_image.m_depth), _image.m_numLayers, _image.m_cubeMap, true); ImageContainer* output = imageAlloc(_allocator, _image.m_format, _image.m_width, _image.m_height, _image.m_depth, _image.m_numLayers, _image.m_cubeMap, true);
if (NULL == output)
{
return NULL;
}
const uint32_t numMips = output->m_numMips; const uint32_t numMips = output->m_numMips;
const uint32_t numLayers = output->m_numLayers; const uint32_t numLayers = output->m_numLayers;
@@ -1136,14 +1158,33 @@ namespace bimg
ImageContainer* input = imageConvert(_allocator, TextureFormat::RGBA32F, _image, true); ImageContainer* input = imageConvert(_allocator, TextureFormat::RGBA32F, _image, true);
if (NULL == input)
{
BX_ERROR_SET(_err, BIMG_ERROR, "Unsupported dimensions.");
return NULL;
}
if (1 >= input->m_numMips) if (1 >= input->m_numMips)
{ {
ImageContainer* temp = imageGenerateMips(_allocator, *input); ImageContainer* temp = imageGenerateMips(_allocator, *input);
imageFree(input); imageFree(input);
input = temp; input = temp;
if (NULL == input)
{
BX_ERROR_SET(_err, BIMG_ERROR, "Unsupported dimensions.");
return NULL;
}
} }
ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, uint16_t(input->m_width), uint16_t(input->m_width), 1, 1, true, true); ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, input->m_width, input->m_width, 1, 1, true, true);
if (NULL == output)
{
imageFree(input);
BX_ERROR_SET(_err, BIMG_ERROR, "Unsupported dimensions.");
return NULL;
}
for (uint8_t side = 0; side < 6; ++side) for (uint8_t side = 0; side < 6; ++side)
{ {
@@ -1155,7 +1196,7 @@ namespace bimg
uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data); uint8_t* dstData = const_cast<uint8_t*>(dstMip.m_data);
bx::memCopy(dstData, srcMip.m_data, srcMip.m_size); bx::memCopy(dstData, srcMip.m_data, bx::min(srcMip.m_size, dstMip.m_size) );
} }
const float glossScale = 10.0f; const float glossScale = 10.0f;

View File

@@ -18,6 +18,7 @@ BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4100) // error C4100: '' : unreferenced formal
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4245) // warning C4245: 'return': conversion from 'int' to 'size_t', signed/unsigned mismatch BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4245) // warning C4245: 'return': conversion from 'int' to 'size_t', signed/unsigned mismatch
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4389) // warning C4389 : '==' : signed / unsigned mismatch BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4389) // warning C4389 : '==' : signed / unsigned mismatch
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505) // warning C4505: 'tinyexr::miniz::def_realloc_func': unreferenced local function has been removed BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4505) // warning C4505: 'tinyexr::miniz::def_realloc_func': unreferenced local function has been removed
BX_PRAGMA_DIAGNOSTIC_IGNORED_MSVC(4702) // warning C4702: unreachable code
#define MINIZ_NO_ARCHIVE_APIS #define MINIZ_NO_ARCHIVE_APIS
#define MINIZ_NO_ARCHIVE_WRITING_APIS #define MINIZ_NO_ARCHIVE_WRITING_APIS
#define MINIZ_NO_STDIO #define MINIZ_NO_STDIO
@@ -317,8 +318,8 @@ namespace bimg
output = imageAlloc(_allocator output = imageAlloc(_allocator
, dstFormat , dstFormat
, uint16_t(width) , width
, uint16_t(height) , height
, 0 , 0
, 1 , 1
, false , false
@@ -326,6 +327,12 @@ namespace bimg
, copyData , copyData
); );
if (NULL == output)
{
BX_ERROR_SET(_err, BIMG_ERROR, "PNG: Unsupported dimensions.");
}
else
{
if (palette) if (palette)
{ {
if (1 == state.info_raw.bitdepth) if (1 == state.info_raw.bitdepth)
@@ -506,6 +513,7 @@ namespace bimg
break; break;
} }
} }
}
else else
{ {
BX_ERROR_SET(_err, BIMG_ERROR, "PNG: Unsupported format."); BX_ERROR_SET(_err, BIMG_ERROR, "PNG: Unsupported format.");
@@ -727,8 +735,8 @@ namespace bimg
{ {
output = imageAlloc(_allocator output = imageAlloc(_allocator
, format , format
, uint16_t(width) , width
, uint16_t(height) , height
, 0 , 0
, 1 , 1
, false , false
@@ -736,6 +744,13 @@ namespace bimg
, data , data
); );
bx::free(_allocator, data); bx::free(_allocator, data);
if (NULL == output)
{
BX_ERROR_SET(_err, BIMG_ERROR, "EXR: Unsupported dimensions.");
return NULL;
}
output->m_hasAlpha = hasAlpha; output->m_hasAlpha = hasAlpha;
} }
@@ -799,8 +814,8 @@ namespace bimg
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, format , format
, bx::narrowCast<uint16_t>(width) , width
, bx::narrowCast<uint16_t>(height) , height
, 0 , 0
, 1 , 1
, false , false
@@ -809,6 +824,12 @@ namespace bimg
); );
stbi_image_free(data); stbi_image_free(data);
if (NULL == output)
{
BX_ERROR_SET(_err, BIMG_ERROR, "stb_image: Unsupported dimensions.");
return NULL;
}
return output; return output;
#else #else
BX_UNUSED(_allocator, _data, _size); BX_UNUSED(_allocator, _data, _size);
@@ -995,8 +1016,8 @@ namespace bimg
output = imageAlloc(_allocator output = imageAlloc(_allocator
, format , format
, bx::narrowCast<uint16_t>(width) , width
, bx::narrowCast<uint16_t>(height) , height
, 0 , 0
, 1 , 1
, false , false
@@ -1004,8 +1025,11 @@ namespace bimg
, NULL , NULL
); );
if (NULL != output)
{
bx::memCopy(output->m_data, dstStride, data, srcStride, dstStride, height); bx::memCopy(output->m_data, dstStride, data, srcStride, dstStride, height);
} }
}
heif_image_release(image); heif_image_release(image);
heif_image_handle_release(handle); heif_image_handle_release(handle);
@@ -1101,8 +1125,8 @@ namespace bimg
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, bimg::TextureFormat::RGBA8 , bimg::TextureFormat::RGBA8
, bx::narrowCast<uint16_t>(width) , uint32_t(width)
, bx::narrowCast<uint16_t>(height) , uint32_t(height)
, 0 , 0
, 1 , 1
, false , false
@@ -1110,6 +1134,13 @@ namespace bimg
, data , data
); );
if (NULL == output)
{
bx::free(_allocator, data);
BX_ERROR_SET(_err, BIMG_ERROR, "WebP: Unsupported dimensions.");
return NULL;
}
bool hasAlpha = false; bool hasAlpha = false;
for (uint32_t ii = 0, num = uint32_t(width * height); ii < num; ++ii) for (uint32_t ii = 0, num = uint32_t(width * height); ii < num; ++ii)

View File

@@ -374,14 +374,19 @@ namespace bimg
{ {
ImageContainer* output = imageAlloc(_allocator ImageContainer* output = imageAlloc(_allocator
, _dstFormat , _dstFormat
, uint16_t(_input.m_width) , _input.m_width
, uint16_t(_input.m_height) , _input.m_height
, uint16_t(_input.m_depth) , _input.m_depth
, _input.m_numLayers , _input.m_numLayers
, _input.m_cubeMap , _input.m_cubeMap
, 1 < _input.m_numMips , 1 < _input.m_numMips
); );
if (NULL == output)
{
return NULL;
}
const uint16_t numSides = _input.m_numLayers * (_input.m_cubeMap ? 6 : 1); const uint16_t numSides = _input.m_numLayers * (_input.m_cubeMap ? 6 : 1);
bx::Error err; bx::Error err;

View File

@@ -393,7 +393,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
// Normal map. // Normal map.
if (_options.normalMap) if (_options.normalMap)
{ {
uint32_t size = bimg::imageGetSize( uint32_t size = (uint32_t)bimg::imageGetSize(
NULL NULL
, uint16_t(dstMip.m_width) , uint16_t(dstMip.m_width)
, uint16_t(dstMip.m_height) , uint16_t(dstMip.m_height)
@@ -507,7 +507,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
|| outputFormat == bimg::TextureFormat::BC7 || outputFormat == bimg::TextureFormat::BC7
) )
{ {
uint32_t size = bimg::imageGetSize( uint32_t size = (uint32_t)bimg::imageGetSize(
NULL NULL
, uint16_t(dstMip.m_width) , uint16_t(dstMip.m_width)
, uint16_t(dstMip.m_height) , uint16_t(dstMip.m_height)
@@ -619,7 +619,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
// SDF // SDF
else if (_options.sdf) else if (_options.sdf)
{ {
uint32_t size = bimg::imageGetSize( uint32_t size = (uint32_t)bimg::imageGetSize(
NULL NULL
, uint16_t(dstMip.m_width) , uint16_t(dstMip.m_width)
, uint16_t(dstMip.m_height) , uint16_t(dstMip.m_height)
@@ -665,7 +665,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
, alphaRef , alphaRef
); );
size = bimg::imageGetSize( size = (uint32_t)bimg::imageGetSize(
NULL NULL
, uint16_t(dstMip.m_width) , uint16_t(dstMip.m_width)
, uint16_t(dstMip.m_height) , uint16_t(dstMip.m_height)
@@ -737,7 +737,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
// RGBA8 // RGBA8
else else
{ {
uint32_t size = bimg::imageGetSize( uint32_t size = (uint32_t)bimg::imageGetSize(
NULL NULL
, uint16_t(dstMip.m_width) , uint16_t(dstMip.m_width)
, uint16_t(dstMip.m_height) , uint16_t(dstMip.m_height)