Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/bimg/bimg.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ namespace bx

namespace bimg
{
///
typedef void (*PackFn)(void*, const float*);

///
typedef void (*UnpackFn)(float*, const void*);

/// Texture format enum.
Expand Down Expand Up @@ -225,6 +228,7 @@ namespace bimg
bool cubeMap; //!< Texture is cubemap.
};

///
struct ImageContainer
{
bx::AllocatorI* m_allocator;
Expand All @@ -249,6 +253,7 @@ namespace bimg
bool m_srgb;
};

///
struct ImageMip
{
TextureFormat::Enum m_format;
Expand All @@ -262,6 +267,7 @@ namespace bimg
const uint8_t* m_data;
};

///
struct ImageBlockInfo
{
uint8_t bitsPerPixel;
Expand Down Expand Up @@ -309,6 +315,19 @@ namespace bimg
/// Converts image source format to string.
const char* getName(ImageParser::Enum _parser);

/// Returns true if image is a volume (3D) texture.
inline bool isVolume(const ImageContainer& _imageContainer)
{
return 0 != _imageContainer.m_depth;
}

/// Returns the number of depth slices; one for anything that is not a volume
/// (3D) texture.
inline uint32_t imageGetNumSlices(const ImageContainer& _imageContainer)
{
return 0 != _imageContainer.m_depth ? _imageContainer.m_depth : 1;
}

/// Returns number of mip-maps required for complete mip-map chain.
uint8_t imageGetNumMips(
TextureFormat::Enum _format
Expand Down
2 changes: 1 addition & 1 deletion src/bimg_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ namespace bimg
TextureFormat::Enum m_format;
uint16_t m_width;
uint16_t m_height;
uint16_t m_depth;
uint16_t m_depth; //!< Zero if this is not a volume (3D) texture.
uint16_t m_numLayers;
uint8_t m_numMips;
bool m_cubeMap;
Expand Down
49 changes: 23 additions & 26 deletions src/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -651,10 +651,9 @@ namespace bimg
const uint32_t pitch = _imageContainer->m_width*16;
const uint32_t slice = _imageContainer->m_height*pitch;

for (uint32_t zz = 0, depth = _imageContainer->m_depth; zz < depth; ++zz)
for (uint32_t zz = 0, depth = mip.m_depth; zz < depth; ++zz)
{
const uint32_t srcDataStep = uint32_t(bx::floor(zz * _imageContainer->m_depth / float(depth) ) );
const uint8_t* srcData = &mip.m_data[srcDataStep*slice];
const uint8_t* srcData = &mip.m_data[zz*slice];

imageRgba32fToLinear(const_cast<uint8_t*>(srcData), mip.m_width, mip.m_height, 1, pitch, srcData);
}
Expand Down Expand Up @@ -697,10 +696,9 @@ namespace bimg
const uint32_t pitch = _imageContainer->m_width*16;
const uint32_t slice = _imageContainer->m_height*pitch;

for (uint32_t zz = 0, depth = _imageContainer->m_depth; zz < depth; ++zz)
for (uint32_t zz = 0, depth = mip.m_depth; zz < depth; ++zz)
{
const uint32_t srcDataStep = uint32_t(bx::floor(zz * _imageContainer->m_depth / float(depth) ) );
const uint8_t* srcData = &mip.m_data[srcDataStep*slice];
const uint8_t* srcData = &mip.m_data[zz*slice];

imageRgba32fToGamma(const_cast<uint8_t*>(srcData), mip.m_width, mip.m_height, 1, pitch, srcData);
}
Expand Down Expand Up @@ -3624,14 +3622,10 @@ namespace bimg

_width = bx::max<uint32_t>(blockWidth * minBlockX, ( (_width + blockWidth - 1) / blockWidth)*blockWidth);
_height = bx::max<uint32_t>(blockHeight * minBlockY, ( (_height + blockHeight - 1) / blockHeight)*blockHeight);
_depth = bx::max<uint32_t>(1, _depth);
_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.
const uint32_t numSlices = bx::max<uint32_t>(1, _depth);

if (_width > UINT16_MAX
|| _height > UINT16_MAX
|| _depth > UINT16_MAX
Expand All @@ -3640,11 +3634,9 @@ namespace bimg
return NULL;
}

const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height, _depth) : 1;
uint64_t size = imageGetSize(NULL, _width, _height, _depth, _cubeMap, _hasMips, uint16_t(_numLayers), _format);
const uint8_t numMips = _hasMips ? imageGetNumMips(_format, _width, _height, numSlices) : 1;
uint64_t size = imageGetSize(NULL, _width, _height, numSlices, _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;
Expand Down Expand Up @@ -4114,6 +4106,7 @@ namespace bimg

uint32_t dxgiFormat = 0;
uint32_t arraySize = 1;
bool volume = 0 != (caps[1] & DDSCAPS2_VOLUME);
if (DDPF_FOURCC == (pixelFlags & DDPF_FOURCC)
&& DDS_DX10 == fourcc)
{
Expand All @@ -4129,8 +4122,12 @@ namespace bimg

uint32_t miscFlags2;
total += bx::read(_reader, miscFlags2, _err);

volume = DDS_DX10_DIMENSION_TEXTURE3D == dims;
}

depth = volume ? bx::max<uint32_t>(1, depth) : 0;

BX_UNUSED(total);

if (!_err->isOk() )
Expand Down Expand Up @@ -4622,7 +4619,7 @@ namespace bimg
_imageContainer.m_offset = (uint32_t)offset;
_imageContainer.m_width = width;
_imageContainer.m_height = height;
_imageContainer.m_depth = bx::max<uint32_t>(depth, 1);
_imageContainer.m_depth = depth;
_imageContainer.m_format = format;
_imageContainer.m_orientation = Orientation::R0;
_imageContainer.m_numLayers = uint16_t(bx::max<uint32_t>(numberOfArrayElements, 1) );
Expand Down Expand Up @@ -5027,11 +5024,11 @@ namespace bimg
const uint32_t numFaces = bx::max<uint32_t>(faceCount, 1);
const uint32_t width = bx::max<uint32_t>(pixelWidth, 1);
const uint32_t height = bx::max<uint32_t>(pixelHeight, 1);
const uint32_t depth = bx::max<uint32_t>(pixelDepth, 1);
const uint32_t depth = pixelDepth;
const bool cubeMap = (6 == faceCount);

if (16 < numMips
|| (cubeMap && 1 != depth) )
|| (cubeMap && 0 != depth) )
{
BX_ERROR_SET(_err, BIMG_ERROR, "KTX2: Invalid header values.");
return false;
Expand Down Expand Up @@ -5529,7 +5526,7 @@ namespace bimg
total += bx::write(_writer, typeSize, _err);
total += bx::write(_writer, _width, _err);
total += bx::write(_writer, _height, _err);
total += bx::write(_writer, _depth > 1 ? _depth : uint32_t(0), _err); // pixelDepth = 0 for 2D/cube
total += bx::write(_writer, _depth, _err); // pixelDepth = 0 for 2D/cube
total += bx::write(_writer, _numLayers > 1 ? _numLayers : uint32_t(0), _err); // layerCount = 0 for non-array
total += bx::write(_writer, uint32_t(_cubeMap ? 6 : 1), _err); // faceCount
total += bx::write(_writer, numMips, _err); // levelCount
Expand Down Expand Up @@ -5679,7 +5676,7 @@ namespace bimg
total += bx::write(_writer, typeSize, _err);
total += bx::write(_writer, _imageContainer.m_width, _err);
total += bx::write(_writer, _imageContainer.m_height, _err);
total += bx::write(_writer, _imageContainer.m_depth > 1 ? _imageContainer.m_depth : uint32_t(0), _err);
total += bx::write(_writer, _imageContainer.m_depth, _err);
total += bx::write(_writer, _imageContainer.m_numLayers > 1 ? uint32_t(_imageContainer.m_numLayers) : uint32_t(0), _err);
total += bx::write(_writer, uint32_t(_imageContainer.m_cubeMap ? 6 : 1), _err);
total += bx::write(_writer, numMips, _err);
Expand Down Expand Up @@ -5877,7 +5874,7 @@ namespace bimg
_imageContainer.m_offset = (uint32_t)offset;
_imageContainer.m_width = width;
_imageContainer.m_height = height;
_imageContainer.m_depth = depth;
_imageContainer.m_depth = 1 < depth ? depth : 0;
_imageContainer.m_format = format;
_imageContainer.m_orientation = Orientation::R0;
_imageContainer.m_numLayers = 1;
Expand Down Expand Up @@ -7415,7 +7412,7 @@ namespace bimg
| DDSD_WIDTH
| DDSD_PIXELFORMAT
| DDSD_CAPS
| (1 < _depth ? DDSD_DEPTH : 0)
| (0 != _depth ? DDSD_DEPTH : 0)
| (1 < _numMips ? DDSD_MIPMAPCOUNT : 0)
| (isCompressed(_format) ? DDSD_LINEARSIZE : DDSD_PITCH)
)
Expand Down Expand Up @@ -7464,7 +7461,7 @@ namespace bimg
uint32_t caps[4] =
{
uint32_t(DDSCAPS_TEXTURE | (1 < _numMips ? DDSCAPS_COMPLEX|DDSCAPS_MIPMAP : 0) ),
uint32_t(_cubeMap ? DDSCAPS2_CUBEMAP|DSCAPS2_CUBEMAP_ALLSIDES : 0),
uint32_t(_cubeMap ? DDSCAPS2_CUBEMAP|DSCAPS2_CUBEMAP_ALLSIDES : (0 != _depth ? DDSCAPS2_VOLUME : 0) ),
0,
0,
};
Expand All @@ -7482,7 +7479,7 @@ namespace bimg
if (UINT32_MAX != dxgiFormat)
{
total += bx::write(_writer, dxgiFormat, _err);
total += bx::write(_writer, uint32_t(1 < _depth ? DDS_DX10_DIMENSION_TEXTURE3D : DDS_DX10_DIMENSION_TEXTURE2D), _err); // dims
total += bx::write(_writer, uint32_t(0 != _depth ? DDS_DX10_DIMENSION_TEXTURE3D : DDS_DX10_DIMENSION_TEXTURE2D), _err); // dims
total += bx::write(_writer, uint32_t(_cubeMap ? DDS_DX10_MISC_TEXTURECUBE : 0), _err); // miscFlags
total += bx::write(_writer, uint32_t(_numLayers), _err); // arraySize
total += bx::write(_writer, uint32_t(0), _err); // miscFlags2
Expand Down Expand Up @@ -7555,7 +7552,7 @@ namespace bimg
total += bx::write(_writer, tfi.m_fmt, _err); // glBaseInternalFormat
total += bx::write(_writer, _width, _err);
total += bx::write(_writer, _height, _err);
total += bx::write(_writer, _depth > 1 ? _depth : uint32_t(0), _err); // For 2D and cube textures pixelDepth must be 0.
total += bx::write(_writer, _depth, _err); // For 2D and cube textures pixelDepth must be 0.
total += bx::write(_writer, _numLayers > 1 ? _numLayers : uint32_t(0), _err); // numberOfArrayElements; If the texture is not an array texture, numberOfArrayElements must equal 0.
total += bx::write(_writer, _cubeMap ? uint32_t(6) : uint32_t(1), _err); // numberOfFaces; For cubemaps and cubemap arrays this should be 6. For non cubemaps this should be 1
total += bx::write(_writer, uint32_t(_numMips), _err);
Expand Down
12 changes: 6 additions & 6 deletions src/image_cubemap_filter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ namespace bimg
{
BX_ERROR_SCOPE(_err);

if (_input.m_depth != 1
if (0 != _input.m_depth
&& _input.m_numLayers != 1
&& _input.m_format != TextureFormat::RGBA32F
&& _input.m_width/2 != _input.m_height)
Expand All @@ -217,7 +217,7 @@ namespace bimg
, _input.m_format
, dstWidth
, dstWidth
, 1
, 0
, 1
, true
, false
Expand Down Expand Up @@ -339,7 +339,7 @@ namespace bimg
{
BX_ERROR_SCOPE(_err);

if (_input.m_depth != 1
if (0 != _input.m_depth
&& _input.m_numLayers != 1
&& _input.m_format != TextureFormat::RGBA32F
&& ( (_input.m_width != _input.m_height*6) || (_input.m_width*6 != _input.m_height) ) )
Expand All @@ -358,7 +358,7 @@ namespace bimg
, _input.m_format
, dstWidth
, dstWidth
, 1
, 0
, 1
, true
, false
Expand Down Expand Up @@ -413,7 +413,7 @@ namespace bimg
const uint32_t dstPitch = dstWidth*16;
const float texelSize = 1.0f / float(dstWidth);

ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, dstWidth, dstWidth, 1, 1, true, false);
ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, dstWidth, dstWidth, 0, 1, true, false);

if (NULL == output)
{
Expand Down Expand Up @@ -1177,7 +1177,7 @@ namespace bimg
}
}

ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, input->m_width, input->m_width, 1, 1, true, true);
ImageContainer* output = imageAlloc(_allocator, TextureFormat::RGBA32F, input->m_width, input->m_width, 0, 1, true, true);

if (NULL == output)
{
Expand Down
2 changes: 1 addition & 1 deletion src/image_decode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ namespace bimg
_imageContainer.m_offset = UINT32_MAX;
_imageContainer.m_width = _width;
_imageContainer.m_height = _height;
_imageContainer.m_depth = 1;
_imageContainer.m_depth = 0;
_imageContainer.m_numLayers = 1;
_imageContainer.m_numMips = 1;
_imageContainer.m_hasAlpha = false;
Expand Down
2 changes: 1 addition & 1 deletion src/image_decode_wic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ namespace bimg
if (0 < width
&& 0 < height)
{
image = imageAlloc(_allocator, TextureFormat::RGBA8, width, height, 1, 1, false, false);
image = imageAlloc(_allocator, TextureFormat::RGBA8, width, height, 0, 1, false, false);
if (NULL != image)
{
hr = converter->CopyPixels(NULL, width * 4, image->m_size, (BYTE*)image->m_data);
Expand Down
4 changes: 2 additions & 2 deletions src/image_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,9 +630,9 @@ namespace bimg
const uint32_t dstPitch = _dst->m_width*16;
const uint32_t dstSlice = _dst->m_height*dstPitch;

for (uint32_t zz = 0, depth = _dst->m_depth; zz < depth; ++zz, dstData += dstSlice)
for (uint32_t zz = 0, depth = dstMip.m_depth; zz < depth; ++zz, dstData += dstSlice)
{
const uint32_t srcDataStep = uint32_t(bx::floor(zz * _src->m_depth / float(_dst->m_depth) ) );
const uint32_t srcDataStep = uint32_t(bx::floor(zz * srcMip.m_depth / float(depth) ) );
const uint8_t* srcData = &srcMip.m_data[srcDataStep*srcSlice];

void* result = stbir_resize(
Expand Down
2 changes: 1 addition & 1 deletion tools/meta/meta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ static bool processFile(bx::AllocatorI* _allocator, const char* _filePath)
, info.m_height
);

if (info.m_depth > 1)
if (0 != info.m_depth)
{
bx::printf(" x %u", info.m_depth);
}
Expand Down
6 changes: 3 additions & 3 deletions tools/texturec/texturec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,13 +170,13 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
{
outputWidth = bx::max(blockWidth * minBlockX, ( ( (outputWidth>>1) + blockWidth - 1) / blockWidth )*blockWidth);
outputHeight = bx::max(blockHeight * minBlockY, ( ( (outputHeight>>1) + blockHeight - 1) / blockHeight)*blockHeight);
outputDepth = bx::max(outputDepth>>1, 1u);
outputDepth = 0 != outputDepth ? bx::max(outputDepth>>1, 1u) : 0;
}
}

if (_options.equirect)
{
if (outputDepth == 1
if (outputDepth == 0
&& outputWidth/2 == outputHeight)
{
if (outputWidth/2 > _options.maxSize)
Expand All @@ -195,7 +195,7 @@ bimg::ImageContainer* convert(bx::AllocatorI* _allocator, const void* _inputData
}
else if (_options.strip)
{
if (outputDepth == 1
if (outputDepth == 0
&& ( (outputWidth == outputHeight*6) || (outputWidth*6 == outputHeight) ) )
{
const bool horizontal = outputWidth == outputHeight*6;
Expand Down
Loading