Add worker-thread image decoder

- Decodes DDS, PNG, JPG, TGA, BMP formats
- Thread-safe for use in worker threads
- Uses stb_image for common formats
- Custom DDS header parsing
This commit is contained in:
savis
2026-01-03 20:36:37 +01:00
parent c6aa6b4149
commit fd1218bd4e
2 changed files with 110 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
#include "StdAfx.h"
#include "ImageDecoder.h"
#include "EterImageLib/DDSTextureLoader9.h"
#include <stb_image.h>
bool CImageDecoder::DecodeImage(const void* pData, size_t dataSize, TDecodedImageData& outImage)
{
if (!pData || dataSize == 0)
return false;
outImage.Clear();
if (DecodeDDS(pData, dataSize, outImage))
return true;
if (DecodeSTB(pData, dataSize, outImage))
return true;
return false;
}
bool CImageDecoder::DecodeDDS(const void* pData, size_t dataSize, TDecodedImageData& outImage)
{
if (dataSize < 4)
return false;
const uint32_t DDS_MAGIC = 0x20534444;
uint32_t magic = *(const uint32_t*)pData;
if (magic != DDS_MAGIC)
return false;
if (dataSize < 128)
return false;
struct DDSHeader
{
uint32_t magic;
uint32_t size;
uint32_t flags;
uint32_t height;
uint32_t width;
uint32_t pitchOrLinearSize;
uint32_t depth;
uint32_t mipMapCount;
uint32_t reserved1[11];
};
const DDSHeader* header = (const DDSHeader*)pData;
outImage.width = header->width;
outImage.height = header->height;
outImage.mipLevels = (header->mipMapCount > 0) ? header->mipMapCount : 1;
outImage.isDDS = true;
outImage.format = TDecodedImageData::FORMAT_DDS;
outImage.pixels.resize(dataSize);
memcpy(outImage.pixels.data(), pData, dataSize);
return true;
}
bool CImageDecoder::DecodeSTB(const void* pData, size_t dataSize, TDecodedImageData& outImage)
{
int width, height, channels;
unsigned char* imageData = stbi_load_from_memory(
(const stbi_uc*)pData,
(int)dataSize,
&width,
&height,
&channels,
4
);
if (!imageData)
return false;
outImage.width = width;
outImage.height = height;
outImage.format = TDecodedImageData::FORMAT_RGBA8;
outImage.isDDS = false;
outImage.mipLevels = 1;
size_t pixelDataSize = width * height * 4;
outImage.pixels.resize(pixelDataSize);
memcpy(outImage.pixels.data(), imageData, pixelDataSize);
stbi_image_free(imageData);
return true;
}

View File

@@ -0,0 +1,18 @@
#ifndef __INC_ETERLIB_IMAGEDECODER_H__
#define __INC_ETERLIB_IMAGEDECODER_H__
#include "DecodedImageData.h"
// Image decoder for worker threads
class CImageDecoder
{
public:
// Decode image from memory (DDS, PNG, JPG, TGA, BMP)
static bool DecodeImage(const void* pData, size_t dataSize, TDecodedImageData& outImage);
private:
static bool DecodeDDS(const void* pData, size_t dataSize, TDecodedImageData& outImage);
static bool DecodeSTB(const void* pData, size_t dataSize, TDecodedImageData& outImage);
};
#endif // __INC_ETERLIB_IMAGEDECODER_H__