From 974638d58ea4eb24a3697e38cb0960ce2e18b36d Mon Sep 17 00:00:00 2001 From: hyzboy Date: Mon, 2 Dec 2019 22:10:49 +0800 Subject: [PATCH] finished code,but no debug and test --- CMakeLists.txt | 14 +++- ConvertImage.cpp | 71 ++++++++++++++++++++ ConvertImage.h | 30 +++++++++ ILImage.h | 51 ++++++++++++++ ILImageSupport.cpp | 133 +++++++++++++++++++++++++++++++++++++ TextureFileCreater.cpp | 122 ++++++++++++++++++++++++++++++++++ TextureFileCreater.h | 44 ++++++++++++ TextureFileCreaterR.cpp | 32 +++++++++ TextureFileCreaterRG.cpp | 30 +++++++++ TextureFileCreaterRGB.cpp | 62 +++++++++++++++++ TextureFileCreaterRGBA.cpp | 114 +++++++++++++++++++++++++++++++ main.cpp | 18 +++-- pixel_format.cpp | 53 ++++++++------- pixel_format.h | 8 +-- 14 files changed, 742 insertions(+), 40 deletions(-) create mode 100644 ConvertImage.cpp create mode 100644 ConvertImage.h create mode 100644 ILImage.h create mode 100644 ILImageSupport.cpp create mode 100644 TextureFileCreater.cpp create mode 100644 TextureFileCreater.h create mode 100644 TextureFileCreaterR.cpp create mode 100644 TextureFileCreaterRG.cpp create mode 100644 TextureFileCreaterRGB.cpp create mode 100644 TextureFileCreaterRGBA.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4898be8..1a3b43b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,18 @@ add_definitions(-DUNICODE -D_UNICODE) include_directories("DevIL Windows SDK/include") link_directories("DevIL Windows SDK/lib/x64/unicode/Release") -set(SOURCE_FILE main.cpp pixel_format.cpp) -set(HEADER_FILE pixel_format.h) +set(SOURCE_FILE main.cpp pixel_format.cpp + ILImage.h + ILImageSupport.cpp + ConvertImage.cpp + TextureFileCreater.h + TextureFileCreater.cpp + TextureFileCreaterR.cpp + TextureFileCreaterRG.cpp + TextureFileCreaterRGB.cpp + TextureFileCreaterRGBA.cpp) + +set(HEADER_FILE pixel_format.h ConvertImage.h) SOURCE_GROUP("Header Files" FILES ${HEADER_FILE}) SOURCE_GROUP("Source Files" FILES ${SOURCE_FILE}) diff --git a/ConvertImage.cpp b/ConvertImage.cpp new file mode 100644 index 0000000..dd9ed49 --- /dev/null +++ b/ConvertImage.cpp @@ -0,0 +1,71 @@ +#include"ConvertImage.h" +#include"ILImage.h" +#include"TextureFileCreater.h" + +TextureFileCreater *CreateTextureFileCreaterR(const PixelFormat *,ILImage *); +TextureFileCreater *CreateTextureFileCreaterRG(const PixelFormat *,ILImage *); +TextureFileCreater *CreateTextureFileCreaterRGB(const PixelFormat *,ILImage *); +TextureFileCreater *CreateTextureFileCreaterRGBA(const PixelFormat *,ILImage *); + +ConvertImage::ConvertImage() +{ + image=nullptr; +} + +ConvertImage::~ConvertImage() +{ + SAFE_CLEAR(image); +} + +bool ConvertImage::Load(const OSString &fn) +{ + LOG_INFO(OS_TEXT("File: ")+fn); + + image=new ILImage(); + + if(!image->LoadFile(fn)) + { + delete image; + return(false); + } + + filename=fn; + + return(true); +} + +bool ConvertImage::Convert(const PixelFormat **pf) +{ + image->Bind(); + + const uint channels=image->channels(); + + TextureFileCreater *tex_file_creater; + + if(channels==1)tex_file_creater=CreateTextureFileCreaterR(pf[0],image);else + if(channels==2)tex_file_creater=CreateTextureFileCreaterRG(pf[1],image);else + if(channels==3)tex_file_creater=CreateTextureFileCreaterRGB(pf[2],image);else + if(channels==4)tex_file_creater=CreateTextureFileCreaterRGBA(pf[3],image);else + { + LOG_ERROR(OS_TEXT("image format don't support ")); + return(false); + } + + if(!tex_file_creater->WriteFileHeader(filename)) + { + tex_file_creater->Delete(); + LOG_ERROR(OS_TEXT("Write file header failed.")); + return(false); + } + + if(!tex_file_creater->Write()) + { + tex_file_creater->Delete(); + return(false); + } + + tex_file_creater->Close(); + + delete tex_file_creater; + return(true); +} diff --git a/ConvertImage.h b/ConvertImage.h new file mode 100644 index 0000000..923fc2c --- /dev/null +++ b/ConvertImage.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include"pixel_format.h" + +using namespace hgl; + +class ILImage; + +class ConvertImage +{ + OSString filename; + + ILImage *image; + +private: + + bool CreateTextureFile(const PixelFormat *); + +private: + +public: + + ConvertImage(); + ~ConvertImage(); + + bool Load(const OSString &fn); + bool Convert(const PixelFormat **); +};//class ConvertImage \ No newline at end of file diff --git a/ILImage.h b/ILImage.h new file mode 100644 index 0000000..f1e4483 --- /dev/null +++ b/ILImage.h @@ -0,0 +1,51 @@ +#pragma once +#include +#include + +using namespace hgl; + +class ILImage +{ + ILuint il_index; + ILuint il_width,il_height; + ILuint il_bit,il_format,il_type; + + uint channel_count; + +private: + + bool Convert(ILuint,ILuint); + + void *GetData(ILuint,ILuint); + +public: + + const ILuint width ()const{return il_width;} + const ILuint height ()const{return il_height;} + const ILuint bit ()const{return il_bit;} + const ILuint format ()const{return il_format;} + const ILuint type ()const{return il_type;} + + const ILuint pixel_total()const{return il_width*il_height;} + +public: + + const uint channels()const{return channel_count;} //通道数量 + +public: + + ILImage(); + ~ILImage(); + + bool LoadFile(const OSString &); + + void Bind(); + + void *GetR(ILuint type); + + void *GetRG(ILuint type){return GetData(IL_LUMINANCE_ALPHA,type);} + void *GetRGB(ILuint type){return GetData(IL_RGB,type);} + void *GetBGR(ILuint type){return GetData(IL_BGR,type);} + void *GetRGBA(ILuint type){return GetData(IL_RGBA,type);} + void *GetBGRA(ILuint type){return GetData(IL_BGRA,type);} +};//class ILImage diff --git a/ILImageSupport.cpp b/ILImageSupport.cpp new file mode 100644 index 0000000..7d6f4fb --- /dev/null +++ b/ILImageSupport.cpp @@ -0,0 +1,133 @@ +//注:起名为ILImageSupport是为了避免与IL中现有的ilimage冲突 + +#include"ILImage.h" +#include +#include + +using namespace hgl; + +ILImage::ILImage() +{ + ilGenImages(1,&il_index); +} + +ILImage::~ILImage() +{ + ilDeleteImages(1,&il_index); +} + +void ILImage::Bind() +{ + ilBindImage(il_index); +} + +bool ILImage::Convert(ILuint format,ILuint type) +{ + if(il_format==format + &&il_type==type)return(true); + + Bind(); + if(!ilConvertImage(format,type)) + return(false); + + il_format=format; + il_type=type; + return(true); +} + +bool ILImage::LoadFile(const OSString &filename) +{ + Bind(); + + if(!ilLoadImage(filename.c_str())) + { + LOG_ERROR(OS_TEXT("LoadImage failed.")); + return(false); + } + + il_width =ilGetInteger(IL_IMAGE_WIDTH); + il_height =ilGetInteger(IL_IMAGE_HEIGHT); + il_bit =ilGetInteger(IL_IMAGE_BITS_PER_PIXEL); + il_format =ilGetInteger(IL_IMAGE_FORMAT); + il_type =ilGetInteger(IL_IMAGE_TYPE); + + if(ilGetInteger(IL_IMAGE_ORIGIN)==IL_ORIGIN_LOWER_LEFT) + iluFlipImage(); + + LOG_INFO(OS_TEXT("\t width: ")+OSString(il_width)); + LOG_INFO(OS_TEXT("\theight: ")+OSString(il_height)); + LOG_INFO(OS_TEXT("\t bit: ")+OSString(il_bit)); + LOG_INFO(OS_TEXT("\tformat: ")+OSString(il_format)); + LOG_INFO(OS_TEXT("\t type: ")+OSString(il_type)); + + if(il_format==IL_COLOR_INDEX) + { + uint il_pattle=ilGetInteger(IL_PALETTE_TYPE); + + if(il_pattle==IL_PAL_RGB24||il_pattle==IL_PAL_BGR24) + { + il_bit =24; + il_format =IL_BGR; + il_type =IL_UNSIGNED_BYTE; + } + else + if(il_pattle==IL_PAL_RGB32||il_pattle==IL_PAL_BGR32) + { + il_bit =48; + il_format =IL_BGR; + il_type =IL_UNSIGNED_SHORT; + } + else + if(il_pattle==IL_PAL_RGBA32||il_pattle==IL_PAL_BGRA32) + { + il_bit =32; + il_format =IL_BGRA; + il_type =IL_UNSIGNED_BYTE; + } + else + { + LOG_ERROR("Don't support the pattle format."); + return(false); + } + + Convert(il_format,il_type); + } + + if(il_format==IL_LUMINANCE||il_format==IL_ALPHA)channel_count=1;else + if(il_format==IL_LUMINANCE_ALPHA) channel_count=2;else + if(il_format==IL_RGB||il_format==IL_BGR) channel_count=3;else + if(il_format==IL_RGBA||il_format==IL_BGRA) channel_count=4;else + channel_count=0; + + return(true); +} + +void *ILImage::GetR(ILuint type) +{ + Bind(); + + if(il_format==IL_ALPHA)return ilGetAlpha(type); + if(il_format==IL_LUMINANCE) + { + if(il_type!=type) + { + if(!Convert(il_format,type)) + return(nullptr); + + return ilGetData(); + } + } + + return(nullptr); +} + +void *ILImage::GetData(ILuint format,ILuint type) +{ + Bind(); + + if(il_format!=format||il_type!=type) + if(!Convert(format,type)) + return nullptr; + + return ilGetData(); +} diff --git a/TextureFileCreater.cpp b/TextureFileCreater.cpp new file mode 100644 index 0000000..b3b4fc9 --- /dev/null +++ b/TextureFileCreater.cpp @@ -0,0 +1,122 @@ +#include"TextureFileCreater.h" +#include + +namespace +{ + /** + * 截取完整路径中的路径名和文件名 + * @param pathname 拆分后的路径名 + * @param filename 拆分后的文件名 + * @param fullname 拆分前的完整路径文件名 + */ + template + inline bool SplitFilename(BaseString &pathname,BaseString &filename,const BaseString &fullname) + { + if(fullname.Length()<=1) + return false; + + const T spear_char[] = { '/','\\' }; + + const int pos=fullname.FindRightChar(spear_char); + + if(pos==-1) + return(false); + + pathname.Strcpy(fullname,pos); + filename.Strcpy(fullname.c_str()+pos+1); + + return(true); + } + + template + inline BaseString ReplaceExtName(const BaseString &old_name,const BaseString &new_extname,const T split_char='.') + { + if(old_name.Length()<=1) + return(BaseString::charOf(split_char)+new_extname); + + const int pos=old_name.FindRightChar(split_char); + + if(pos==-1) + return old_name.SubString(0,pos+1)+new_extname; + else + return old_name+BaseString(split_char)+new_extname; + } +}//namespace + +bool ToILType(ILuint &type,const uint8 bits,const ColorDataType cdt) +{ + constexpr ILuint target_type[3][(uint)ColorDataType::END-1]= + { + //UNORM SNORM UINT SINT, USCALE,SSCALE, UFLOAT SFLOAT + {IL_UNSIGNED_BYTE, IL_BYTE, IL_UNSIGNED_BYTE, IL_BYTE, 0,0, 0, 0}, + {IL_UNSIGNED_SHORT, IL_SHORT, IL_UNSIGNED_SHORT, IL_SHORT, 0,0, IL_HALF, IL_HALF}, + {IL_UNSIGNED_INT, IL_INT, IL_UNSIGNED_INT, IL_INT, 0,0, IL_FLOAT, IL_FLOAT} + }; + + 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,ILImage *img) +{ + fmt=pf; + image=img; + + pixel_total=image->pixel_total(); + pixel_bytes=pf->GetPixelBytes(); + total_bytes=pixel_total*pixel_bytes; + + dos=nullptr; +} +TextureFileCreater::~TextureFileCreater() +{ + SAFE_CLEAR(dos); +} + +bool TextureFileCreater::WriteFileHeader(const OSString &old_filename) +{ + OSString pn,fn; + + SplitFilename(pn,fn,old_filename); + + filename=ReplaceExtName(old_filename,OS_TEXT(".Tex2D")); + + if(!fos.CreateTrunc(filename)) + return(false); + + dos=new io::LEDataOutputStream(&fos); + + dos->Write("Tex2D\x1A",6); + dos->WriteUint8(2); //版本 + dos->WriteBool(false); //是否有mipmaps + dos->WriteUint32(image->width()); + dos->WriteUint32(image->height()); + dos->WriteUint8(fmt->channels); //颜色通道数 + dos->WriteUint8((uint8 *)fmt->color,fmt->channels); //颜色标记 + dos->WriteUint8(fmt->bits,fmt->channels); //颜色位数 + dos->WriteUint8((uint8)fmt->type); //数据类型 + + return(true); +} + +bool TextureFileCreater::Write(void *data) +{ + return(dos->Write(data,total_bytes)==total_bytes); +} + +void TextureFileCreater::Close() +{ + SAFE_CLEAR(dos); + fos.Close(); +} + +void TextureFileCreater::Delete() +{ + Close(); + + filesystem::FileDelete(filename); +} \ No newline at end of file diff --git a/TextureFileCreater.h b/TextureFileCreater.h new file mode 100644 index 0000000..5d53a4d --- /dev/null +++ b/TextureFileCreater.h @@ -0,0 +1,44 @@ +#pragma once + +#include"ILImage.h" +#include"pixel_format.h" +#include +#include + +using namespace hgl; + +bool ToILType(ILuint &type,const uint8 bits,const ColorDataType cdt); + +class TextureFileCreater +{ +protected: + + const PixelFormat *fmt; + + ILImage *image; + + uint pixel_bytes; //单像素字节数 + uint pixel_total; //象素总量=width*height + uint total_bytes; //总字节数 + +protected: + + OSString filename; + + io::FileOutputStream fos; + io::DataOutputStream *dos; + + bool Write(void *); + +public: + + TextureFileCreater(const PixelFormat *pf,ILImage *); + virtual ~TextureFileCreater(); + + virtual bool WriteFileHeader(const OSString &); + + virtual bool Write()=0; + + virtual void Close(); + virtual void Delete(); +};//class TextureFileCreater \ No newline at end of file diff --git a/TextureFileCreaterR.cpp b/TextureFileCreaterR.cpp new file mode 100644 index 0000000..aacff9d --- /dev/null +++ b/TextureFileCreaterR.cpp @@ -0,0 +1,32 @@ +#include"TextureFileCreater.h" +#include"ILImage.h" + +class TextureFileCreaterR:public TextureFileCreater +{ +public: + + using TextureFileCreater::TextureFileCreater; + +public: + + bool Write() override + { + ILuint type; + + if(!ToILType(type,fmt->bits[0],fmt->type)) + return(nullptr); + + void *data=image->GetR(type); + + if(!data) + return(nullptr); + + //目前仅有R8UN,R16UN,R16F,R32U,R32I,R32F几种,都是8的整倍数,所以直接写 + return TextureFileCreater::Write(data); + } +};//class TextureFileCreaterR:public TextureFileCreater + +TextureFileCreater *CreateTextureFileCreaterR(const PixelFormat *pf,ILImage *image) +{ + return(new TextureFileCreaterR(pf,image)); +} \ No newline at end of file diff --git a/TextureFileCreaterRG.cpp b/TextureFileCreaterRG.cpp new file mode 100644 index 0000000..5e10f9e --- /dev/null +++ b/TextureFileCreaterRG.cpp @@ -0,0 +1,30 @@ +#include"TextureFileCreater.h" +#include"ILImage.h" + +class TextureFileCreaterRG:public TextureFileCreater +{ +public: + + using TextureFileCreater::TextureFileCreater; + +public: + + bool Write() override + { + ILuint type; + + if(!ToILType(type,fmt->bits[0],fmt->type)) + return(nullptr); + + void *data=image->GetRG(type); + + //目前仅有R8UN,R16UN,R16F,R32U,R32I,R32F几种,都是8的整倍数,所以直接写 + + return TextureFileCreater::Write(data); + } +};//class TextureFileCreaterRG:public TextureFileCreater + +TextureFileCreater *CreateTextureFileCreaterRG(const PixelFormat *pf,ILImage *image) +{ + return(new TextureFileCreaterRG(pf,image)); +} diff --git a/TextureFileCreaterRGB.cpp b/TextureFileCreaterRGB.cpp new file mode 100644 index 0000000..4594069 --- /dev/null +++ b/TextureFileCreaterRGB.cpp @@ -0,0 +1,62 @@ +#include"TextureFileCreater.h" +#include"ILImage.h" +#include + +class TextureFileCreaterRGB:public TextureFileCreater +{ +public: + + using TextureFileCreater::TextureFileCreater; + + void RGB8toRGB565(uint16 *target,uint8 *src,uint size) + { + for(uint i=0;i>3); + + ++target; + src+=3; + } + } + +public: + + bool Write() override + { + if(fmt->format==ColorFormat::RGB32U + ||fmt->format==ColorFormat::RGB32I + ||fmt->format==ColorFormat::RGB32F) + { + ILuint type; + + if(!ToILType(type,fmt->bits[0],fmt->type)) + return(nullptr); + + void *origin_rgb=image->GetRGB(type); + + return TextureFileCreater::Write(origin_rgb); + } + else if(fmt->format==ColorFormat::RGB565) + { + void *origin_rgb=image->GetRGB(IL_UNSIGNED_BYTE); + + AutoDelete rgb565=new uint16[image->pixel_total()]; + + RGB8toRGB565(rgb565,(uint8 *)origin_rgb,image->pixel_total()); + + return TextureFileCreater::Write(rgb565); + } + else + { + LOG_ERROR(OS_TEXT("Don't support this RGB format")); + return(false); + } + } +};//class TextureFileCreaterRGB:public TextureFileCreater + +TextureFileCreater *CreateTextureFileCreaterRGB(const PixelFormat *pf,ILImage *image) +{ + return(new TextureFileCreaterRGB(pf,image)); +} diff --git a/TextureFileCreaterRGBA.cpp b/TextureFileCreaterRGBA.cpp new file mode 100644 index 0000000..88d014a --- /dev/null +++ b/TextureFileCreaterRGBA.cpp @@ -0,0 +1,114 @@ +#include"TextureFileCreater.h" +#include"ILImage.h" +#include + +class TextureFileCreaterRGBA:public TextureFileCreater +{ +public: + + using TextureFileCreater::TextureFileCreater; + + void RGBA8toRGBA4(uint16 *target,uint8 *src,uint size) + { + for(uint i=0;i>4); + + ++target; + src+=4; + } + } + + void RGBA8toA1RGB5(uint16 *target,uint8 *src,uint size) + { + for(uint i=0;i>3); + + ++target; + src+=4; + } + } + + void RGBA16toA2BGR10(uint32 *target,uint16 *src,uint size) + { + for(uint i=0;i> 6); + + ++target; + src+=4; + } + } + +public: + + bool Write() override + { + if(fmt->format==ColorFormat::RGBA8UN + ||fmt->format==ColorFormat::RGBA16UN + ||fmt->format==ColorFormat::RGBA16F + ||fmt->format==ColorFormat::RGBA32U + ||fmt->format==ColorFormat::RGBA32I + ||fmt->format==ColorFormat::RGBA32F) + { + ILuint type; + + if(!ToILType(type,fmt->bits[0],fmt->type)) + return(nullptr); + + void *origin_rgba=image->GetRGBA(type); + + return TextureFileCreater::Write(origin_rgba); + } + else if(fmt->format==ColorFormat::BGRA4) + { + void *origin_rgba=image->GetRGBA(IL_UNSIGNED_BYTE); + + AutoDelete bgra4=new uint16[image->pixel_total()]; + + RGBA8toRGBA4(bgra4,(uint8 *)origin_rgba,image->pixel_total()); + + return TextureFileCreater::Write(bgra4); + } + else if(fmt->format==ColorFormat::A1RGB5) + { + void *origin_rgba=image->GetRGBA(IL_UNSIGNED_BYTE); + + AutoDelete a1_rgb5=new uint16[image->pixel_total()]; + + RGBA8toA1RGB5(a1_rgb5,(uint8 *)origin_rgba,image->pixel_total()); + + return TextureFileCreater::Write(a1_rgb5); + } + else if(fmt->format==ColorFormat::A2BGR10UN) + { + void *origin_rgba=image->GetRGBA(IL_UNSIGNED_SHORT); + + AutoDelete a2_bgr10=new uint32[image->pixel_total()]; + + RGBA16toA2BGR10(a2_bgr10,(uint16 *)origin_rgba,image->pixel_total()); + + return TextureFileCreater::Write(a2_bgr10); + } + else + { + LOG_ERROR(OS_TEXT("Don't support this RGBA format")); + return(false); + } + } +};//class TextureFileCreaterRGB:public TextureFileCreater + +TextureFileCreater *CreateTextureFileCreaterRGBA(const PixelFormat *pf,ILImage *image) +{ + return(new TextureFileCreaterRGBA(pf,image)); +} diff --git a/main.cpp b/main.cpp index 70d171f..ab08d3e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,13 +1,11 @@ -#include -#include -#include +#include #include -#include"pixel_format.h" #include #include #include #include #include +#include"ConvertImage.h" using namespace hgl; using namespace hgl::filesystem; @@ -48,7 +46,7 @@ void ParseParamFormat(const CmdParse &cmd) std::cout<name<name<<" "<GetPixelBytes()<<" bits "<type)]<channels<<": "<name<<" "<GetPixelBytes()<<" bits "<type)]<>3;} ///<获取单个象素所需字节数 };// const PixelFormat *GetPixelFormat(ColorFormat); ///<根据获取获取象素格式类型