init
This commit is contained in:
267
expkg/src/BinaryOPT/ImageReader.cpp
Normal file
267
expkg/src/BinaryOPT/ImageReader.cpp
Normal file
@ -0,0 +1,267 @@
|
||||
//
|
||||
// Created by sfd on 25-8-5.
|
||||
//
|
||||
|
||||
#include "ImageReader.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
|
||||
#include "BinaryWriter.h"
|
||||
#include "lz4.h"
|
||||
|
||||
|
||||
namespace PKG
|
||||
{
|
||||
|
||||
|
||||
#include <vector>
|
||||
|
||||
std::vector<unsigned char> Lz4Decompress(const unsigned char* compressedData,
|
||||
size_t compressedSize,
|
||||
size_t decompressedSize)
|
||||
{
|
||||
// 准备输出缓冲区
|
||||
std::vector<unsigned char> output(decompressedSize);
|
||||
|
||||
// 执行解压缩
|
||||
int result = LZ4_decompress_safe(
|
||||
reinterpret_cast<const char*>(compressedData),
|
||||
reinterpret_cast<char*>(output.data()),
|
||||
static_cast<int>(compressedSize),
|
||||
static_cast<int>(decompressedSize)
|
||||
);
|
||||
|
||||
// 检查解压结果
|
||||
if (result < 0 || static_cast<size_t>(result) != decompressedSize) {
|
||||
throw std::runtime_error("LZ4 decompression failed");
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
TexImage ImageReader::ReadFrom(BinaryReader& reader, const TexImageContainer& container, const TexFormat format)
|
||||
{
|
||||
int mipMapCount = reader.ReadInt32();
|
||||
|
||||
auto aFormat = GetFormatFromTex(container.ImageFormat, format);
|
||||
|
||||
TexImage image{};
|
||||
|
||||
for (int i = 0; i < mipMapCount; i++)
|
||||
{
|
||||
|
||||
TexMipMap mipmap;
|
||||
|
||||
switch (container.ImageContainerVersion)
|
||||
{
|
||||
case ImageContainerVersion::VERSION1:
|
||||
mipmap = ReadMipMapV1(reader); break;
|
||||
case ImageContainerVersion::VERSION2:
|
||||
case ImageContainerVersion::VERSION3:
|
||||
mipmap = ReadMipMapV2AndV3(reader); break;
|
||||
case ImageContainerVersion::VERSION4:
|
||||
mipmap = ReadMipMapV4(reader); break;
|
||||
}
|
||||
|
||||
mipmap.Format = aFormat;
|
||||
if (mipmap.IsZ4Compressed)
|
||||
{
|
||||
mipmap.Data = Lz4Decompress(mipmap.Data.data(), mipmap.Data.size(), mipmap.DecompressedDataCount);
|
||||
mipmap.IsZ4Compressed = false;
|
||||
}
|
||||
|
||||
|
||||
image.Mipmaps.push_back(mipmap);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
TexImageContainer ImageReader::ImageContainerReaderReadFrom(BinaryReader& reader, TexFormat texFormat)
|
||||
{
|
||||
TexImageContainer container;
|
||||
|
||||
container.Magic = reader.ReadNString();
|
||||
|
||||
int imageCount = reader.ReadInt32();
|
||||
|
||||
if (container.Magic == "TEXB0001")
|
||||
{
|
||||
}
|
||||
else if (container.Magic == "TEXB0002")
|
||||
{
|
||||
}
|
||||
else if (container.Magic == "TEXB0003")
|
||||
{
|
||||
container.ImageFormat = (FreeImageFormat)reader.ReadInt32();
|
||||
}
|
||||
else if (container.Magic == "TEXB0004")
|
||||
{
|
||||
auto format = (FreeImageFormat)reader.ReadInt32();
|
||||
|
||||
bool isVideoMp4 = reader.ReadInt32();
|
||||
if (format == FreeImageFormat::FIF_UNKNOWN)
|
||||
{
|
||||
if (isVideoMp4)
|
||||
format = FreeImageFormat::FIF_MP4;
|
||||
}
|
||||
container.ImageFormat = format;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "bad image format" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
int version = std::stoi(container.Magic.substr(4, 4));
|
||||
|
||||
container.ImageContainerVersion = (ImageContainerVersion)version;
|
||||
|
||||
if (container.ImageContainerVersion == ImageContainerVersion::VERSION4 && container.ImageFormat != FreeImageFormat::FIF_MP4)
|
||||
{
|
||||
container.ImageContainerVersion = ImageContainerVersion::VERSION3;
|
||||
}
|
||||
|
||||
for (int i = 0; i < imageCount; i++)
|
||||
{
|
||||
container.Images.push_back(ReadFrom(reader, container, texFormat));
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
TexMipMap ImageReader::ReadMipMapV1(BinaryReader& reader)
|
||||
{
|
||||
TexMipMap mipmap{};
|
||||
mipmap.Width = reader.ReadInt32();
|
||||
mipmap.Height = reader.ReadInt32();
|
||||
mipmap.Data = ReadBytes(reader);
|
||||
|
||||
return mipmap;
|
||||
}
|
||||
|
||||
TexMipMap ImageReader::ReadMipMapV2AndV3(BinaryReader& reader)
|
||||
{
|
||||
TexMipMap mipmap{};
|
||||
|
||||
mipmap.Width = reader.ReadInt32();
|
||||
mipmap.Height = reader.ReadInt32();
|
||||
mipmap.IsZ4Compressed = reader.ReadInt32() == 1;
|
||||
mipmap.DecompressedDataCount = reader.ReadInt32();
|
||||
mipmap.Data = ReadBytes(reader);
|
||||
|
||||
return mipmap;
|
||||
}
|
||||
|
||||
TexMipMap ImageReader::ReadMipMapV4(BinaryReader& reader)
|
||||
{
|
||||
int param1 = reader.ReadInt32();
|
||||
if (param1 != 1)
|
||||
{
|
||||
std::cerr << "ReadMipmapV4 unknow param1: " << param1 << std::endl;
|
||||
}
|
||||
|
||||
int param2 = reader.ReadInt32();
|
||||
if (param2 != 2)
|
||||
{
|
||||
std::cerr << "ReadMipmapV4 unknow param2: " << param1 << std::endl;
|
||||
}
|
||||
|
||||
std::string condition = reader.ReadNString();
|
||||
|
||||
int param3 = reader.ReadInt32();
|
||||
if (param3 != 1)
|
||||
{
|
||||
std::cerr << "ReadMipmapV4 unknow param3: " << param1 << std::endl;
|
||||
}
|
||||
|
||||
TexMipMap mipmap{};
|
||||
mipmap.Width = reader.ReadInt32();
|
||||
mipmap.Height = reader.ReadInt32();
|
||||
mipmap.IsZ4Compressed = reader.ReadInt32() == 1;
|
||||
mipmap.DecompressedDataCount = reader.ReadInt32();
|
||||
mipmap.Data = ReadBytes(reader);
|
||||
|
||||
return mipmap;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ImageReader::ReadBytes(BinaryReader& reader)
|
||||
{
|
||||
int count = reader.ReadInt32();
|
||||
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
reader.ReadData(bytes, count);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
MipmapFormat ImageReader::GetFormatFromTex(FreeImageFormat imageFormat, TexFormat format)
|
||||
{
|
||||
if (imageFormat != FreeImageFormat::FIF_UNKNOWN)
|
||||
{
|
||||
return FreeImageFormatToMipmapFormat(imageFormat);
|
||||
}
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case TexFormat::RGBA8888: return MipmapFormat::RGBA8888;
|
||||
case TexFormat::DXT5: return MipmapFormat::CompressedDXT5;
|
||||
case TexFormat::DXT3: return MipmapFormat::CompressedDXT3;
|
||||
case TexFormat::DXT1: return MipmapFormat::CompressedDXT1;
|
||||
case TexFormat::RG88: return MipmapFormat::RG88;
|
||||
case TexFormat::R8: return MipmapFormat::R8;
|
||||
}
|
||||
|
||||
std::cerr << "unknow format" << std::endl;
|
||||
|
||||
return MipmapFormat::Invalid;
|
||||
}
|
||||
|
||||
MipmapFormat ImageReader::FreeImageFormatToMipmapFormat(FreeImageFormat imageFormat)
|
||||
{
|
||||
switch (imageFormat)
|
||||
{
|
||||
case FreeImageFormat::FIF_BMP: return MipmapFormat::ImageBMP;
|
||||
case FreeImageFormat::FIF_ICO: return MipmapFormat::ImageICO;
|
||||
case FreeImageFormat::FIF_JPEG: return MipmapFormat::ImageJPEG;
|
||||
case FreeImageFormat::FIF_JNG: return MipmapFormat::ImageJNG;
|
||||
case FreeImageFormat::FIF_KOALA: return MipmapFormat::ImageKOALA;
|
||||
case FreeImageFormat::FIF_LBM: return MipmapFormat::ImageLBM;
|
||||
case FreeImageFormat::FIF_MNG: return MipmapFormat::ImageMNG;
|
||||
case FreeImageFormat::FIF_PBM: return MipmapFormat::ImagePBM;
|
||||
case FreeImageFormat::FIF_PBMRAW: return MipmapFormat::ImagePBMRAW;
|
||||
case FreeImageFormat::FIF_PCD: return MipmapFormat::ImagePCD;
|
||||
case FreeImageFormat::FIF_PCX: return MipmapFormat::ImagePCX;
|
||||
case FreeImageFormat::FIF_PGM: return MipmapFormat::ImagePGM;
|
||||
case FreeImageFormat::FIF_PGMRAW: return MipmapFormat::ImagePGMRAW;
|
||||
case FreeImageFormat::FIF_PNG: return MipmapFormat::ImagePNG;
|
||||
case FreeImageFormat::FIF_PPM: return MipmapFormat::ImagePPM;
|
||||
case FreeImageFormat::FIF_PPMRAW: return MipmapFormat::ImagePPMRAW;
|
||||
case FreeImageFormat::FIF_RAS: return MipmapFormat::ImageRAS;
|
||||
case FreeImageFormat::FIF_TARGA: return MipmapFormat::ImageTARGA;
|
||||
case FreeImageFormat::FIF_TIFF: return MipmapFormat::ImageTIFF;
|
||||
case FreeImageFormat::FIF_WBMP: return MipmapFormat::ImageWBMP;
|
||||
case FreeImageFormat::FIF_PSD: return MipmapFormat::ImagePSD;
|
||||
case FreeImageFormat::FIF_CUT: return MipmapFormat::ImageCUT;
|
||||
case FreeImageFormat::FIF_XBM: return MipmapFormat::ImageXBM;
|
||||
case FreeImageFormat::FIF_XPM: return MipmapFormat::ImageXPM;
|
||||
case FreeImageFormat::FIF_DDS: return MipmapFormat::ImageDDS;
|
||||
case FreeImageFormat::FIF_GIF: return MipmapFormat::ImageGIF;
|
||||
case FreeImageFormat::FIF_HDR: return MipmapFormat::ImageHDR;
|
||||
case FreeImageFormat::FIF_FAXG3: return MipmapFormat::ImageFAXG3;
|
||||
case FreeImageFormat::FIF_SGI: return MipmapFormat::ImageSGI;
|
||||
case FreeImageFormat::FIF_EXR: return MipmapFormat::ImageEXR;
|
||||
case FreeImageFormat::FIF_J2K: return MipmapFormat::ImageJ2K;
|
||||
case FreeImageFormat::FIF_JP2: return MipmapFormat::ImageJP2;
|
||||
case FreeImageFormat::FIF_PFM: return MipmapFormat::ImagePFM;
|
||||
case FreeImageFormat::FIF_PICT: return MipmapFormat::ImagePICT;
|
||||
case FreeImageFormat::FIF_RAW: return MipmapFormat::ImageRAW;
|
||||
case FreeImageFormat::FIF_MP4: return MipmapFormat::VideoMp4;
|
||||
}
|
||||
|
||||
std::cerr << "unknown format" << std::endl;
|
||||
return MipmapFormat::Invalid;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user