Merge with develop
This commit is contained in:
parent
7a44693ec2
commit
83f8502b51
14 changed files with 644 additions and 160 deletions
|
@ -348,6 +348,27 @@ public:
|
||||||
*/
|
*/
|
||||||
void makeNonPowerOf2Dummy();
|
void makeNonPowerOf2Dummy();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make a bitmap fully opaque (set alpha to 255).
|
||||||
|
*/
|
||||||
|
void makeOpaque();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if the bitmap has uniform alpha values for all pixels.
|
||||||
|
* \param alpha return the uniform value if return is true
|
||||||
|
* \return uniform or not
|
||||||
|
*/
|
||||||
|
bool isAlphaUniform(uint8 *alpha = NULL) const;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if the bitmap is a real grayscale.
|
||||||
|
* \return grayscale or not
|
||||||
|
*/
|
||||||
|
bool isGrayscale() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the pixels buffer of the image, or of one of its mipmap.
|
* Return the pixels buffer of the image, or of one of its mipmap.
|
||||||
* Return a reference of an array in pixel format get with getPixelFormat().
|
* Return a reference of an array in pixel format get with getPixelFormat().
|
||||||
|
|
|
@ -146,6 +146,14 @@ public:
|
||||||
*/
|
*/
|
||||||
uint8 toGray() const;
|
uint8 toGray() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color is gray
|
||||||
|
*/
|
||||||
|
bool isGray() const
|
||||||
|
{
|
||||||
|
return R == G && G == B;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a 16 bits 565 pixel.
|
* Get a 16 bits 565 pixel.
|
||||||
*/
|
*/
|
||||||
|
@ -169,6 +177,17 @@ public:
|
||||||
B= (B<<3) + (B>>2);
|
B= (B<<3) + (B>>2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the RGBA fields with a 32 bits 8888 pixel.
|
||||||
|
*/
|
||||||
|
void set8888(uint32 col)
|
||||||
|
{
|
||||||
|
R = col & 255;
|
||||||
|
G = (col >> 8) & 255;
|
||||||
|
B = (col >> 16) & 255;
|
||||||
|
A = (col >> 24) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute in this the average of 2 RGBA.
|
* Compute in this the average of 2 RGBA.
|
||||||
|
|
|
@ -65,9 +65,9 @@ const uint32 CBitmap::bitPerPixels[ModeCount]=
|
||||||
16 // DsDt
|
16 // DsDt
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint32 CBitmap::DXTC1HEADER = NL_MAKEFOURCC('D','X', 'T', '1');
|
const uint32 CBitmap::DXTC1HEADER = NL_MAKEFOURCC('D', 'X', 'T', '1');
|
||||||
const uint32 CBitmap::DXTC3HEADER = NL_MAKEFOURCC('D','X', 'T', '3');
|
const uint32 CBitmap::DXTC3HEADER = NL_MAKEFOURCC('D', 'X', 'T', '3');
|
||||||
const uint32 CBitmap::DXTC5HEADER = NL_MAKEFOURCC('D','X', 'T', '5');
|
const uint32 CBitmap::DXTC5HEADER = NL_MAKEFOURCC('D', 'X', 'T', '5');
|
||||||
|
|
||||||
|
|
||||||
#ifdef NEL_ALL_BITMAP_WHITE
|
#ifdef NEL_ALL_BITMAP_WHITE
|
||||||
|
@ -309,6 +309,155 @@ void CBitmap::makeDummyFromBitField(const uint8 bitmap[1024])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------*\
|
||||||
|
makeOpaque
|
||||||
|
\*-------------------------------------------------------------------*/
|
||||||
|
void CBitmap::makeOpaque()
|
||||||
|
{
|
||||||
|
if (_Width*_Height == 0) return;
|
||||||
|
|
||||||
|
uint pixelSize;
|
||||||
|
|
||||||
|
switch(PixelFormat)
|
||||||
|
{
|
||||||
|
case RGBA: pixelSize = 4; break;
|
||||||
|
case AlphaLuminance: pixelSize = 2; break;
|
||||||
|
case Alpha: pixelSize = 1; break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint8 m = 0; m < _MipMapCount; ++m)
|
||||||
|
{
|
||||||
|
// get a pointer on original data
|
||||||
|
uint8 *data = _Data[m].getPtr();
|
||||||
|
|
||||||
|
// special case for only alpha values
|
||||||
|
if (pixelSize == 1)
|
||||||
|
{
|
||||||
|
memset(data, 255, _Data[m].size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// end of data
|
||||||
|
uint8 *endData = data + _Data[m].size();
|
||||||
|
|
||||||
|
// first alpha
|
||||||
|
data += pixelSize - 1;
|
||||||
|
|
||||||
|
// replace all alpha values by 255
|
||||||
|
while(data < endData)
|
||||||
|
{
|
||||||
|
*data = 255;
|
||||||
|
data += pixelSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------*\
|
||||||
|
isAlphaUniform
|
||||||
|
\*-------------------------------------------------------------------*/
|
||||||
|
bool CBitmap::isAlphaUniform(uint8 *alpha) const
|
||||||
|
{
|
||||||
|
uint32 size = _Data[0].size();
|
||||||
|
|
||||||
|
if (size == 0) return false;
|
||||||
|
|
||||||
|
uint pixelSize;
|
||||||
|
|
||||||
|
switch(PixelFormat)
|
||||||
|
{
|
||||||
|
// formats with alpha channel
|
||||||
|
case RGBA:
|
||||||
|
pixelSize = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AlphaLuminance:
|
||||||
|
pixelSize = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Alpha:
|
||||||
|
pixelSize = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// formats without alpha channel
|
||||||
|
case Luminance:
|
||||||
|
if (alpha) *alpha = 255;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a pointer on original data
|
||||||
|
uint8 *data = (uint8*)_Data[0].getPtr();
|
||||||
|
uint8 *endData = data + size;
|
||||||
|
|
||||||
|
// first alpha
|
||||||
|
data += pixelSize - 1;
|
||||||
|
|
||||||
|
// first alpha value
|
||||||
|
uint8 value = *data;
|
||||||
|
|
||||||
|
// check if all alphas have the same value
|
||||||
|
while(data < endData && *data == value) data += pixelSize;
|
||||||
|
|
||||||
|
// texture can be converted if all alphas are 0 or 255
|
||||||
|
if (data >= endData)
|
||||||
|
{
|
||||||
|
// return the uniform value
|
||||||
|
if (alpha) *alpha = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------*\
|
||||||
|
isGrayscale
|
||||||
|
\*-------------------------------------------------------------------*/
|
||||||
|
bool CBitmap::isGrayscale() const
|
||||||
|
{
|
||||||
|
// all grayscale formats or, al least, without color information
|
||||||
|
switch(PixelFormat)
|
||||||
|
{
|
||||||
|
case Luminance:
|
||||||
|
case AlphaLuminance:
|
||||||
|
case Alpha:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case RGBA:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// DXTC formats won't be managed at the moment
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 size = _Data[0].size();
|
||||||
|
if (size == 0) return false;
|
||||||
|
|
||||||
|
// get a pointer on original data
|
||||||
|
uint32 *data = (uint32*)_Data[0].getPtr();
|
||||||
|
uint32 *endData = (uint32*)((uint8*)data + size);
|
||||||
|
|
||||||
|
NLMISC::CRGBA color;
|
||||||
|
|
||||||
|
// check if all alphas have the same value
|
||||||
|
while(data < endData)
|
||||||
|
{
|
||||||
|
color.set8888(*data);
|
||||||
|
|
||||||
|
if (!color.isGray()) return false;
|
||||||
|
|
||||||
|
++data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -601,78 +601,157 @@ sint CSystemUtils::getTotalVideoMemory()
|
||||||
#elif defined(NL_OS_MAC)
|
#elif defined(NL_OS_MAC)
|
||||||
// the right method is using OpenGL
|
// the right method is using OpenGL
|
||||||
#else
|
#else
|
||||||
// under Linux, no method is really reliable...
|
if (res == -1)
|
||||||
NLMISC::CIFile file;
|
|
||||||
|
|
||||||
std::string logFile = "/var/log/Xorg.0.log";
|
|
||||||
|
|
||||||
// parse last Xorg.0.log
|
|
||||||
if (file.open(logFile, true))
|
|
||||||
{
|
{
|
||||||
char buffer[256];
|
// use nvidia-smi
|
||||||
|
std::string command = "nvidia-smi -q -d MEMORY";
|
||||||
|
|
||||||
while(!file.eof())
|
std::string out = getCommandOutput(command);
|
||||||
|
|
||||||
|
if (out.empty())
|
||||||
{
|
{
|
||||||
file.getline(buffer, 256);
|
nlwarning("Unable to launch %s", command.c_str());
|
||||||
|
|
||||||
if (buffer[0] == '\0') break;
|
|
||||||
|
|
||||||
std::string line(buffer);
|
|
||||||
|
|
||||||
// nvidia driver
|
|
||||||
std::string::size_type pos = line.find(") NVIDIA(");
|
|
||||||
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
{
|
|
||||||
// [ 20.883] (--) NVIDIA(0): Memory: 2097152 kBytes
|
|
||||||
pos = line.find("Memory: ", pos);
|
|
||||||
|
|
||||||
// found memory line
|
|
||||||
if (pos == std::string::npos) continue;
|
|
||||||
pos += 8;
|
|
||||||
|
|
||||||
std::string::size_type posUnits = line.find(" kBytes", pos);
|
|
||||||
|
|
||||||
// found units in KiB
|
|
||||||
if (posUnits == std::string::npos) continue;
|
|
||||||
|
|
||||||
std::string videoMemory = line.substr(pos, posUnits-pos);
|
|
||||||
|
|
||||||
if (!NLMISC::fromString(videoMemory, res)) continue;
|
|
||||||
|
|
||||||
nlinfo("Xorg NVIDIA driver reported %d KiB of video memory", res);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// intel driver
|
|
||||||
pos = line.find(") intel(");
|
|
||||||
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
{
|
|
||||||
// (**) intel(0): VideoRam: 131072 KB
|
|
||||||
pos = line.find("VideoRam: ", pos);
|
|
||||||
|
|
||||||
// found memory line
|
|
||||||
if (pos == std::string::npos) continue;
|
|
||||||
pos += 10;
|
|
||||||
|
|
||||||
std::string::size_type posUnits = line.find(" KB", pos);
|
|
||||||
|
|
||||||
// found units in KiB
|
|
||||||
if (posUnits == std::string::npos) continue;
|
|
||||||
|
|
||||||
std::string videoMemory = line.substr(pos, posUnits-pos);
|
|
||||||
|
|
||||||
if (!NLMISC::fromString(videoMemory, res)) continue;
|
|
||||||
|
|
||||||
nlinfo("Xorg Intel driver reported %d KiB of video memory", res);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: other drivers: nv, fglrx (ATI), radeon (ATI)
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
explode(out, std::string("\n"), lines, true);
|
||||||
|
|
||||||
file.close();
|
// process each line
|
||||||
|
for(uint i = 0; i < lines.size(); ++i)
|
||||||
|
{
|
||||||
|
// Total : 62 MB
|
||||||
|
|
||||||
|
std::string line = lines[i];
|
||||||
|
|
||||||
|
// find Total line
|
||||||
|
std::string::size_type pos = line.find("Total");
|
||||||
|
if (pos == std::string::npos) continue;
|
||||||
|
pos += 6;
|
||||||
|
|
||||||
|
// find separator
|
||||||
|
pos = line.find(':', pos);
|
||||||
|
if (pos == std::string::npos) continue;
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
// find units
|
||||||
|
std::string::size_type posUnits = line.find(' ', pos);
|
||||||
|
if (posUnits == std::string::npos) continue;
|
||||||
|
++posUnits;
|
||||||
|
|
||||||
|
// found device ID
|
||||||
|
std::string memory = line.substr(pos, posUnits-pos-1);
|
||||||
|
std::string units = line.substr(posUnits);
|
||||||
|
|
||||||
|
// convert video memory to sint
|
||||||
|
if (NLMISC::fromString(memory, res))
|
||||||
|
{
|
||||||
|
if (units == "MB")
|
||||||
|
{
|
||||||
|
res *= 1024;
|
||||||
|
}
|
||||||
|
else if (units == "GB")
|
||||||
|
{
|
||||||
|
res *= 1024 * 1024;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// reset to use other methods
|
||||||
|
res = -1;
|
||||||
|
|
||||||
|
nlwarning("nvidia-smi reported %d %s as wrong video memory units", res, units.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlinfo("nvidia-smi reported %d KiB of video memory", res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// reset to use other methods
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == -1)
|
||||||
|
{
|
||||||
|
// under Linux, no method is really reliable...
|
||||||
|
NLMISC::CIFile file;
|
||||||
|
|
||||||
|
std::string logFile = "/var/log/Xorg.0.log";
|
||||||
|
|
||||||
|
// parse last Xorg.0.log
|
||||||
|
if (file.open(logFile, true))
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
while(!file.eof())
|
||||||
|
{
|
||||||
|
file.getline(buffer, 256);
|
||||||
|
|
||||||
|
if (buffer[0] == '\0') break;
|
||||||
|
|
||||||
|
std::string line(buffer);
|
||||||
|
|
||||||
|
// nvidia driver
|
||||||
|
std::string::size_type pos = line.find(") NVIDIA(");
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
// [ 20.883] (--) NVIDIA(0): Memory: 2097152 kBytes
|
||||||
|
// [ 28.515] (--) NVIDIA(0): Memory: 262144 kBytes
|
||||||
|
pos = line.find("Memory: ", pos);
|
||||||
|
|
||||||
|
// found memory line
|
||||||
|
if (pos == std::string::npos) continue;
|
||||||
|
pos += 8;
|
||||||
|
|
||||||
|
std::string::size_type posUnits = line.find(" kBytes", pos);
|
||||||
|
|
||||||
|
// found units in KiB
|
||||||
|
if (posUnits == std::string::npos) continue;
|
||||||
|
|
||||||
|
std::string videoMemory = line.substr(pos, posUnits-pos);
|
||||||
|
|
||||||
|
if (!NLMISC::fromString(videoMemory, res)) continue;
|
||||||
|
|
||||||
|
nlinfo("Xorg NVIDIA driver reported %d KiB of video memory", res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// intel driver
|
||||||
|
pos = line.find(") intel(");
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
// (**) intel(0): VideoRam: 131072 KB
|
||||||
|
pos = line.find("VideoRam: ", pos);
|
||||||
|
|
||||||
|
// found memory line
|
||||||
|
if (pos == std::string::npos) continue;
|
||||||
|
pos += 10;
|
||||||
|
|
||||||
|
std::string::size_type posUnits = line.find(" KB", pos);
|
||||||
|
|
||||||
|
// found units in KiB
|
||||||
|
if (posUnits == std::string::npos) continue;
|
||||||
|
|
||||||
|
std::string videoMemory = line.substr(pos, posUnits-pos);
|
||||||
|
|
||||||
|
if (!NLMISC::fromString(videoMemory, res)) continue;
|
||||||
|
|
||||||
|
nlinfo("Xorg Intel driver reported %d KiB of video memory", res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: other drivers: fglrx (ATI), radeon (ATI)
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res == -1)
|
if (res == -1)
|
||||||
|
|
|
@ -35,6 +35,7 @@ IF(WITH_NEL_TOOLS)
|
||||||
SUBDIRS(
|
SUBDIRS(
|
||||||
build_interface
|
build_interface
|
||||||
get_neighbors
|
get_neighbors
|
||||||
|
textures_optimizer
|
||||||
tga_cut
|
tga_cut
|
||||||
tga_resize)
|
tga_resize)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
|
@ -669,69 +669,50 @@ static void BuildColoredVersionForOneBitmap(const CBuildInfo &bi, const std::str
|
||||||
// we can save it as RGB to optimize it
|
// we can save it as RGB to optimize it
|
||||||
if (bi.OptimizeTextures > 0 && depth == 32)
|
if (bi.OptimizeTextures > 0 && depth == 32)
|
||||||
{
|
{
|
||||||
uint32 size = srcBitmap.getPixels().size();
|
uint8 value = 0;
|
||||||
|
|
||||||
if (size > 0)
|
// texture can be converted if all alphas are 0 or 255
|
||||||
|
if (srcBitmap.isAlphaUniform(&value) && (value == 255 || value == 0))
|
||||||
{
|
{
|
||||||
// get a pointer on original data
|
if (bi.OptimizeTextures > 1)
|
||||||
uint8 *data = srcBitmap.getPixels().getPtr();
|
|
||||||
|
|
||||||
// pointer on first alpha value
|
|
||||||
uint8 *tmp = data + 3;
|
|
||||||
uint8 *endData = data + size;
|
|
||||||
uint8 value = *tmp;
|
|
||||||
|
|
||||||
// check if all alphas have the same value
|
|
||||||
while(tmp < endData && *tmp == value) tmp += 4;
|
|
||||||
|
|
||||||
// texture can be converted if all alphas are 0 or 255
|
|
||||||
if (tmp >= endData && (value == 255 || value == 0))
|
|
||||||
{
|
{
|
||||||
if (bi.OptimizeTextures > 1)
|
// make bitmap opaque
|
||||||
|
srcBitmap.makeOpaque();
|
||||||
|
|
||||||
|
// original depth is now 24 bits, since we discarded alpha channel
|
||||||
|
depth = 24;
|
||||||
|
|
||||||
|
NLMISC::COFile os;
|
||||||
|
|
||||||
|
if (os.open(fullInputBitmapPath))
|
||||||
{
|
{
|
||||||
// original depth is now 24 bits, since we discarded alpha channel
|
nlwarning("Optimizing texture %s...", fullInputBitmapPath.c_str());
|
||||||
depth = 24;
|
|
||||||
|
|
||||||
// if texture is fully transparent, make it fully opaque
|
std::string ext = CFile::getExtension(fullInputBitmapPath);
|
||||||
if (value == 0)
|
|
||||||
|
// resave the texture in optimized same format
|
||||||
|
if (ext == "png")
|
||||||
{
|
{
|
||||||
tmp = data + 3;
|
srcBitmap.writePNG(os, 24);
|
||||||
|
|
||||||
while(tmp < endData)
|
|
||||||
{
|
|
||||||
*tmp = 255;
|
|
||||||
tmp += 4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (ext == "tga")
|
||||||
NLMISC::COFile os;
|
|
||||||
|
|
||||||
if (os.open(fullInputBitmapPath))
|
|
||||||
{
|
{
|
||||||
nlwarning("Optimizing texture %s...", fullInputBitmapPath.c_str());
|
srcBitmap.writeTGA(os, 24);
|
||||||
|
}
|
||||||
std::string ext = CFile::getExtension(fullInputBitmapPath);
|
else
|
||||||
|
{
|
||||||
// resave the texture in optimized same format
|
nlwarning("Don't support %s format for texture, unable to save it", ext.c_str());
|
||||||
if (ext == "png")
|
|
||||||
{
|
|
||||||
srcBitmap.writePNG(os, 24);
|
|
||||||
}
|
|
||||||
else if (ext == "tga")
|
|
||||||
{
|
|
||||||
srcBitmap.writeTGA(os, 24);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning("Don't support %s format for texture, unable to save it", ext.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nlwarning("Texture %s can be optimized", fullInputBitmapPath.c_str());
|
nlwarning("Unable to save texture %s", fullInputBitmapPath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Texture %s can be optimized", fullInputBitmapPath.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
code/nel/tools/3d/textures_optimizer/CMakeLists.txt
Normal file
9
code/nel/tools/3d/textures_optimizer/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
FILE(GLOB SRC *.cpp *.h)
|
||||||
|
|
||||||
|
ADD_EXECUTABLE(textures_optimizer ${SRC})
|
||||||
|
|
||||||
|
TARGET_LINK_LIBRARIES(textures_optimizer nelmisc)
|
||||||
|
NL_DEFAULT_PROPS(textures_optimizer "NeL, Tools, 3D: Textures optimizer")
|
||||||
|
NL_ADD_RUNTIME_FLAGS(textures_optimizer)
|
||||||
|
|
||||||
|
INSTALL(TARGETS textures_optimizer RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT tools3d)
|
233
code/nel/tools/3d/textures_optimizer/main.cpp
Normal file
233
code/nel/tools/3d/textures_optimizer/main.cpp
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
||||||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as
|
||||||
|
// published by the Free Software Foundation, either version 3 of the
|
||||||
|
// License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "nel/misc/file.h"
|
||||||
|
#include "nel/misc/bitmap.h"
|
||||||
|
#include "nel/misc/path.h"
|
||||||
|
#include "nel/misc/debug.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void writeInstructions()
|
||||||
|
{
|
||||||
|
std::cout << "Syntax: textures_optimizer [-a] [-g] <input>" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << " Try to optimize TGA or PNG textures by removing useless alpha channel or converting a RGB with black and white values to grayscale" << std::endl;
|
||||||
|
std::cout << " By default, it only make checks and display if texture can optimized or not" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "with" << std::endl;
|
||||||
|
std::cout << "-a : Remove alpha channel if useless" << std::endl;
|
||||||
|
std::cout << "-g : Convert to grayscale if all pixels are gray" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
std::cout << "-h or -? for this help" << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FixAlpha = false;
|
||||||
|
bool FixGrayscale = false;
|
||||||
|
|
||||||
|
std::vector<std::string> InputFilenames;
|
||||||
|
|
||||||
|
bool parseOptions(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// process each argument
|
||||||
|
for(sint i = 1; i < argc; ++i)
|
||||||
|
{
|
||||||
|
std::string option = argv[i];
|
||||||
|
|
||||||
|
if (option.length() > 0)
|
||||||
|
{
|
||||||
|
bool isOption = option[0] == '-';
|
||||||
|
|
||||||
|
#ifdef NL_OS_WINDOWS
|
||||||
|
// authorize / for options only under Windows,
|
||||||
|
// because under Linux it could be a full path
|
||||||
|
if (!isOption) isOption = (option[0] == '/');
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Option
|
||||||
|
if (isOption)
|
||||||
|
{
|
||||||
|
// remove option prefix
|
||||||
|
option = option.substr(1);
|
||||||
|
|
||||||
|
// Fix alpha
|
||||||
|
if (option == "a")
|
||||||
|
{
|
||||||
|
FixAlpha = true;
|
||||||
|
}
|
||||||
|
// Fix grayscale
|
||||||
|
else if (option == "g")
|
||||||
|
{
|
||||||
|
FixGrayscale = true;
|
||||||
|
}
|
||||||
|
else if (option == "h" || option == "?")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Unknown option -%s", option.c_str());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Filename
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string ext = NLMISC::toLower(NLMISC::CFile::getExtension(option));
|
||||||
|
|
||||||
|
if (ext == "png" || ext == "tga")
|
||||||
|
{
|
||||||
|
InputFilenames.push_back(option);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nlwarning("Only PNG and TGA files supported, %s won't be processed", option.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !InputFilenames.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "nel/misc/system_utils.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
NLMISC::CApplicationContext applicationContext;
|
||||||
|
|
||||||
|
if (!parseOptions(argc, argv))
|
||||||
|
{
|
||||||
|
writeInstructions();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint i = 0; i < InputFilenames.size(); ++i)
|
||||||
|
{
|
||||||
|
std::string ext = NLMISC::toLower(NLMISC::CFile::getExtension(InputFilenames[i]));
|
||||||
|
|
||||||
|
NLMISC::CIFile input;
|
||||||
|
|
||||||
|
if (!input.open(InputFilenames[i]))
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to open " << InputFilenames[i] << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NLMISC::CBitmap bitmap;
|
||||||
|
|
||||||
|
uint8 depth = bitmap.load(input);
|
||||||
|
|
||||||
|
// don't need file so close it
|
||||||
|
input.close();
|
||||||
|
|
||||||
|
if (depth == 0)
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to decode " << InputFilenames[i] << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
bool hasAlpha = false;
|
||||||
|
bool isGrayscale = false;
|
||||||
|
|
||||||
|
if (bitmap.getPixelFormat() == NLMISC::CBitmap::RGBA && depth == 32)
|
||||||
|
{
|
||||||
|
hasAlpha = true;
|
||||||
|
}
|
||||||
|
else if (bitmap.getPixelFormat() == NLMISC::CBitmap::AlphaLuminance)
|
||||||
|
{
|
||||||
|
hasAlpha = true;
|
||||||
|
isGrayscale = true;
|
||||||
|
}
|
||||||
|
else if (bitmap.getPixelFormat() == NLMISC::CBitmap::Luminance)
|
||||||
|
{
|
||||||
|
isGrayscale = true;
|
||||||
|
}
|
||||||
|
else if (bitmap.getPixelFormat() == NLMISC::CBitmap::Alpha)
|
||||||
|
{
|
||||||
|
hasAlpha = true;
|
||||||
|
isGrayscale = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isGrayscale && bitmap.isGrayscale())
|
||||||
|
{
|
||||||
|
std::cout << InputFilenames[i] << " (grayscale image with RGB colors)" << std::endl;
|
||||||
|
|
||||||
|
if (FixGrayscale)
|
||||||
|
{
|
||||||
|
if (!bitmap.convertToType(hasAlpha ? NLMISC::CBitmap::AlphaLuminance:NLMISC::CBitmap::Luminance))
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to convert to Luminance" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
isGrayscale = true;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 alpha = 0;
|
||||||
|
|
||||||
|
if (hasAlpha && bitmap.isAlphaUniform(&alpha))
|
||||||
|
{
|
||||||
|
std::cout << InputFilenames[i] << " (image with uniform alpha channel " << alpha << ")" << std::endl;
|
||||||
|
|
||||||
|
if (FixAlpha && (alpha == 0 || alpha == 255))
|
||||||
|
{
|
||||||
|
bitmap.makeOpaque();
|
||||||
|
|
||||||
|
hasAlpha = false;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!modified) continue;
|
||||||
|
|
||||||
|
NLMISC::COFile output;
|
||||||
|
|
||||||
|
if (!output.open(InputFilenames[i]))
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to open" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 newDepth = isGrayscale ? 8:24;
|
||||||
|
|
||||||
|
if (hasAlpha) newDepth += 8;
|
||||||
|
|
||||||
|
bool res = false;
|
||||||
|
|
||||||
|
if (ext == "png")
|
||||||
|
{
|
||||||
|
res = bitmap.writePNG(output, newDepth);
|
||||||
|
}
|
||||||
|
else if (ext == "tga")
|
||||||
|
{
|
||||||
|
res = bitmap.writePNG(output, newDepth);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
std::cerr << "Unable to encode" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -843,7 +843,7 @@ void CPatchManager::createBatchFile(CProductDescriptionForClient &descFile, bool
|
||||||
for (uint32 fff = 0; fff < vFilenames.size (); fff++)
|
for (uint32 fff = 0; fff < vFilenames.size (); fff++)
|
||||||
{
|
{
|
||||||
string SrcPath = ClientPatchPath;
|
string SrcPath = ClientPatchPath;
|
||||||
string DstPath = rCat.getUnpackTo();
|
string DstPath = CPath::standardizePath(rCat.getUnpackTo()); // to be sure there is a / at the end
|
||||||
NLMISC::CFile::createDirectoryTree(DstPath);
|
NLMISC::CFile::createDirectoryTree(DstPath);
|
||||||
|
|
||||||
// this file must be moved
|
// this file must be moved
|
||||||
|
@ -2400,19 +2400,6 @@ void CCheckThread::run ()
|
||||||
fromString(sServerVersion, nServerVersion);
|
fromString(sServerVersion, nServerVersion);
|
||||||
fromString(sClientVersion, nClientVersion);
|
fromString(sClientVersion, nClientVersion);
|
||||||
|
|
||||||
#ifdef NL_OS_UNIX
|
|
||||||
string sClientNewVersion = ClientCfg.BuildName;
|
|
||||||
|
|
||||||
sint32 nClientNewVersion;
|
|
||||||
fromString(sClientNewVersion, nClientNewVersion);
|
|
||||||
|
|
||||||
// servers files are not compatible with current client, use last client version
|
|
||||||
if (nClientNewVersion && nServerVersion > nClientNewVersion)
|
|
||||||
{
|
|
||||||
nServerVersion = nClientNewVersion;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nClientVersion != nServerVersion)
|
if (nClientVersion != nServerVersion)
|
||||||
{
|
{
|
||||||
// first, try in the version subdirectory
|
// first, try in the version subdirectory
|
||||||
|
|
|
@ -329,10 +329,12 @@ void CGuildMemberModule::_inviteCharacterInGuild(CGuildCharProxy& invitor, CGuil
|
||||||
/// check guild and invited member allegiances compatibilities
|
/// check guild and invited member allegiances compatibilities
|
||||||
CGuild::TAllegiances guildAllegiance, invitedAllegiance;
|
CGuild::TAllegiances guildAllegiance, invitedAllegiance;
|
||||||
guildAllegiance = guild->getAllegiance();
|
guildAllegiance = guild->getAllegiance();
|
||||||
|
|
||||||
CCharacter * invitedChar = PlayerManager.getChar(target.getId());
|
CCharacter * invitedChar = PlayerManager.getChar(target.getId());
|
||||||
if( invitedChar == 0 ) return;
|
if (invitedChar == NULL) return;
|
||||||
invitedAllegiance = invitedChar->getAllegiance();
|
invitedAllegiance = invitedChar->getAllegiance();
|
||||||
if( invitedAllegiance.first != guildAllegiance.first && invitedAllegiance.first != PVP_CLAN::Neutral )
|
|
||||||
|
if (invitedAllegiance.first != guildAllegiance.first && invitedAllegiance.first != PVP_CLAN::Neutral)
|
||||||
{
|
{
|
||||||
SM_STATIC_PARAMS_2( params, STRING_MANAGER::player, STRING_MANAGER::faction );
|
SM_STATIC_PARAMS_2( params, STRING_MANAGER::player, STRING_MANAGER::faction );
|
||||||
params[0].setEIdAIAlias( target.getId(), CAIAliasTranslator::getInstance()->getAIAlias( target.getId()) );
|
params[0].setEIdAIAlias( target.getId(), CAIAliasTranslator::getInstance()->getAIAlias( target.getId()) );
|
||||||
|
@ -340,7 +342,8 @@ void CGuildMemberModule::_inviteCharacterInGuild(CGuildCharProxy& invitor, CGuil
|
||||||
invitor.sendSystemMessage("GUILD_ICOMPATIBLE_ALLEGIANCE",params);
|
invitor.sendSystemMessage("GUILD_ICOMPATIBLE_ALLEGIANCE",params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( invitedAllegiance.second != guildAllegiance.second && invitedAllegiance.second != PVP_CLAN::Neutral )
|
|
||||||
|
if (invitedAllegiance.second != guildAllegiance.second && invitedAllegiance.second != PVP_CLAN::Neutral)
|
||||||
{
|
{
|
||||||
SM_STATIC_PARAMS_2( params, STRING_MANAGER::player, STRING_MANAGER::faction );
|
SM_STATIC_PARAMS_2( params, STRING_MANAGER::player, STRING_MANAGER::faction );
|
||||||
params[0].setEIdAIAlias( target.getId(), CAIAliasTranslator::getInstance()->getAIAlias( target.getId()) );
|
params[0].setEIdAIAlias( target.getId(), CAIAliasTranslator::getInstance()->getAIAlias( target.getId()) );
|
||||||
|
|
|
@ -104,7 +104,7 @@ uint32 IMissionStepTemplate::sendRpStepText(CCharacter * user,const std::vector<
|
||||||
|
|
||||||
_User = user;
|
_User = user;
|
||||||
|
|
||||||
if (_RoleplayText.substr(0, 6) == "WEBIG_")
|
if (_RoleplayText.compare(0, 6, "WEBIG_") == 0)
|
||||||
{
|
{
|
||||||
TVectorParamCheck params;
|
TVectorParamCheck params;
|
||||||
string name = _RoleplayText;
|
string name = _RoleplayText;
|
||||||
|
@ -174,7 +174,7 @@ uint32 IMissionStepTemplate::sendStepText(CCharacter * user,const std::vector<ui
|
||||||
// If the text is overriden, add the overide parameters
|
// If the text is overriden, add the overide parameters
|
||||||
if ( !_OverridenText.empty() )
|
if ( !_OverridenText.empty() )
|
||||||
{
|
{
|
||||||
if (_OverridenText.substr(0, 6) == "WEBIG_")
|
if (_OverridenText.compare(0, 6, "WEBIG_") == 0)
|
||||||
{
|
{
|
||||||
string text = _OverridenText;
|
string text = _OverridenText;
|
||||||
if (user)
|
if (user)
|
||||||
|
|
|
@ -2441,7 +2441,7 @@ uint32 CMissionTemplate::testPrerequisits( CCharacter * user, CPrerequisitInfos
|
||||||
|
|
||||||
uint32 CMissionTemplate::sendTitleText( const TDataSetRow & userRow, const TDataSetRow & giver ) const
|
uint32 CMissionTemplate::sendTitleText( const TDataSetRow & userRow, const TDataSetRow & giver ) const
|
||||||
{
|
{
|
||||||
if (TitleText.substr(0, 6) == "WEBIG_")
|
if (TitleText.compare(0, 6, "WEBIG_") == 0)
|
||||||
{
|
{
|
||||||
string text = TitleText;
|
string text = TitleText;
|
||||||
CCharacter *user = PlayerManager.getChar(getEntityIdFromRow(userRow));
|
CCharacter *user = PlayerManager.getChar(getEntityIdFromRow(userRow));
|
||||||
|
@ -2469,7 +2469,7 @@ uint32 CMissionTemplate::sendTitleText( const TDataSetRow & userRow, const TData
|
||||||
|
|
||||||
uint32 CMissionTemplate::sendAutoText( const TDataSetRow & userRow,const NLMISC::CEntityId & giver) const
|
uint32 CMissionTemplate::sendAutoText( const TDataSetRow & userRow,const NLMISC::CEntityId & giver) const
|
||||||
{
|
{
|
||||||
if (AutoText.substr(0, 6) == "WEBIG_")
|
if (AutoText.compare(0, 6, "WEBIG_") == 0)
|
||||||
{
|
{
|
||||||
string text = AutoText;
|
string text = AutoText;
|
||||||
CCharacter *user = PlayerManager.getChar(getEntityIdFromRow(userRow));
|
CCharacter *user = PlayerManager.getChar(getEntityIdFromRow(userRow));
|
||||||
|
@ -2494,7 +2494,7 @@ uint32 CMissionTemplate::sendAutoText( const TDataSetRow & userRow,const NLMISC:
|
||||||
|
|
||||||
uint32 CMissionTemplate::sendDescText( const TDataSetRow & userRow, const TDataSetRow & giver, uint32 descIndex) const
|
uint32 CMissionTemplate::sendDescText( const TDataSetRow & userRow, const TDataSetRow & giver, uint32 descIndex) const
|
||||||
{
|
{
|
||||||
if (DescText.substr(0, 6) == "WEBIG_")
|
if (DescText.compare(0, 6, "WEBIG_") == 0)
|
||||||
{
|
{
|
||||||
string text = DescText;
|
string text = DescText;
|
||||||
CCharacter *user = PlayerManager.getChar(getEntityIdFromRow(userRow));
|
CCharacter *user = PlayerManager.getChar(getEntityIdFromRow(userRow));
|
||||||
|
|
|
@ -8,6 +8,9 @@ FILE(GLOB SRC main.cpp
|
||||||
${CMAKE_SOURCE_DIR}/ryzom/client/src/stdpch.h
|
${CMAKE_SOURCE_DIR}/ryzom/client/src/stdpch.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# always enable custom patch server
|
||||||
|
ADD_DEFINITIONS(-DRZ_USE_CUSTOM_PATCH_SERVER)
|
||||||
|
|
||||||
ADD_EXECUTABLE(ryzom_client_patcher ${SRC})
|
ADD_EXECUTABLE(ryzom_client_patcher ${SRC})
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
INCLUDE_DIRECTORIES(
|
||||||
|
|
|
@ -397,4 +397,3 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue