almost finish CKBitmapData read
This commit is contained in:
parent
e2647ed39b
commit
9c1fcd172d
|
@ -10,14 +10,117 @@ namespace LibCmo::CK2 {
|
||||||
#pragma region Assist RW Functions
|
#pragma region Assist RW Functions
|
||||||
|
|
||||||
bool CKBitmapData::ReadSpecificFormatBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot) {
|
bool CKBitmapData::ReadSpecificFormatBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot) {
|
||||||
|
// read transparent prop
|
||||||
|
CKDWORD transprop;
|
||||||
|
chk->ReadStruct(transprop);
|
||||||
|
|
||||||
|
// get ext and guid to find correct guid
|
||||||
|
CKCHAR filerawext[4];
|
||||||
|
CKGUID fileguid;
|
||||||
|
chk->ReadNoSizeBuffer(CKSizeof(filerawext), filerawext);
|
||||||
|
chk->ReadStruct(fileguid);
|
||||||
|
CKFileExtension fileext(filerawext);
|
||||||
|
auto reader = DataHandlers::CKBitmapHandler::GetBitmapHandlerWrapper(fileext, fileguid);
|
||||||
|
if (reader == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read image size
|
||||||
|
CKDWORD imgbytesize;
|
||||||
|
chk->ReadStruct(imgbytesize);
|
||||||
|
if (imgbytesize != 0) {
|
||||||
|
// get image data ptr
|
||||||
|
const void* imgdata = nullptr;
|
||||||
|
if (!chk->ReadDryBuffer(&imgdata, imgbytesize)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse image
|
||||||
|
VxMath::VxImageDescEx cache;
|
||||||
|
if (!reader->ReadMemory(imgdata, imgbytesize, &cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// post proc image (copy to slot)
|
||||||
|
VxMath::VxDoBlit(&cache, slot);
|
||||||
|
|
||||||
|
// proc image alpha
|
||||||
|
if (transprop == 2) {
|
||||||
|
CKDWORD alphacount;
|
||||||
|
chk->ReadStruct(alphacount);
|
||||||
|
if (alphacount == 1) {
|
||||||
|
CKDWORD globalalpha;
|
||||||
|
chk->ReadStruct(globalalpha);
|
||||||
|
VxMath::VxDoAlphaBlit(slot, static_cast<CKBYTE>(globalalpha));
|
||||||
|
} else {
|
||||||
|
CKStateChunk::TBuffer alphabuf;
|
||||||
|
CKDWORD buflen;
|
||||||
|
chk->ReadBufferWrapper(&alphabuf, &buflen);
|
||||||
|
VxMath::VxDoAlphaBlit(slot, reinterpret_cast<CKBYTE*>(alphabuf.get()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CKBitmapData::ReadRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot) {
|
bool CKBitmapData::ReadRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot) {
|
||||||
|
CKDWORD bytePerPixel, width, height, redMask, greenMask, blueMask, alphaMask;
|
||||||
|
chk->ReadStruct(bytePerPixel); // not used
|
||||||
|
if (bytePerPixel == 0) return false;
|
||||||
|
|
||||||
|
chk->ReadStruct(width);
|
||||||
|
chk->ReadStruct(height);
|
||||||
|
chk->ReadStruct(alphaMask);
|
||||||
|
chk->ReadStruct(redMask);
|
||||||
|
chk->ReadStruct(greenMask);
|
||||||
|
chk->ReadStruct(blueMask);
|
||||||
|
|
||||||
|
// read RGBA buffer
|
||||||
|
CKStateChunk::TBuffer redBuffer, greenBuffer, blueBuffer, alphaBuffer;
|
||||||
|
CKDWORD bufsize;
|
||||||
|
CKDWORD bufopt;
|
||||||
|
chk->ReadStruct(bufopt);
|
||||||
|
bufopt &= 0xFu;
|
||||||
|
if (bufopt != 0) {
|
||||||
|
// MARK: not supported CCompressionTools::jpegDecode()
|
||||||
|
// There are some shitty jpeg decode function.
|
||||||
|
// I do not want to touch them because all of my work do not related to them
|
||||||
|
// so return false simply
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
chk->ReadBufferWrapper(&redBuffer, &bufsize);
|
||||||
|
chk->ReadBufferWrapper(&greenBuffer, &bufsize);
|
||||||
|
chk->ReadBufferWrapper(&blueBuffer, &bufsize);
|
||||||
|
}
|
||||||
|
chk->ReadBufferWrapper(&alphaBuffer, &bufsize);
|
||||||
|
|
||||||
|
// write into file
|
||||||
|
if (redBuffer != nullptr && greenBuffer != nullptr && blueBuffer != nullptr) {
|
||||||
|
// create image
|
||||||
|
slot->CreateImage(width, height);
|
||||||
|
// get essential data
|
||||||
|
CKDWORD pixelcount = slot->GetPixelCount();
|
||||||
|
CKBYTE* dst = slot->GetMutableImage(),
|
||||||
|
* redSrc = reinterpret_cast<CKBYTE*>(redBuffer.get()),
|
||||||
|
* greenSrc = reinterpret_cast<CKBYTE*>(greenBuffer.get()),
|
||||||
|
* blueSrc = reinterpret_cast<CKBYTE*>(blueBuffer.get()),
|
||||||
|
* alphaSrc = reinterpret_cast<CKBYTE*>(alphaBuffer.get());
|
||||||
|
for (CKDWORD p = 0; p < pixelcount; ++p) {
|
||||||
|
// if no alpha data, set to 0xFF
|
||||||
|
*(dst++) = (alphaBuffer != nullptr ? (*(alphaSrc++)) : 0xFFu);
|
||||||
|
*(dst++) = *(redSrc++);
|
||||||
|
*(dst++) = *(greenSrc++);
|
||||||
|
*(dst++) = *(blueSrc++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKBitmapData::ReadOldRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot) {
|
bool CKBitmapData::ReadOldRawBitmap(CKStateChunk* chk, VxMath::VxImageDescEx* slot) {
|
||||||
|
// MARK: not supported because all of my work do not involve this function.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +140,9 @@ namespace LibCmo::CK2 {
|
||||||
XContainer::XBitArray notReadSlot;
|
XContainer::XBitArray notReadSlot;
|
||||||
|
|
||||||
// check 3 types enbedded image
|
// check 3 types enbedded image
|
||||||
|
// MARK: i think there is a potential vulnerable issue.
|
||||||
|
// if a slot failed, all following slot will read data from a wrong position.
|
||||||
|
// thus the program will crash or allocated massive garbage data.
|
||||||
if (chunk->SeekIdentifierDword(identifiers.m_SpecificFormat)) {
|
if (chunk->SeekIdentifierDword(identifiers.m_SpecificFormat)) {
|
||||||
// specific format
|
// specific format
|
||||||
CKDWORD slotcount, width, height, bpp;
|
CKDWORD slotcount, width, height, bpp;
|
||||||
|
@ -48,6 +154,10 @@ namespace LibCmo::CK2 {
|
||||||
SetSlotCount(slotcount);
|
SetSlotCount(slotcount);
|
||||||
notReadSlot.resize(slotcount, false);
|
notReadSlot.resize(slotcount, false);
|
||||||
|
|
||||||
|
// the height and width is written outside of specific format
|
||||||
|
// so we create image first for it.
|
||||||
|
// and let reader to read data.
|
||||||
|
// and free image if is is failed.
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
CreateImage(width, height, i);
|
CreateImage(width, height, i);
|
||||||
|
@ -67,11 +177,17 @@ namespace LibCmo::CK2 {
|
||||||
SetSlotCount(slotcount);
|
SetSlotCount(slotcount);
|
||||||
notReadSlot.resize(slotcount, false);
|
notReadSlot.resize(slotcount, false);
|
||||||
|
|
||||||
|
// the height and width is read by raw data function self.
|
||||||
|
// so we pass a cache variable to reader and do some modification
|
||||||
|
// if it is success.
|
||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
if (ReadRawBitmap(chunk, GetImageDesc(i))) {
|
VxMath::VxImageDescEx rawcache;
|
||||||
|
if (ReadRawBitmap(chunk, &rawcache)) {
|
||||||
notReadSlot[i] = true;
|
notReadSlot[i] = true;
|
||||||
} else {
|
|
||||||
ReleaseImage(i);
|
// do upside down blit
|
||||||
|
CreateImage(rawcache.GetWidth(), rawcache.GetHeight(), i);
|
||||||
|
VxMath::VxDoBlitUpsideDown(&rawcache, GetImageDesc(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +199,7 @@ namespace LibCmo::CK2 {
|
||||||
SetSlotCount(slotcount);
|
SetSlotCount(slotcount);
|
||||||
notReadSlot.resize(slotcount, false);
|
notReadSlot.resize(slotcount, false);
|
||||||
|
|
||||||
|
// MARK: a rough implement because we do not support this identifier
|
||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
if (ReadOldRawBitmap(chunk, GetImageDesc(i))) {
|
if (ReadOldRawBitmap(chunk, GetImageDesc(i))) {
|
||||||
notReadSlot[i] = true;
|
notReadSlot[i] = true;
|
||||||
|
@ -105,18 +222,24 @@ namespace LibCmo::CK2 {
|
||||||
for (CKDWORD i = 0; i < slotcount; ++i) {
|
for (CKDWORD i = 0; i < slotcount; ++i) {
|
||||||
std::string filename;
|
std::string filename;
|
||||||
chunk->ReadString(filename);
|
chunk->ReadString(filename);
|
||||||
if (filename.empty()) return;
|
if (filename.empty()) continue;
|
||||||
|
|
||||||
// set
|
|
||||||
SetSlotFileName(i, filename.c_str());
|
|
||||||
|
|
||||||
// if not loaded, and suc in resolve file path.
|
|
||||||
// load it
|
|
||||||
bool isNotLoaded = i >= notReadSlot.size() || notReadSlot[i];
|
bool isNotLoaded = i >= notReadSlot.size() || notReadSlot[i];
|
||||||
if (isNotLoaded && m_Context->GetPathManager()->ResolveFileName(filename)) {
|
if (isNotLoaded) {
|
||||||
LoadImage(filename.c_str(), i);
|
// if this image is not loaded.
|
||||||
|
// try resolve its file name and load it.
|
||||||
|
// and set resolved filename for it.
|
||||||
|
if (m_Context->GetPathManager()->ResolveFileName(filename)) {
|
||||||
|
if (LoadImage(filename.c_str(), i)) {
|
||||||
|
SetSlotFileName(i, filename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise, set filename simply
|
||||||
|
SetSlotFileName(i, filename.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// movie info
|
// movie info
|
||||||
|
@ -124,6 +247,7 @@ namespace LibCmo::CK2 {
|
||||||
// MARK: movie is not implemented here.
|
// MARK: movie is not implemented here.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKBitmapData::DumpToChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataWriteIdentifiers& identifiers) {
|
bool CKBitmapData::DumpToChunk(CKStateChunk* chunk, CKFileVisitor* file, const CKBitmapDataWriteIdentifiers& identifiers) {
|
||||||
|
@ -176,29 +300,45 @@ namespace LibCmo::CK2 {
|
||||||
// get extension of file. then get corresponding reader
|
// get extension of file. then get corresponding reader
|
||||||
std::string ext(filename);
|
std::string ext(filename);
|
||||||
m_Context->GetPathManager()->GetExtension(ext);
|
m_Context->GetPathManager()->GetExtension(ext);
|
||||||
std::unique_ptr<DataHandlers::CKBitmapHandler, DataHandlers::CKBitmapHandlerDeleter> reader(
|
auto reader = DataHandlers::CKBitmapHandler::GetBitmapHandlerWrapper(CKFileExtension(ext.c_str()), CKGUID());
|
||||||
DataHandlers::CKBitmapHandler::GetBitmapHandler(CKFileExtension(ext.c_str()), CKGUID())
|
|
||||||
);
|
|
||||||
if (reader == nullptr) return false;
|
if (reader == nullptr) return false;
|
||||||
|
|
||||||
// get desc
|
// get desc and read data
|
||||||
VxMath::VxImageDescEx* desc = GetImageDesc(slot);
|
if (!reader->ReadFile(filename, GetImageDesc(slot))) {
|
||||||
if (desc == nullptr) return false;
|
|
||||||
|
|
||||||
// read data
|
|
||||||
if (!reader->ReadFile(filename, desc)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// free reader
|
|
||||||
reader.reset();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKBitmapData::SaveImage(CKSTRING filename, CKDWORD slot) {
|
bool CKBitmapData::SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt) {
|
||||||
if (filename == nullptr) return false;
|
if (filename == nullptr) return false;
|
||||||
if (slot >= m_Slots.size()) return false;
|
if (slot >= m_Slots.size()) return false;
|
||||||
|
|
||||||
|
// prepare save format
|
||||||
|
CKBitmapProperties savefmt;
|
||||||
|
if (isForceThisFmt) {
|
||||||
|
savefmt = this->m_SaveProperties;
|
||||||
|
} else {
|
||||||
|
std::string ext(filename);
|
||||||
|
m_Context->GetPathManager()->GetExtension(ext);
|
||||||
|
if (ext.empty()) {
|
||||||
|
// fallback to this fmt
|
||||||
|
savefmt = this->m_SaveProperties;
|
||||||
|
} else {
|
||||||
|
savefmt.m_Ext.SetExt(ext.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get reader by format
|
||||||
|
auto reader = DataHandlers::CKBitmapHandler::GetBitmapHandlerWrapper(savefmt.m_Ext, savefmt.m_ReaderGuid);
|
||||||
|
if (reader == nullptr) return false;
|
||||||
|
|
||||||
|
// save file
|
||||||
|
if (!reader->SaveFile(filename, GetImageDesc(slot), savefmt)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +380,11 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKBitmapData::SetTransparent(bool Transparency) {
|
void CKBitmapData::SetTransparent(bool Transparency) {
|
||||||
|
if (Transparency) {
|
||||||
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
|
EnumsHelper::Add(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
|
||||||
|
} else {
|
||||||
|
EnumsHelper::Rm(m_BitmapFlags, CK_BITMAPDATA_FLAGS::CKBITMAPDATA_TRANSPARENT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKBitmapData::IsTransparent() {
|
bool CKBitmapData::IsTransparent() {
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
void CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot);
|
void CreateImage(CKDWORD Width, CKDWORD Height, CKDWORD Slot);
|
||||||
bool LoadImage(CKSTRING filename, CKDWORD slot);
|
bool LoadImage(CKSTRING filename, CKDWORD slot);
|
||||||
bool SaveImage(CKSTRING filename, CKDWORD slot);
|
bool SaveImage(CKSTRING filename, CKDWORD slot, bool isForceThisFmt = false);
|
||||||
VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot);
|
VxMath::VxImageDescEx* GetImageDesc(CKDWORD slot);
|
||||||
void ReleaseImage(CKDWORD slot);
|
void ReleaseImage(CKDWORD slot);
|
||||||
|
|
||||||
|
|
|
@ -161,11 +161,6 @@ namespace LibCmo::CK2 {
|
||||||
this->m_DataVersion = version;
|
this->m_DataVersion = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKStateChunk::DeleteBuffer(const void* buf) {
|
|
||||||
if (buf == nullptr) return;
|
|
||||||
delete[] reinterpret_cast<const char*>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CKStateChunk::Skip(CKDWORD DwordCount) {
|
bool CKStateChunk::Skip(CKDWORD DwordCount) {
|
||||||
bool result;
|
bool result;
|
||||||
switch (this->m_Parser.m_Status) {
|
switch (this->m_Parser.m_Status) {
|
||||||
|
@ -190,6 +185,17 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void* CKStateChunk::GetCurrentPointer() {
|
||||||
|
switch (this->m_Parser.m_Status) {
|
||||||
|
case CKStateChunkStatus::READ:
|
||||||
|
case CKStateChunkStatus::WRITE:
|
||||||
|
return this->m_pData + this->m_Parser.m_CurrentPos;
|
||||||
|
case CKStateChunkStatus::IDLE:
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CKDWORD CKStateChunk::GetCeilDwordSize(size_t char_size) {
|
CKDWORD CKStateChunk::GetCeilDwordSize(size_t char_size) {
|
||||||
return static_cast<CKDWORD>((char_size + 3) >> 2);
|
return static_cast<CKDWORD>((char_size + 3) >> 2);
|
||||||
}
|
}
|
||||||
|
@ -560,11 +566,14 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
bool CKStateChunk::ReadByteData(void* data_ptr, CKDWORD size_in_byte) {
|
bool CKStateChunk::ReadByteData(void* data_ptr, CKDWORD size_in_byte) {
|
||||||
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
||||||
if (data_ptr == nullptr) return false;
|
|
||||||
|
|
||||||
CKDWORD size_in_dword = this->GetCeilDwordSize(size_in_byte);
|
CKDWORD size_in_dword = this->GetCeilDwordSize(size_in_byte);
|
||||||
if (this->EnsureReadSpace(size_in_dword)) {
|
if (this->EnsureReadSpace(size_in_dword)) {
|
||||||
|
// only copy when data_ptr is not nullptr
|
||||||
|
// do dry run if there are no dest to copy for.
|
||||||
|
if (data_ptr != nullptr) {
|
||||||
std::memcpy(data_ptr, this->m_pData + this->m_Parser.m_CurrentPos, size_in_byte);
|
std::memcpy(data_ptr, this->m_pData + this->m_Parser.m_CurrentPos, size_in_byte);
|
||||||
|
}
|
||||||
this->m_Parser.m_CurrentPos += size_in_dword;
|
this->m_Parser.m_CurrentPos += size_in_dword;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -760,6 +769,12 @@ namespace LibCmo::CK2 {
|
||||||
}
|
}
|
||||||
*len_in_byte = bufByteSize;
|
*len_in_byte = bufByteSize;
|
||||||
|
|
||||||
|
// special treat for zero length buffer
|
||||||
|
if (bufByteSize == 0) {
|
||||||
|
*buf = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// create buffer
|
// create buffer
|
||||||
*buf = new char[bufByteSize];
|
*buf = new char[bufByteSize];
|
||||||
|
|
||||||
|
@ -774,6 +789,38 @@ namespace LibCmo::CK2 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadBufferWrapper(TBuffer* uptr, CKDWORD* len_in_byte) {
|
||||||
|
if (uptr == nullptr || len_in_byte == nullptr) return false;
|
||||||
|
|
||||||
|
void* bufcache = nullptr;
|
||||||
|
bool ret = ReadBuffer(&bufcache, len_in_byte);
|
||||||
|
uptr->reset(bufcache);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadDryBuffer(const void** buf, CKDWORD ordered_size) {
|
||||||
|
if (buf == nullptr) return false;
|
||||||
|
|
||||||
|
// backup current pos
|
||||||
|
*buf = GetCurrentPointer();
|
||||||
|
if (!this->ReadByteData(nullptr, ordered_size)) {
|
||||||
|
*buf = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::BufferDeleter::operator()(void* buf) {
|
||||||
|
if (buf == nullptr) return;
|
||||||
|
delete[] reinterpret_cast<const char*>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::DeleteBuffer(const void* buf) {
|
||||||
|
if (buf == nullptr) return;
|
||||||
|
delete[] reinterpret_cast<const char*>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/* ========== Sequence Functions ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
bool CKStateChunk::ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls) {
|
bool CKStateChunk::ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls) {
|
||||||
|
@ -957,5 +1004,4 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../VTAll.hpp"
|
#include "../VTAll.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
|
@ -80,15 +82,11 @@ namespace LibCmo::CK2 {
|
||||||
CKDWORD GetDataSize(void);
|
CKDWORD GetDataSize(void);
|
||||||
CK_STATECHUNK_DATAVERSION GetDataVersion();
|
CK_STATECHUNK_DATAVERSION GetDataVersion();
|
||||||
void SetDataVersion(CK_STATECHUNK_DATAVERSION version);
|
void SetDataVersion(CK_STATECHUNK_DATAVERSION version);
|
||||||
/**
|
|
||||||
* @brief Free the buffer allocated by CKStateChunk reading functions.
|
|
||||||
* @param buf The buffer need to be free.
|
|
||||||
*/
|
|
||||||
void DeleteBuffer(const void* buf);
|
|
||||||
bool Skip(CKDWORD DwordCount);
|
bool Skip(CKDWORD DwordCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CKDWORD GetCeilDwordSize(size_t char_size);
|
CKDWORD GetCeilDwordSize(size_t char_size);
|
||||||
|
void* GetCurrentPointer();
|
||||||
bool ResizeBuffer(CKDWORD new_dwsize);
|
bool ResizeBuffer(CKDWORD new_dwsize);
|
||||||
bool EnsureWriteSpace(CKDWORD dwsize);
|
bool EnsureWriteSpace(CKDWORD dwsize);
|
||||||
bool EnsureReadSpace(CKDWORD dword_required);
|
bool EnsureReadSpace(CKDWORD dword_required);
|
||||||
|
@ -200,6 +198,19 @@ namespace LibCmo::CK2 {
|
||||||
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer
|
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The deleter for std::unique_ptr of CKStateChunk created buffer.
|
||||||
|
*/
|
||||||
|
struct BufferDeleter {
|
||||||
|
BufferDeleter() = default;
|
||||||
|
BufferDeleter(const BufferDeleter&) noexcept {}
|
||||||
|
void operator()(void* buf);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @brief The type of CKStateChunk auto free buffer.
|
||||||
|
*/
|
||||||
|
using TBuffer = std::unique_ptr<void, BufferDeleter>;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Read a buffer with unknow size (order user specific it).
|
/// Read a buffer with unknow size (order user specific it).
|
||||||
/// <para>ReadAndFillBuffer(int, void*), ReadAndFillBuffer_LEndian(int, void*), ReadAndFillBuffer_LEndian16(int, void*) are redirected to this.</para>
|
/// <para>ReadAndFillBuffer(int, void*), ReadAndFillBuffer_LEndian(int, void*), ReadAndFillBuffer_LEndian16(int, void*) are redirected to this.</para>
|
||||||
|
@ -219,6 +230,29 @@ namespace LibCmo::CK2 {
|
||||||
/// <param name="len">a pointer to the variable receiving the length of gotten buffer.</param>
|
/// <param name="len">a pointer to the variable receiving the length of gotten buffer.</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool ReadBuffer(void** buf, CKDWORD* len_in_byte);
|
bool ReadBuffer(void** buf, CKDWORD* len_in_byte);
|
||||||
|
/**
|
||||||
|
* @brief A auto free wrapper for ReadBuffer
|
||||||
|
* @param uptr The pointer to unique_ptr receiving data.
|
||||||
|
* @param len_in_byte The size of gotten buffer.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool ReadBufferWrapper(TBuffer* uptr, CKDWORD* len_in_byte);
|
||||||
|
/**
|
||||||
|
* @brief Perform a dry buffer reading.
|
||||||
|
* This function will only make sure there is enough space for your reading.
|
||||||
|
* And return the start memory address to you.
|
||||||
|
* And will not create any extra memory like ReadBuffer.
|
||||||
|
* @param buf[out] a pointer to the pointer receiving data start address.
|
||||||
|
* @param ordered_sizepin] your expected length of this buffer.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool ReadDryBuffer(const void** buf, CKDWORD ordered_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free the buffer allocated by CKStateChunk reading functions.
|
||||||
|
* @param buf The buffer need to be free.
|
||||||
|
*/
|
||||||
|
void DeleteBuffer(const void* buf);
|
||||||
|
|
||||||
/* ========== Sequence Functions ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,7 @@ namespace LibCmo::CK2::DataHandlers {
|
||||||
using SaveOperation = std::function<int(stbi_write_func*, void*, int, int, int, const void*)>;
|
using SaveOperation = std::function<int(stbi_write_func*, void*, int, int, int, const void*)>;
|
||||||
static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, SaveOperation oper) {
|
static bool StbSaveFile(CKSTRING u8filename, const VxMath::VxImageDescEx* write_image, SaveOperation oper) {
|
||||||
if (u8filename == nullptr || write_image == nullptr) return false;
|
if (u8filename == nullptr || write_image == nullptr) return false;
|
||||||
|
if (!write_image->IsValid()) return false;
|
||||||
FILE* fs = EncodingHelper::U8FOpen(u8filename, "wb");
|
FILE* fs = EncodingHelper::U8FOpen(u8filename, "wb");
|
||||||
if (fs == nullptr) return false;
|
if (fs == nullptr) return false;
|
||||||
|
|
||||||
|
@ -153,6 +154,7 @@ namespace LibCmo::CK2::DataHandlers {
|
||||||
}
|
}
|
||||||
static CKDWORD StbSaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, SaveOperation oper) {
|
static CKDWORD StbSaveMemory(void* memory, const VxMath::VxImageDescEx* write_image, SaveOperation oper) {
|
||||||
if (write_image == nullptr) return 0;
|
if (write_image == nullptr) return 0;
|
||||||
|
if (!write_image->IsValid()) return 0;
|
||||||
|
|
||||||
// allocate buffer and convert data from ARGB to RGBA
|
// allocate buffer and convert data from ARGB to RGBA
|
||||||
CKBYTE* data = new CKBYTE[write_image->GetImageSize()];
|
CKBYTE* data = new CKBYTE[write_image->GetImageSize()];
|
||||||
|
@ -279,6 +281,14 @@ namespace LibCmo::CK2::DataHandlers {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CKBitmapHandler, CKBitmapHandlerDeleter> CKBitmapHandler::GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid) {
|
||||||
|
return std::unique_ptr<CKBitmapHandler, std::function<void(CKBitmapHandler*)>>(GetBitmapHandler(ext, guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKBitmapHandlerDeleter::operator()(CKBitmapHandler* handler) {
|
||||||
|
CKBitmapHandler::ReleaseBitmapHandler(handler);
|
||||||
|
}
|
||||||
|
|
||||||
void CKBitmapHandler::ReleaseBitmapHandler(CKBitmapHandler* handler) {
|
void CKBitmapHandler::ReleaseBitmapHandler(CKBitmapHandler* handler) {
|
||||||
if (handler != nullptr) delete handler;
|
if (handler != nullptr) delete handler;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../VTAll.hpp"
|
#include "../../VTAll.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace LibCmo::CK2::DataHandlers {
|
namespace LibCmo::CK2::DataHandlers {
|
||||||
|
|
||||||
|
class CKBitmapHandler;
|
||||||
|
/**
|
||||||
|
* @brief An assist class which can applied to std::unique_ptr as a custom deleter
|
||||||
|
* to make sure the CKBitmapHandler* can be free correctly.
|
||||||
|
*/
|
||||||
|
struct CKBitmapHandlerDeleter {
|
||||||
|
CKBitmapHandlerDeleter() = default;
|
||||||
|
CKBitmapHandlerDeleter(const CKBitmapHandlerDeleter&) noexcept {}
|
||||||
|
void operator()(CKBitmapHandler* handler);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface about processing bitmap data between raw data and specific data.
|
* 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,
|
* This interface will be capable to converting specific bitmap data into raw ARGB8888 raw data,
|
||||||
|
@ -25,6 +38,10 @@ namespace LibCmo::CK2::DataHandlers {
|
||||||
* @return The pointer to CKBitmapHandler. nullptr if fail to find.
|
* @return The pointer to CKBitmapHandler. nullptr if fail to find.
|
||||||
*/
|
*/
|
||||||
static CKBitmapHandler* GetBitmapHandler(const CKFileExtension& ext, const CKGUID& guid);
|
static CKBitmapHandler* GetBitmapHandler(const CKFileExtension& ext, const CKGUID& guid);
|
||||||
|
/**
|
||||||
|
* @brief A auto free wrapper for GetBitmapHandler
|
||||||
|
*/
|
||||||
|
static std::unique_ptr<CKBitmapHandler, CKBitmapHandlerDeleter> GetBitmapHandlerWrapper(const CKFileExtension& ext, const CKGUID& guid);
|
||||||
/**
|
/**
|
||||||
* @brief General CKBitmapHandler disposer
|
* @brief General CKBitmapHandler disposer
|
||||||
* @param handler[in] The handler need to be free.
|
* @param handler[in] The handler need to be free.
|
||||||
|
@ -73,18 +90,6 @@ namespace LibCmo::CK2::DataHandlers {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief An assist class which can applied to std::unique_ptr as a custom deleter
|
|
||||||
* to make sure the CKBitmapHandler* can be free correctly.
|
|
||||||
*/
|
|
||||||
struct CKBitmapHandlerDeleter {
|
|
||||||
CKBitmapHandlerDeleter() = default;
|
|
||||||
CKBitmapHandlerDeleter(const CKBitmapHandlerDeleter&) noexcept {}
|
|
||||||
void operator()(CKBitmapHandler* handler) {
|
|
||||||
CKBitmapHandler::ReleaseBitmapHandler(handler);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CKBitmapBMPHandler : public CKBitmapHandler {
|
class CKBitmapBMPHandler : public CKBitmapHandler {
|
||||||
public:
|
public:
|
||||||
CKBitmapBMPHandler();
|
CKBitmapBMPHandler();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user