forked from metin-server/m2dev-client-src
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:
92
src/EterLib/ImageDecoder.cpp
Normal file
92
src/EterLib/ImageDecoder.cpp
Normal 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;
|
||||
}
|
||||
18
src/EterLib/ImageDecoder.h
Normal file
18
src/EterLib/ImageDecoder.h
Normal 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__
|
||||
Reference in New Issue
Block a user