TexConv/TextureFileCreater.cpp

209 lines
5.8 KiB
C++
Raw Normal View History

2020-03-06 23:29:16 +08:00
#include"TextureFileCreater.h"
2019-12-02 22:10:49 +08:00
#include<hgl/filesystem/FileSystem.h>
namespace
{
/**
*
* @param pathname
* @param filename
* @param fullname
*/
template<typename T>
2020-09-03 21:14:20 +08:00
inline bool SplitFilename(String<T> &pathname,String<T> &filename,const String<T> &fullname)
2019-12-02 22:10:49 +08:00
{
if(fullname.Length()<=1)
return false;
const T spear_char[] = { '/','\\' };
2020-10-19 20:01:00 +08:00
const int pos=fullname.FindRightChars(spear_char);
2019-12-02 22:10:49 +08:00
if(pos==-1)
return(false);
pathname.Strcpy(fullname,pos);
filename.Strcpy(fullname.c_str()+pos+1);
return(true);
}
template<typename T>
2020-09-03 21:14:20 +08:00
inline String<T> ReplaceExtName(const String<T> &old_name,const String<T> &new_extname,const T split_char='.')
2019-12-02 22:10:49 +08:00
{
if(old_name.Length()<=1)
2020-09-03 21:14:20 +08:00
return(String<T>::charOf(split_char)+new_extname);
2019-12-02 22:10:49 +08:00
const int pos=old_name.FindRightChar(split_char);
2019-12-03 15:31:51 +08:00
if(pos!=-1)
return old_name.SubString(0,pos)+new_extname;
2019-12-02 22:10:49 +08:00
else
2020-09-03 21:14:20 +08:00
return old_name+String<T>::charOf(split_char)+new_extname;
2019-12-02 22:10:49 +08:00
}
}//namespace
bool ToILType(ILuint &type,const uint8 bits,const ColorDataType cdt)
{
constexpr ILuint target_type[3][(uint)ColorDataType::END-1]=
{
2019-12-04 20:47:58 +08:00
//UNORM SNORM UINT SINT, USCALE,SSCALE, UFLOAT SFLOAT
/* 8 */{IL_UNSIGNED_BYTE, IL_BYTE, IL_UNSIGNED_BYTE, IL_BYTE, 0,0, 0, 0},
/* 16 */{IL_UNSIGNED_SHORT, IL_SHORT, IL_UNSIGNED_SHORT, IL_SHORT, 0,0, IL_HALF, IL_HALF},
/* 32 */{IL_UNSIGNED_INT, IL_INT, IL_UNSIGNED_INT, IL_INT, 0,0, IL_FLOAT, IL_FLOAT}
2019-12-02 22:10:49 +08:00
};
if(bits<=8 )type=target_type[0][(uint)cdt-1];else
if(bits<=16 )type=target_type[1][(uint)cdt-1];else
if(bits<=32 )type=target_type[2][(uint)cdt-1];else
return(false);
return(type);
}
TextureFileCreater::TextureFileCreater(const PixelFormat *pf)
2019-12-02 22:10:49 +08:00
{
2020-10-25 21:22:18 +08:00
pixel_format=pf;
2019-12-02 22:10:49 +08:00
dos=nullptr;
image=nullptr;
2019-12-02 22:10:49 +08:00
}
2020-10-25 21:22:18 +08:00
2019-12-02 22:10:49 +08:00
TextureFileCreater::~TextureFileCreater()
{
SAFE_CLEAR(dos);
}
2021-12-06 10:47:34 +08:00
const char texture_file_type_name[uint(TextureFileType::RANGE_SIZE)][16]=
{
"Tex1D",
"Tex2D",
"Tex3D",
"TexCubemap",
"Tex1DArray",
"Tex2DArray",
"TexCubemapArray"
};
bool TextureFileCreater::CreateTexFile(const OSString& old_filename, const TextureFileType& type)
2019-12-02 22:10:49 +08:00
{
OSString pn,fn;
SplitFilename<os_char>(pn,fn,old_filename);
2021-12-06 10:47:34 +08:00
if(!RangeCheck<TextureFileType>(type))
{
LOG_ERROR(OS_TEXT("TextureFileCreater::WriteFileHeader(")+old_filename+OS_TEXT(") texture type error that it's ")+OSString::valueOf(int(type)));
return(false);
}
AnsiString file_type_name=texture_file_type_name[uint(type)];
OSString file_ext_name=OS_TEXT(".")+ToOSString(file_type_name);
filename=ReplaceExtName<os_char>(old_filename,file_ext_name);
2019-12-02 22:10:49 +08:00
if(!fos.CreateTrunc(filename))
return(false);
dos=new io::LEDataOutputStream(&fos);
2021-12-06 10:47:34 +08:00
dos->Write(file_type_name.c_str(),file_type_name.Length());
dos->WriteUint8(0x1A);
2020-10-25 21:22:18 +08:00
dos->WriteUint8(3); //版本
2021-12-06 10:47:34 +08:00
return(true);
}
bool TextureFileCreater::WriteSize1D(const uint mip_level,const uint length)
{
if(!dos->WriteUint8(mip_level))return(false); //mipmaps级数
if(!dos->WriteUint32(length))return(false);
return(true);
}
2021-12-06 10:47:34 +08:00
bool TextureFileCreater::WriteSize2D(const uint mip_level, const uint width,const uint height)
{
if(!dos->WriteUint8(mip_level))return(false); //mipmaps级数
if(!dos->WriteUint32(width))return(false);
if(!dos->WriteUint32(height))return(false);
return(true);
}
bool TextureFileCreater::WritePixelFormat()
{
if (pixel_format->format > ColorFormat::COMPRESS)
2020-10-25 21:22:18 +08:00
{
if(!dos->WriteUint8(0))return(false);
if(!dos->WriteUint16(uint(pixel_format->format)-uint(ColorFormat::BC1RGB)))return(false);
2020-10-25 21:22:18 +08:00
}
else
{
if(!dos->WriteUint8(pixel_format->channels))return(false); //颜色通道数
if(!dos->WriteUint8((uint8*)pixel_format->color, 4))return(false); //颜色标记
if(!dos->WriteUint8(pixel_format->bits, 4))return(false); //颜色位数
if(!dos->WriteUint8((uint8)pixel_format->type))return(false); //数据类型
2020-10-25 21:22:18 +08:00
}
return(true);
}
2020-10-25 21:22:18 +08:00
uint32 TextureFileCreater::Write(void *data,const uint total_bytes)
{
2020-10-25 21:22:18 +08:00
const uint64 space=0;
if(dos->Write(data,total_bytes)!=total_bytes)
return(0);
if(total_bytes<8)
{
2020-10-25 21:22:18 +08:00
if(dos->Write(&space,8-total_bytes)!=8-total_bytes)
return(0);
return 8;
}
2019-12-02 22:10:49 +08:00
2020-10-25 21:22:18 +08:00
return total_bytes;
2019-12-02 22:10:49 +08:00
}
void TextureFileCreater::Close()
{
SAFE_CLEAR(dos);
fos.Close();
}
void TextureFileCreater::Delete()
{
Close();
filesystem::FileDelete(filename);
}
TextureFileCreater *CreateTextureFileCreaterR(const PixelFormat *);
TextureFileCreater *CreateTextureFileCreaterRG(const PixelFormat *);
TextureFileCreater *CreateTextureFileCreaterRGB(const PixelFormat *);
TextureFileCreater *CreateTextureFileCreaterRGBA(const PixelFormat *);
TextureFileCreater *CreateTextureFileCreaterCompress(const PixelFormat *);
TextureFileCreater *CreateTFC(const PixelFormat *fmt,const int channels)
{
if(!fmt)return(nullptr);
if(channels<1||channels>4)return(nullptr);
using CTFC_FUNC=TextureFileCreater *(*)(const PixelFormat *);
static CTFC_FUNC CreateTFC[4]=
{
CreateTextureFileCreaterR,
CreateTextureFileCreaterRG,
CreateTextureFileCreaterRGB,
CreateTextureFileCreaterRGBA
};
if(fmt->format<ColorFormat::COMPRESS)
return CreateTFC[channels-1](fmt);
else
return CreateTextureFileCreaterCompress(fmt);
2019-12-02 22:10:49 +08:00
}