TexConv/ComboTexture.cpp

342 lines
9.6 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include<iostream>
#include<iomanip>
#include"ILImage.h"
#include<hgl/type/DataType.h>
#include<hgl/util/cmd/CmdParse.h>
#include<hgl/type/Smart.h>
using namespace hgl;
using namespace hgl::util;
#if HGL_OS == HGL_OS_Windows
#define std_cout std::wcout
#else
#define std_cout std::cout
#endif//
namespace hgl
{
constexpr double TWO_SQRT=1.414213562373095; //2的开方unreal用的这个
constexpr double clamp_u=0.436*255.0;
constexpr double clamp_v=0.615*255.0;
void RGB2YUV(uint8 *y,uint8 *u,uint8 *v,const uint8 *rgb,const uint count,const double gamma)
{
uint8 r,g,b;
for(uint i=0;i<count;i++)
{
r=*rgb++;
g=*rgb++;
b=*rgb++;
*y = 0.299 * r + 0.587 * g + 0.114 * b;
*u++=(clamp_u - 0.14713 * r - 0.28886 * g + 0.436 * b) / 0.872;
*v++=(clamp_v + 0.615 * r - 0.51499 * g - 0.10001 * b) / 1.230;
*y=clamp(pow((*y)/255.0f,gamma))*255;
++y;
}
}
template<typename T>
void MixRGB(T *rgb,const T *r,const T *g,const T *b,const uint count)
{
for(uint i=0;i<count;i++)
{
*rgb=*r;++rgb;++r;
*rgb=*g;++rgb;++g;
*rgb=*b;++rgb;++b;
}
}
template<typename T>
void MixRGBA(T *rgba,const T *r,const T *g,const T *b,const T *a,const uint count)
{
for(uint i=0;i<count;i++)
{
*rgba=*r;++rgba;++r;
*rgba=*g;++rgba;++g;
*rgba=*b;++rgba;++b;
*rgba=*a;++rgba;++a;
}
}
template<typename T>
void MixRGBA(T *rgba,const T *rgb,const T *a,const uint count)
{
for(uint i=0;i<count;i++)
{
*rgba=*rgb;++rgba;++rgb;
*rgba=*rgb;++rgba;++rgb;
*rgba=*rgb;++rgba;++rgb;
*rgba=*a;++rgba;++a;
}
}
bool SaveRGBAFile(const OSString &filename,const uint w,const uint h,const float scale,const uint8 *rgb,const uint8 *a,const OSString &flag)
{
const OSString out_filename=OSString(filename)+OS_TEXT("_")+flag+OS_TEXT(".png");
AutoDeleteArray<uint8> pixels(w*h*4);
MixRGBA<uint8>(pixels,rgb,a,w*h);
if(SaveImageToFile(out_filename,w,h,scale,4,IL_UNSIGNED_BYTE,pixels))
{
std_cout<<OS_TEXT("Output ")<<flag.c_str()<<OS_TEXT(": ")<<out_filename.c_str()<<std::endl;
return(true);
}
return(false);
}
bool SaveRGBAFile(const OSString &filename,const uint w,const uint h,const float scale,const uint8 *r,const uint8 *g,const uint8 *b,const uint8 *a,const OSString &flag)
{
const OSString out_filename=OSString(filename)+OS_TEXT("_")+flag+OS_TEXT(".png");
AutoDeleteArray<uint8> pixels(w*h*4);
MixRGBA<uint8>(pixels,r,g,b,a,w*h);
if(SaveImageToFile(out_filename,w,h,scale,4,IL_UNSIGNED_BYTE,pixels))
{
std_cout<<OS_TEXT("Output ")<<flag.c_str()<<OS_TEXT(": ")<<out_filename.c_str()<<std::endl;
return(true);
}
return(false);
}
bool SaveRGBFile(const OSString &filename,const uint w,const uint h,const float scale,const uint8 *r,const uint8 *g,const uint8 *b,const OSString &flag)
{
const OSString out_filename=OSString(filename)+OS_TEXT("_")+flag+OS_TEXT(".png");
AutoDeleteArray<uint8> pixels(w*h*3);
MixRGB<uint8>(pixels,r,g,b,w*h);
if(SaveImageToFile(out_filename,w,h,scale,3,IL_UNSIGNED_BYTE,pixels))
{
std_cout<<OS_TEXT("Output ")<<flag.c_str()<<OS_TEXT(": ")<<out_filename.c_str()<<std::endl;
return(true);
}
return(false);
}
}//namespace hgl
double GetArgGamma(const os_char *param)
{
if(!param||!*param)return 1.0f;
if(hgl::stricmp(param,"/gamma:",7))
return 1.0f;
double result;
if(stof(param+7,result))
return result;
return 1.0f;
}
int os_main(int argc,os_char **argv)
{
std::cout<<"Combo Texture Compression"<<std::endl<<std::endl;
if(argc<2)
{
// FullTexture: Y+Normal
// HalfTexture: U+V+M+R
std::cout<<"Example: ComboTexture <output name> MPBR Color.png Normal.png Metallic.png Roughness.png [/gamma:2.2]"<<std::endl;
// FullTexture: Y1+Y2+Y3+Y4
// HalfTexture: U1+U2+U3+U4
// HalfTexture: V1+V2+V3+V4
std::cout<<"Example: ComboTexture <output name> 4RGB Color1.png Color2.png Color3.png Color4.png [/gamma:2.2]"<<std::endl;
// FullTexture: Y1+Normal1
// FullTexture: Y2+Normal2
// HalfTexture: U1+V1+U2+V2
std::cout<<"Example: ComboTexture <output name> 2CN Color1.png Normal1.png Color2.png Normal2.png [/gamma:2.2]"<<std::endl;
//// FullTexture: Y1+Y2+G
//// HalfTexture: U1+V1+U2+V2
//std::cout<<"Example1: ComboTexture <output name> C2G1 Color1.png Color2.png Grayscale.png"<<std::endl;
//// FullTexture: Y+M+R
//// HalfTexture: U+V+G
//std::cout<<"Example2: ComboTexture <output name> MPBR6 Color.png Matallic.png Roughness.png Grayscale.png"<<std::endl;
//// FullTexture: Y+G1+G2
//// HalfTexture: U+V+M+R
//std::cout<<"Example3: ComboTexture <output name> MPBR7 Color.png Matallic.png Roughness.png Grayscale1.png Grayscale2.png"<<std::endl;
return(0);
}
ilInit();
if(stricmp(argv[2],"MPBR")==0)
{
ILImage color,normal,metallic,roughness;
uint w,h;
if(!color.LoadFile(argv[3]))return(1);
if(!normal.LoadFile(argv[4]))return(1);
if(!metallic.LoadFile(argv[5]))return(1);
if(!roughness.LoadFile(argv[6]))return(1);
double gamma=(argc>7?GetArgGamma(argv[7]):1.0f);
color.ToRGB();
normal.ToRGB();
metallic.ToGray();
roughness.ToGray();
w=color.width();
h=color.height();
normal.Resize(w,h);
metallic.Resize(w,h);
roughness.Resize(w,h);
const uint pixel_total=w*h;
AutoDeleteArray<uint8> y(pixel_total);
AutoDeleteArray<uint8> u(pixel_total);
AutoDeleteArray<uint8> v(pixel_total);
RGB2YUV(y,u,v,(uint8 *)color.GetRGB(IL_UNSIGNED_BYTE),pixel_total,gamma);
SaveRGBAFile( argv[1],
w,h,1.0,
(uint8 *)normal.GetRGB(IL_UNSIGNED_BYTE),
y,
OS_TEXT("NormalLuma"));
SaveRGBAFile( argv[1],
w,h,0.5,
u,v,
(uint8 *)metallic.GetLum(IL_UNSIGNED_BYTE),
(uint8 *)roughness.GetLum(IL_UNSIGNED_BYTE),
OS_TEXT("CbCrMR"));
}
else
if(stricmp(argv[2],"4RGB")==0)
{
ILImage rgb[4];
uint w,h;
if(!rgb[0].LoadFile(argv[3]))return 1;
if(!rgb[1].LoadFile(argv[4]))return 1;
if(!rgb[2].LoadFile(argv[5]))return 1;
if(!rgb[3].LoadFile(argv[6]))return 1;
double gamma=(argc>7?GetArgGamma(argv[7]):1.0f);
rgb[0].ToRGB();
rgb[1].ToRGB();
rgb[2].ToRGB();
rgb[3].ToRGB();
w=rgb[0].width();
h=rgb[0].height();
rgb[1].Resize(w,h);
rgb[2].Resize(w,h);
rgb[3].Resize(w,h);
const uint pixel_total=w*h;
AutoDeleteArray<uint8> y[4],u[4],v[4];
for(uint i=0;i<4;i++)
{
y[i].alloc(pixel_total);
u[i].alloc(pixel_total);
v[i].alloc(pixel_total);
RGB2YUV(y[i],u[i],v[i],(uint8 *)rgb[i].GetRGB(IL_UNSIGNED_BYTE),pixel_total,gamma);
}
SaveRGBAFile( argv[1],
w,h,1.0,
y[0],y[1],y[2],y[3],
OS_TEXT("4Luma"));
SaveRGBAFile( argv[1],
w,h,0.5,
u[0],u[1],u[2],u[3],
OS_TEXT("4Cb"));
SaveRGBAFile( argv[1],
w,h,0.5,
v[0],v[1],v[2],v[3],
OS_TEXT("4Cr"));
}
else
if(stricmp(argv[2],"2CN")==0)
{
ILImage color[2],normal[2];
uint w,h;
if(!color[0].LoadFile(argv[3]))return(1);
if(!normal[0].LoadFile(argv[4]))return(1);
if(!color[1].LoadFile(argv[5]))return(1);
if(!normal[1].LoadFile(argv[6]))return(1);
double gamma=(argc>7?GetArgGamma(argv[7]):1.0f);
color[0].ToRGB();
normal[0].ToRGB();
color[1].ToRGB();
normal[1].ToRGB();
w=color[0].width();
h=color[0].height();
color[1].Resize(w,h);
normal[0].Resize(w,h);
normal[1].Resize(w,h);
const uint pixel_total=w*h;
AutoDeleteArray<uint8> y[2],u[2],v[2];
for(uint i=0;i<2;i++)
{
y[i].alloc(pixel_total);
u[i].alloc(pixel_total);
v[i].alloc(pixel_total);
RGB2YUV(y[i],u[i],v[i],(uint8 *)color[i].GetRGB(IL_UNSIGNED_BYTE),pixel_total,gamma);
}
SaveRGBAFile( argv[1],
w,h,1.0,
(uint8 *)normal[0].GetRGB(IL_UNSIGNED_BYTE),
y[0],
OS_TEXT("NormalLuma1"));
SaveRGBAFile( argv[1],
w,h,1.0,
(uint8 *)normal[1].GetRGB(IL_UNSIGNED_BYTE),
y[1],
OS_TEXT("NormalLuma2"));
SaveRGBAFile( argv[1],
w,h,0.5,
u[0],v[0],
u[1],v[1],
OS_TEXT("2CbCr"));
}
ilShutDown();
return 0;
}