From f7f1478ecfbfa07bc86a4c84fc63cb1f54806bdc Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Thu, 7 Sep 2023 16:27:41 +0800 Subject: [PATCH] fix CKContext prevobj error. finish bitmap reader / writer --- LibCmo/CK2/CKContext.cpp | 16 +- LibCmo/CK2/CKTypes.hpp | 46 +++- LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp | 274 ++++++++++++++++++++ LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp | 98 +++++++ LibCmo/LibCmo.vcxproj | 4 + LibCmo/LibCmo.vcxproj.filters | 18 ++ LibCmo/VTImage.cpp | 9 + LibCmo/VxMath/VxMath.cpp | 109 ++++++++ LibCmo/VxMath/VxMath.hpp | 39 ++- LibCmo/VxMath/VxTypes.hpp | 99 +++---- 10 files changed, 655 insertions(+), 57 deletions(-) create mode 100644 LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp create mode 100644 LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp create mode 100644 LibCmo/VTImage.cpp create mode 100644 LibCmo/VxMath/VxMath.cpp diff --git a/LibCmo/CK2/CKContext.cpp b/LibCmo/CK2/CKContext.cpp index a7af4e9..5fb86cd 100644 --- a/LibCmo/CK2/CKContext.cpp +++ b/LibCmo/CK2/CKContext.cpp @@ -87,11 +87,17 @@ namespace LibCmo::CK2 { } ObjImpls::CKObject* GeneralPrevFinder(XContainer::XObjectPointerArray& objptrs, ObjImpls::CKObject* previous) { - auto finder = std::find(objptrs.begin(), objptrs.end(), previous); - if (finder == objptrs.end()) return nullptr; - ++finder; - if (finder == objptrs.end()) return nullptr; - return *finder; + if (objptrs.empty()) return nullptr; + + if (previous == nullptr) { + return objptrs.front(); + } else { + auto finder = std::find(objptrs.begin(), objptrs.end(), previous); + if (finder == objptrs.end()) return nullptr; + ++finder; + if (finder == objptrs.end()) return nullptr; + return *finder; + } } ObjImpls::CKObject* CKContext::GetObjectByName(CKSTRING name, ObjImpls::CKObject* previous) { if (name == nullptr) return nullptr; diff --git a/LibCmo/CK2/CKTypes.hpp b/LibCmo/CK2/CKTypes.hpp index 457e04f..cd7957c 100644 --- a/LibCmo/CK2/CKTypes.hpp +++ b/LibCmo/CK2/CKTypes.hpp @@ -262,12 +262,11 @@ namespace LibCmo::CK2 { //class CKFile; class CKDependencies; class CKDependenciesContext; - class CKPluginManager; class CKDebugContext; class CKObjectArray; class CKObjectDeclaration; //class CKContext; - struct CKBitmapProperties; + //struct CKBitmapProperties; class CKVertexBuffer; //--- Managers @@ -284,6 +283,13 @@ namespace LibCmo::CK2 { class CKPathManager; class CKVariableManager; class CKSceneObjectDesc; + class CKPluginManager; + } + + namespace DataHandlers { + class CKBitmapHandler; + class CKMovieHandler; + class CKSoundHandler; } //--- Important classes @@ -360,5 +366,41 @@ namespace LibCmo::CK2 { } }; + + /** + * The struct describe the bitmap handler's infomation, + * including its GUID and supported file extension. + * This struct also will store some parameters related to bitmap handler, + * such as jpeg compress level and etc. But currently there are no + * such parameters. + */ + struct CKBitmapProperties { + CKBitmapProperties() : + m_ReaderGuid(), m_Ext(3, '\0') {} + CKBitmapProperties(CKGUID& guid, const char* ext) : + m_ReaderGuid(guid), m_Ext(3, '\0') { + SetExt(ext); + } + LIBCMO_DEFAULT_COPY_MOVE(CKBitmapProperties); + + void SetExt(const char* s) { + if (s == nullptr) { + m_Ext[0] = '\0'; + } else { + if (s[0] == '.') ++s; // skip dot + size_t len = std::strlen(s); + if (len > m_Ext.size()) len = m_Ext.size(); + std::memcpy(m_Ext.data(), s, len); + } + } + + CKSTRING ExtToCKSTRING() { + return m_Ext.c_str(); + } + + CKGUID m_ReaderGuid; /**< CKGUID that uniquely identifies the reader that created this properties structure */ + std::string m_Ext; /**< File Extension of the image being described by this structure */ + }; + } diff --git a/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp b/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp new file mode 100644 index 0000000..7cbec6b --- /dev/null +++ b/LibCmo/CK2/DataHandlers/CKBitmapHandler.cpp @@ -0,0 +1,274 @@ +#include "CKBitmapHandler.hpp" +#include "stb_image.h" +#include "stb_image_write.h" +#include "stb_image_resize.h" + +namespace LibCmo::CK2::DataHandlers { + + static void RGBAToARGB(CK2::CKDWORD count, const void* _rgba, void* _argb) { + const char* rgba = reinterpret_cast(_rgba); + char* argb = reinterpret_cast(_argb); + // copy RGB + VxMath::VxCopyStructure( + count, + argb + sizeof(uint8_t), + 4 * sizeof(uint8_t), + 3 * sizeof(uint8_t), + rgba, + 4 * sizeof(uint8_t) + ); + // copy A + VxMath::VxCopyStructure( + count, + argb, + 4 * sizeof(uint8_t), + sizeof(uint8_t), + rgba + (3 * sizeof(uint8_t)), + 4 * sizeof(uint8_t) + ); + } + + static void ARGBToRGBA(CK2::CKDWORD count, const void* _argb, void* _rgba) { + const char* argb = reinterpret_cast(_argb); + char* rgba = reinterpret_cast(_rgba); + // copy RGB + VxMath::VxCopyStructure( + count, + rgba, + 4 * sizeof(uint8_t), + 3 * sizeof(uint8_t), + argb + sizeof(uint8_t), + 4 * sizeof(uint8_t) + ); + // copy A + VxMath::VxCopyStructure( + count, + rgba + (3 * sizeof(uint8_t)), + 4 * sizeof(uint8_t), + sizeof(uint8_t), + argb, + 4 * sizeof(uint8_t) + ); + } + + static void PostRead(stbi_uc* data, int x, int y, VxMath::VxImageDescEx* read_image) { + // scale image if need + if (x != read_image->GetWidth() || y != read_image->GetHeight()) { + // alloc + CKBYTE* newdata = new CKBYTE[read_image->GetImageSize()]; + // resize + stbir_resize( + data, x, y, 0, + newdata, static_cast(read_image->GetWidth()), static_cast(read_image->GetHeight()), 0, + STBIR_TYPE_UINT8, 4, STBIR_ALPHA_CHANNEL_NONE, 0, // no alpha channel, mean we treat alpha channel as a normal color factor. + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, + STBIR_FILTER_BOX, STBIR_FILTER_BOX, + STBIR_COLORSPACE_SRGB, nullptr + ); + // copy data + RGBAToARGB(read_image->GetPixelCount(), newdata, read_image->GetImage()); + // free + delete[] newdata; + } else { + // copy data RGBA -> ARGB + RGBAToARGB(read_image->GetPixelCount(), data, read_image->GetImage()); + } + } + static bool StbReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) { + if (u8filename == nullptr || read_image == nullptr) return false; + FILE* fs = EncodingHelper::U8FOpen(u8filename, "rb"); + if (fs == nullptr) return false; + + // read data + int x, y, channels_in_file; + stbi_uc* data = stbi_load_from_file(fs, &x, &y, &channels_in_file, 4); // 4 == RGBA8888 + std::fclose(fs); + if (data == nullptr) return false; + + // scale image if need + PostRead(data, x, y, read_image); + + // clear data + stbi_image_free(data); + return true; + } + static bool StbReadMemory(const void* memory, CKDWORD size, VxMath::VxImageDescEx* read_image) { + // same like ReadFile + if (memory == nullptr || read_image == nullptr) return false; + + // read data + int x, y, channels_in_file; + stbi_uc* data = stbi_load_from_memory( + reinterpret_cast(memory), + static_cast(size), + &x, &y, &channels_in_file, 4 // 4 == RGBA8888 + ); + if (data == nullptr) return false; + + // scale image if need + PostRead(data, x, y, read_image); + + // clear data + stbi_image_free(data); + return true; + } + + struct FileSaveContext { + FileSaveContext(FILE* fs) : + m_Fs(fs), m_Counter(0) {} + FILE* m_Fs; + size_t m_Counter; + }; + static void FileWriteFunction(void* context, void* data, int size) { + FileSaveContext* ctx = reinterpret_cast(context); + if (ctx->m_Fs != nullptr) { + std::fwrite(data, sizeof(char), size, ctx->m_Fs); + } + ctx->m_Counter += size; + } + struct MemorySaveContext { + MemorySaveContext(void* mem) : + m_Mem(mem), m_Counter(0) {} + void* m_Mem; + size_t m_Counter; + }; + static void MemoryWriteFunction(void* context, void* data, int size) { + MemorySaveContext* ctx = reinterpret_cast(context); + if (ctx->m_Mem != nullptr) { + std::memcpy(ctx->m_Mem, data, size); + ctx->m_Mem = reinterpret_cast(ctx->m_Mem) + size; + } + ctx->m_Counter += size; + } + + using SaveOperation = std::function; + static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, SaveOperation oper) { + if (u8filename == nullptr || write_image == nullptr) return false; + FILE* fs = EncodingHelper::U8FOpen(u8filename, "wb"); + if (fs == nullptr) return; + + // allocate buffer and convert data from ARGB to RGBA + VxMath::VxImageDescEx* wi = const_cast(write_image); + CKBYTE* data = new CKBYTE[write_image->GetImageSize()]; + ARGBToRGBA(write_image->GetPixelCount(), wi->GetImage(), data); + + // write data + FileSaveContext* ctx = new FileSaveContext(fs); + int ret = oper( + &FileWriteFunction, ctx, + static_cast(wi->GetWidth()), static_cast(wi->GetHeight()), + 4, data // 4 == RGBA8888 + ); + + // free data + delete ctx; + delete[] data; + std::fclose(fs); + + return ret == 0; + } + static CKDWORD StbSaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, SaveOperation oper) { + if (write_image == nullptr) return 0; + + // allocate buffer and convert data from ARGB to RGBA + VxMath::VxImageDescEx* wi = const_cast(write_image); + CKBYTE* data = new CKBYTE[write_image->GetImageSize()]; + ARGBToRGBA(write_image->GetPixelCount(), wi->GetImage(), data); + + // write data + MemorySaveContext* ctx = new MemorySaveContext(memory); + int ret = oper( + &FileWriteFunction, ctx, + static_cast(wi->GetWidth()), static_cast(wi->GetHeight()), + 4, data // 4 == RGBA8888 + ); + + // free data + CKDWORD expected = static_cast(ctx->m_Counter); + delete ctx; + delete[] data; + + if (ret == 0) return 0; + else return expected; + } + +#pragma region CKBitmapBMPHandler + + CKBitmapBMPHandler::CKBitmapBMPHandler() : + CKBitmapHandler(), c_DefaultProp() { + c_DefaultProp.SetExt("Tga"); + c_DefaultProp.m_ReaderGuid.d1 = 0xBCA97223u; + c_DefaultProp.m_ReaderGuid.d2 = 0x48578BCAu; + } + + CKBitmapBMPHandler::~CKBitmapBMPHandler() {} + + const CKBitmapProperties& CKBitmapBMPHandler::GetBitmapDefaultProperties() { + return c_DefaultProp; + } + + bool CKBitmapBMPHandler::ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) { + StbReadFile(u8filename, read_image); + } + + bool CKBitmapBMPHandler::ReadMemory(const void* memory, CKDWORD size, VxMath::VxImageDescEx* read_image) { + StbReadMemory(memory, size, read_image); + } + + bool CKBitmapBMPHandler::SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) { + return StbSaveFile(u8filename, write_image, + [&codec_param](stbi_write_func* func, void* context, int w, int h, int comp, const void* data) -> int { + return stbi_write_bmp_to_func(func, context, w, h, comp, data); + }); + } + + CKDWORD CKBitmapBMPHandler::SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) { + return StbSaveMemory(memory, write_image, + [&codec_param](stbi_write_func* func, void* context, int w, int h, int comp, const void* data) -> int { + return stbi_write_bmp_to_func(func, context, w, h, comp, data); + }); + } + +#pragma endregion + +#pragma region CKBitmapTGAHandler + + CKBitmapTGAHandler::CKBitmapTGAHandler() : + CKBitmapHandler(), c_DefaultProp() { + c_DefaultProp.SetExt("Tga"); + c_DefaultProp.m_ReaderGuid.d1 = 0x585C7216u; + c_DefaultProp.m_ReaderGuid.d2 = 0x33302657u; + } + + CKBitmapTGAHandler::~CKBitmapTGAHandler() {} + + const CKBitmapProperties& CKBitmapTGAHandler::GetBitmapDefaultProperties() { + return c_DefaultProp; + } + + bool CKBitmapTGAHandler::ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) { + StbReadFile(u8filename, read_image); + } + + bool CKBitmapTGAHandler::ReadMemory(const void* memory, CKDWORD size, VxMath::VxImageDescEx* read_image) { + StbReadMemory(memory, size, read_image); + } + + bool CKBitmapTGAHandler::SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) { + return StbSaveFile(u8filename, write_image, + [&codec_param](stbi_write_func* func, void* context, int w, int h, int comp, const void* data) -> int { + return stbi_write_bmp_to_func(func, context, w, h, comp, data); + }); + } + + CKDWORD CKBitmapTGAHandler::SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) { + return StbSaveMemory(memory, write_image, + [&codec_param](stbi_write_func* func, void* context, int w, int h, int comp, const void* data) -> int { + return stbi_write_bmp_to_func(func, context, w, h, comp, data); + }); + } + +#pragma endregion + + +} diff --git a/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp b/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp new file mode 100644 index 0000000..9307493 --- /dev/null +++ b/LibCmo/CK2/DataHandlers/CKBitmapHandler.hpp @@ -0,0 +1,98 @@ +#pragma once + +#include "../../VTAll.hpp" + +namespace LibCmo::CK2::DataHandlers { + + /** + * The interface about processing bitmap data between raw data and specific data. + * This interface will be capable to converting specific bitmap data into raw ARGB8888 raw data, + * or convert them back. + */ + class CKBitmapHandler { + public: + CKBitmapHandler() {} + virtual ~CKBitmapHandler() {} + LIBCMO_DISABLE_COPY_MOVE(CKBitmapHandler); + + /** + * @brief Returns the current default bitmap options. + * @return Current default bitmap options + */ + virtual const CKBitmapProperties& GetBitmapDefaultProperties() = 0; + + /** + @brief Loads a bitmap file. + @return Returns true if successful. + @param u8filename[in] The file ready to read. + @param read_image[out] The pointer point to existed image desc which describe this image HW. + @see ReadMemory + */ + virtual bool ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) = 0; + /** + @brief Loads a bitmap file stored in memory. + @return Returns true if successful. + @param memory[in] The pointer to memory. + @param size[in] The size of memory. + @param read_image[out] The pointer point to existed image desc which describe this image HW. + @see ReadFile + */ + virtual bool ReadMemory(const void* memory, CKDWORD size, VxMath::VxImageDescEx* read_image) = 0; + /** + @brief Saves a image to a file + @return Returns true if successful. + @param u8filename[in] The file ready to write. + @param write_image[in] The image will be written in file. + @param codec_param[in] The written image format parameter. + @see SaveMemory + */ + virtual bool SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) = 0; + /** + @brief Saves an image into a memory block. + @return Returns the number of written bytes if successful, 0 otherwise. + @param memory[in] The memory where the image will be written. nullptr if you need a dry run to get how many bytes you need to allocate. + @param write_image[in] The image will be written in file. + @param codec_param[in] The written image format parameter. + @remark + + You should call this method first to get how much bytes will be written. + + Then you allocate a proper buffer. + + Finally, call this method with your allocated buffer to get the result. + @see SaveFile + */ + virtual CKDWORD SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) = 0; + + }; + + class CKBitmapBMPHandler : public CKBitmapHandler { + public: + CKBitmapBMPHandler(); + virtual ~CKBitmapBMPHandler(); + LIBCMO_DISABLE_COPY_MOVE(CKBitmapBMPHandler); + + virtual const CKBitmapProperties& GetBitmapDefaultProperties() override; + virtual bool ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) override; + virtual bool ReadMemory(const void* memory, CKDWORD size, VxMath::VxImageDescEx* read_image) override; + virtual bool SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override; + virtual CKDWORD SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override; + + protected: + CKBitmapProperties c_DefaultProp; + }; + + class CKBitmapTGAHandler : public CKBitmapHandler { + public: + CKBitmapTGAHandler(); + virtual ~CKBitmapTGAHandler(); + LIBCMO_DISABLE_COPY_MOVE(CKBitmapTGAHandler); + + virtual const CKBitmapProperties& GetBitmapDefaultProperties() override; + virtual bool ReadFile(CKSTRING u8filename, VxMath::VxImageDescEx* read_image) override; + virtual bool ReadMemory(const void* memory, CKDWORD size, VxMath::VxImageDescEx* read_image) override; + virtual bool SaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override; + virtual CKDWORD SaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, const CKBitmapProperties& codec_param) override; + + protected: + CKBitmapProperties c_DefaultProp; + }; + +} diff --git a/LibCmo/LibCmo.vcxproj b/LibCmo/LibCmo.vcxproj index cc4b588..af85d3c 100644 --- a/LibCmo/LibCmo.vcxproj +++ b/LibCmo/LibCmo.vcxproj @@ -178,6 +178,7 @@ + @@ -191,7 +192,9 @@ + + @@ -201,6 +204,7 @@ + diff --git a/LibCmo/LibCmo.vcxproj.filters b/LibCmo/LibCmo.vcxproj.filters index a2a44ba..f5415e4 100644 --- a/LibCmo/LibCmo.vcxproj.filters +++ b/LibCmo/LibCmo.vcxproj.filters @@ -43,6 +43,12 @@ {a8cd2188-b552-478c-9801-a6286b3d48a0} + + {d66924c0-b040-4f5d-8a8e-87d6d412af38} + + + {cff15b64-e076-47af-9719-74af31d1804d} + @@ -102,6 +108,15 @@ Sources\CK2\MgrImpls + + Sources\CK2\DataHandlers + + + Sources + + + Sources\VxMath + @@ -185,5 +200,8 @@ Headers\VxMath + + Headers\CK2\DataHandlers + \ No newline at end of file diff --git a/LibCmo/VTImage.cpp b/LibCmo/VTImage.cpp new file mode 100644 index 0000000..70148a4 --- /dev/null +++ b/LibCmo/VTImage.cpp @@ -0,0 +1,9 @@ + +// Bad wrapper for stb image library. + +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include "stb_image_resize.h" diff --git a/LibCmo/VxMath/VxMath.cpp b/LibCmo/VxMath/VxMath.cpp new file mode 100644 index 0000000..5ba33d5 --- /dev/null +++ b/LibCmo/VxMath/VxMath.cpp @@ -0,0 +1,109 @@ +#include "VxMath.hpp" + +namespace LibCmo::VxMath { + +#pragma region Structure copying + + void VxFillStructure(CK2::CKDWORD Count, void* Dst, CK2::CKDWORD Stride, CK2::CKDWORD SizeSrc, const void* Src) { + VxCopyStructure(Count, Dst, Stride, SizeSrc, Src, SizeSrc); + } + + void VxCopyStructure(CK2::CKDWORD Count, void* Dst, CK2::CKDWORD OutStride, CK2::CKDWORD SizeSrc, const void* Src, CK2::CKDWORD InStride) { + if (Dst == nullptr || Src == nullptr) return; + + char* cdst = reinterpret_cast(Dst); + const char* csrc = reinterpret_cast(Src); + for (CK2::CKDWORD i = 0; i < Count; ++i) { + std::memcpy(cdst, csrc, SizeSrc); + cdst += OutStride; + csrc += InStride; + } + } + +#pragma endregion + +#pragma region Graphic Utilities + + //CK2::CKDWORD VxGetBitCount(CK2::CKDWORD dwMask) { + // if (dwMask == 0u) return 0; + // dwMask >>= VxGetBitShift(dwMask); + // CK2::CKDWORD count = 0; + // while ((dwMask & 1u) == 0u) { + // dwMask >>= 1u; + // ++count; + // } + // return count; + //} + + //CK2::CKDWORD VxGetBitShift(CK2::CKDWORD dwMask) { + // if (dwMask == 0u) return 0; + // CK2::CKDWORD count = 0; + // while ((dwMask & 1u) != 0u) { + // dwMask >>= 1u; + // ++count; + // } + // return count; + //} + + //CK2::CKDWORD VxScaleFactor(CK2::CKDWORD val, CK2::CKDWORD srcBitCount, CK2::CKDWORD dstBitCount) { + // if (srcBitCount == dstBitCount) return val; + // if (srcBitCount > dstBitCount) { + // return val >> (srcBitCount - dstBitCount); + // } else { + // return val << (dstBitCount - srcBitCount); + // } + //} + + void VxDoAlphaBlit(VxImageDescEx* dst_desc, CK2::CKBYTE AlphaValue) { + if (dst_desc == nullptr) return; + + CK2::CKDWORD* pixels = dst_desc->GetPixels(); + CK2::CKDWORD pixelcount = dst_desc->GetPixelCount(); + + for (CK2::CKDWORD i = 0; i < pixelcount; ++i) { + *pixels = (*pixels) & 0xFF000000 | AlphaValue; + ++pixels; + } + + //CK2::CKDWORD* pixels = dst_desc->GetPixels(); + //CK2::CKDWORD pixelcount = dst_desc->GetPixelCount(), + // alphashift = VxGetBitShift(dst_desc->m_AlphaMask), + // alphacount = VxGetBitCount(dst_desc->m_AlphaMask); + + //CK2::CKDWORD av = VxScaleFactor(AlphaValue, static_cast(sizeof(CK2::CKBYTE) * 8), alphacount) << alphashift; + + //for (CK2::CKDWORD i = 0; i < pixelcount; ++i) { + // *pixels = (*pixels) & (~dst_desc->m_AlphaMask) | av; + // ++pixels; + //} + } + + void VxDoAlphaBlit(VxImageDescEx* dst_desc, CK2::CKBYTE* AlphaValues) { + if (dst_desc == nullptr) return; + + CK2::CKDWORD* pixels = dst_desc->GetPixels(); + CK2::CKDWORD pixelcount = dst_desc->GetPixelCount(); + + for (CK2::CKDWORD i = 0; i < pixelcount; ++i) { + *pixels = (*pixels) & 0xFF000000 | (*AlphaValues); + ++pixels; + ++AlphaValues; + } + + //CK2::CKDWORD* pixels = dst_desc->GetPixels(); + //CK2::CKDWORD pixelcount = dst_desc->GetPixelCount(), + // alphashift = VxGetBitShift(dst_desc->m_AlphaMask), + // alphacount = VxGetBitCount(dst_desc->m_AlphaMask); + + //for (CK2::CKDWORD i = 0; i < pixelcount; ++i) { + // *pixels = (*pixels) & (~dst_desc->m_AlphaMask) | (VxScaleFactor(*AlphaValues, static_cast(sizeof(CK2::CKBYTE) * 8), alphacount) << alphashift); + // ++pixels; + // ++AlphaValues; + //} + } + +#pragma endregion + + + +} diff --git a/LibCmo/VxMath/VxMath.hpp b/LibCmo/VxMath/VxMath.hpp index bc72870..c3fd995 100644 --- a/LibCmo/VxMath/VxMath.hpp +++ b/LibCmo/VxMath/VxMath.hpp @@ -11,7 +11,7 @@ namespace LibCmo::VxMath { * @param Count[in] Number of element to set in the destination buffer * @param Dst[out] Destination buffer * @param Stride[in] Amount in bytes between each element in the destination buffer - * @param SizeSrc[in] Size in bytes (but must be a multiple of 4) of an element int the Src buffer + * @param SizeSrc[in] Size in bytes of an element int the Src buffer * @param Src[in] Source buffer * @remark This function can be used to initialized an array of structure when only some members should be modified. */ @@ -21,29 +21,56 @@ namespace LibCmo::VxMath { * @param Count[in] Number of element to copy in the destination buffer * @param Dst[out] Destination buffer * @param OutStride[in] Amount in bytes between each element in the destination buffer - * @param SizeSrc[in] Size in bytes (but must be a multiple of 4) of an element + * @param SizeSrc[in] Size in bytes of an element * @param Src[in] Source buffer. * @param InStride[in] Amount in bytes between each element in the source buffer * @remark This function can be used to initialized an array of structure when only some members should be modified. */ - void VxCopyStructure(CK2::CKDWORD Count, void* Dst, CK2::CKDWORD OutStride, CK2::CKDWORD SizeSrc, const void* Src,CK2::CKDWORD InStride); + void VxCopyStructure(CK2::CKDWORD Count, void* Dst, CK2::CKDWORD OutStride, CK2::CKDWORD SizeSrc, const void* Src, CK2::CKDWORD InStride); // ========== Graphic Utilities ========== - + // + ///** + // * @brief Copy origin image to dest image. + // * Supporting for size scaling. If the size is matched, just a direct copy. + // * @param dest[out] The dest image. + // * @param origin[in] The origin image. + //*/ + //void VxDoBlit(VxImageDescEx* dst, const VxImageDescEx* origin); + + ///** + // * @brief Counts number of bits to representing a value in dwMask + //*/ + //CK2::CKDWORD VxGetBitCount(CK2::CKDWORD dwMask); + ///** + // * @brief Counts number of bits to shift to acces a non zero value in dwMask. + //*/ + //CK2::CKDWORD VxGetBitShift(CK2::CKDWORD dwMask); + + ///** + // * @brief scale the integer to a new range. + // * @param val The int need to be scale + // * @param srcBitCount The bit count which source integer consumed. + // * @param dstBitCount The bit count which dest integer consumed. + // * @remark This function usually used in image color factor assign with mask. + // * @return The result integer. + //*/ + //CK2::CKDWORD VxScaleFactor(CK2::CKDWORD val, CK2::CKDWORD srcBitCount, CK2::CKDWORD dstBitCount); + /** * @brief Sets the alpha component of an image. * @param dst_desc[in] A pointer to a structure describing the destination image format. * @param AlphaValue[in] A CKBYTE value containing the alpha value to set to the whole image * @remark If the destination image does not have alpha information the function returns immediatly. */ - void VxDoAlphaBlit(const VxImageDescEx* dst_desc, CK2::CKBYTE AlphaValue); + void VxDoAlphaBlit(VxImageDescEx* dst_desc, CK2::CKBYTE AlphaValue); /** * @brief Sets the alpha component of an image. * @param dst_desc[in] A pointer to a structure describing the destination image format. * @param AlphaValues[in] A BYTE array containing the alpha values for each pixel. This array should be allocated to Width*Height bytes. * @remark If the destination image does not have alpha information the function returns immediatly. */ - void VxDoAlphaBlit(const VxImageDescEx* dst_desc, CK2::CKBYTE* AlphaValues); + void VxDoAlphaBlit(VxImageDescEx* dst_desc, CK2::CKBYTE* AlphaValues); } diff --git a/LibCmo/VxMath/VxTypes.hpp b/LibCmo/VxMath/VxTypes.hpp index ffe4565..e452b8c 100644 --- a/LibCmo/VxMath/VxTypes.hpp +++ b/LibCmo/VxMath/VxTypes.hpp @@ -70,57 +70,68 @@ namespace LibCmo::VxMath { }; /** - * @brief Enhanced Image description - * @remark The VxImageDescEx holds basically an VxImageDesc with additionnal support for - * Colormap, Image pointer and is ready for future enhancements. + * VxImageDescEx describe the height, width, + * and etc for image. + * Also it hold a pointer to raw image data. + * The image data must be 32bit format. + * Thus the size of Image must be 4 * Width * Height. */ - struct VxImageDescEx { - VX_PIXELFORMAT Flags; /**< Reserved for special formats (such as compressed ) 0 otherwise */ + class VxImageDescEx { + public: + VxImageDescEx(CK2::CKDWORD height, CK2::CKDWORD width) : + m_Width(width), m_Height(height), + //m_RedMask(0), m_GreenMask(0), m_BlueMask(0), m_AlphaMask(0), + m_Image(nullptr){ + m_Image = new CK2::CKBYTE[GetImageSize()]; + } + ~VxImageDescEx() { + delete[] m_Image; + } + LIBCMO_DISABLE_COPY_MOVE(VxImageDescEx); - CK2::CKDWORD Width; /**< Width in pixel of the image */ - CK2::CKDWORD Height; /**< Height in pixel of the image */ - union { - CK2::CKDWORD BytesPerLine; /**< Pitch (width in bytes) of the image */ - CK2::CKDWORD TotalImageSize; /**< For compressed image (DXT1...) the total size of the image */ - }; - CK2::CKINT BitsPerPixel; /**< Number of bits per pixel */ - union { - CK2::CKDWORD RedMask; /**< Mask for Red component */ - CK2::CKDWORD BumpDuMask; /**< Mask for Bump Du component */ - }; - union { - CK2::CKDWORD GreenMask; /**< Mask for Green component */ - CK2::CKDWORD BumpDvMask; /**< Mask for Bump Dv component */ - }; - union { - CK2::CKDWORD BlueMask; /**< Mask for Blue component */ - CK2::CKDWORD BumpLumMask; /**< Mask for Luminance component */ - - }; - CK2::CKDWORD AlphaMask; /**< Mask for Alpha component */ - - CK2::CKWORD BytesPerColorEntry; /**< ColorMap Stride */ - CK2::CKWORD ColorMapEntries; /**< If other than 0 image is palletized */ - - CK2::CKBYTE* ColorMap; /**< Palette colors */ - CK2::CKBYTE* Image; /**< Image */ - - bool HasAlpha() { - return (AlphaMask == 0 || Flags >= VX_PIXELFORMAT::_DXT1); + CK2::CKDWORD GetImageSize() const { + return static_cast(sizeof(uint32_t) * m_Width * m_Height); + } + CK2::CKBYTE* GetImage() { + return m_Image; } - bool operator==(const VxImageDescEx& rhs) const { - return ( - Height == rhs.Height && Width == rhs.Width && - BitsPerPixel == rhs.BitsPerPixel && BytesPerLine == rhs.BytesPerLine && - RedMask == rhs.RedMask && GreenMask == rhs.GreenMask && BlueMask == rhs.BlueMask && AlphaMask == rhs.AlphaMask && - BytesPerColorEntry == rhs.BytesPerColorEntry && ColorMapEntries == rhs.ColorMapEntries - ); + CK2::CKDWORD GetPixelCount() const { + return static_cast(m_Width * m_Height); } - bool operator!=(const VxImageDescEx& rhs) const { - return !((*this) == rhs); + CK2::CKDWORD* GetPixels() { + return reinterpret_cast(m_Image); } + CK2::CKDWORD GetWidth() const { + return m_Width; + } + CK2::CKDWORD GetHeight() const { + return m_Height; + } + + bool IsHWEqual(const VxImageDescEx& rhs) const { + return (m_Width == rhs.m_Width && m_Height == rhs.m_Height); + } + // bool IsMaskEqual(const VxImageDescEx& rhs) const { + // return ( + // m_RedMask == rhs.m_RedMask && + // m_GreenMask == rhs.m_GreenMask && + // m_BlueMask == rhs.m_BlueMask && + // m_AlphaMask == rhs.m_AlphaMask + // ); + // } + + //public: + // CK2::CKDWORD m_RedMask; + // CK2::CKDWORD m_GreenMask; + // CK2::CKDWORD m_BlueMask; + // CK2::CKDWORD m_AlphaMask; + + protected: + CK2::CKDWORD m_Width; /**< Width in pixel of the image */ + CK2::CKDWORD m_Height; /**< Height in pixel of the image */ + CK2::CKBYTE* m_Image; /**< A pointer point to current processing image */ }; }