Merge branch 'master' into DecompressASTC

This commit is contained in:
Pavel Krajcevski 2014-11-03 18:28:44 -05:00
commit 168c6a0071
3 changed files with 131 additions and 104 deletions

View File

@ -111,13 +111,14 @@ void ExtractBasename(const char *filename, char *buf, size_t bufSz) {
int main(int argc, char **argv) {
int fileArg = 1;
if(fileArg == argc) {
if (fileArg == argc) {
PrintUsage();
exit(1);
}
char decompressedOutput[256]; decompressedOutput[0] = '\0';
bool bNoDecompress = false;
char decompressedOutput[256];
decompressedOutput[0] = '\0';
bool bDecompress = true;
int numJobs = 0;
int quality = 50;
int numThreads = 1;
@ -134,10 +135,10 @@ int main(int argc, char **argv) {
do {
knowArg = false;
if(strcmp(argv[fileArg], "-n") == 0) {
if (strcmp(argv[fileArg], "-n") == 0) {
fileArg++;
if(fileArg == argc || (numCompressions = atoi(argv[fileArg])) < 0) {
if (fileArg == argc || (numCompressions = atoi(argv[fileArg])) < 0) {
PrintUsage();
exit(1);
}
@ -147,26 +148,26 @@ int main(int argc, char **argv) {
continue;
}
if(strcmp(argv[fileArg], "-f") == 0) {
if (strcmp(argv[fileArg], "-f") == 0) {
fileArg++;
if(fileArg == argc) {
if (fileArg == argc) {
PrintUsage();
exit(1);
} else {
if(!strcmp(argv[fileArg], "PVRTC")) {
if (!strcmp(argv[fileArg], "PVRTC")) {
format = FasTC::eCompressionFormat_PVRTC4;
} else if(!strcmp(argv[fileArg], "PVRTCLib")) {
} else if (!strcmp(argv[fileArg], "PVRTCLib")) {
format = FasTC::eCompressionFormat_PVRTC4;
bUsePVRTexLib = true;
} else if(!strcmp(argv[fileArg], "BPTCLib")) {
} else if (!strcmp(argv[fileArg], "BPTCLib")) {
format = FasTC::eCompressionFormat_BPTC;
bUseNVTT = true;
} else if(!strcmp(argv[fileArg], "ETC1")) {
} else if (!strcmp(argv[fileArg], "ETC1")) {
format = FasTC::eCompressionFormat_ETC1;
} else if(!strcmp(argv[fileArg], "DXT1")) {
} else if (!strcmp(argv[fileArg], "DXT1")) {
format = FasTC::eCompressionFormat_DXT1;
} else if(!strcmp(argv[fileArg], "DXT5")) {
} else if (!strcmp(argv[fileArg], "DXT5")) {
format = FasTC::eCompressionFormat_DXT5;
}
}
@ -176,10 +177,10 @@ int main(int argc, char **argv) {
continue;
}
if(strcmp(argv[fileArg], "-d") == 0) {
if (strcmp(argv[fileArg], "-d") == 0) {
fileArg++;
if(fileArg == argc) {
if (fileArg == argc) {
PrintUsage();
exit(1);
} else {
@ -193,38 +194,38 @@ int main(int argc, char **argv) {
continue;
}
if(strcmp(argv[fileArg], "-nd") == 0) {
if (strcmp(argv[fileArg], "-nd") == 0) {
fileArg++;
bNoDecompress = true;
bDecompress = false;
knowArg = true;
continue;
}
if(strcmp(argv[fileArg], "-l") == 0) {
if (strcmp(argv[fileArg], "-l") == 0) {
fileArg++;
bSaveLog = true;
knowArg = true;
continue;
}
if(strcmp(argv[fileArg], "-v") == 0) {
if (strcmp(argv[fileArg], "-v") == 0) {
fileArg++;
bVerbose = true;
knowArg = true;
continue;
}
if(strcmp(argv[fileArg], "-simd") == 0) {
if (strcmp(argv[fileArg], "-simd") == 0) {
fileArg++;
bUseSIMD = true;
knowArg = true;
continue;
}
if(strcmp(argv[fileArg], "-t") == 0) {
if (strcmp(argv[fileArg], "-t") == 0) {
fileArg++;
if(fileArg == argc || (numThreads = atoi(argv[fileArg])) < 1) {
if (fileArg == argc || (numThreads = atoi(argv[fileArg])) < 1) {
PrintUsage();
exit(1);
}
@ -234,10 +235,10 @@ int main(int argc, char **argv) {
continue;
}
if(strcmp(argv[fileArg], "-q") == 0) {
if (strcmp(argv[fileArg], "-q") == 0) {
fileArg++;
if(fileArg == argc || (quality = atoi(argv[fileArg])) < 0) {
if (fileArg == argc || (quality = atoi(argv[fileArg])) < 0) {
PrintUsage();
exit(1);
}
@ -247,10 +248,10 @@ int main(int argc, char **argv) {
continue;
}
if(strcmp(argv[fileArg], "-j") == 0) {
if (strcmp(argv[fileArg], "-j") == 0) {
fileArg++;
if(fileArg == argc || (numJobs = atoi(argv[fileArg])) < 0) {
if (fileArg == argc || (numJobs = atoi(argv[fileArg])) < 0) {
PrintUsage();
exit(1);
}
@ -260,16 +261,16 @@ int main(int argc, char **argv) {
continue;
}
if(strcmp(argv[fileArg], "-a") == 0) {
if (strcmp(argv[fileArg], "-a") == 0) {
fileArg++;
bUseAtomics = true;
knowArg = true;
continue;
}
} while(knowArg && fileArg < argc);
} while (knowArg && fileArg < argc);
if(fileArg == argc) {
if (fileArg == argc) {
PrintUsage();
exit(1);
}
@ -277,15 +278,14 @@ int main(int argc, char **argv) {
char basename[256];
ExtractBasename(argv[fileArg], basename, 256);
ImageFile file (argv[fileArg]);
if(!file.Load()) {
fprintf(stderr, "Error loading file: %s\n", argv[fileArg]);
ImageFile file(argv[fileArg]);
if (!file.Load()) {
return 1;
}
FasTC::Image<> img(*file.GetImage());
if(bVerbose) {
if (bVerbose) {
fprintf(stdout, "Entropy: %.5f\n", img.ComputeEntropy());
fprintf(stdout, "Mean Local Entropy: %.5f\n", img.ComputeMeanLocalEntropy());
}
@ -293,12 +293,12 @@ int main(int argc, char **argv) {
std::ofstream logFile;
ThreadSafeStreambuf streamBuf(logFile);
std::ostream logStream(&streamBuf);
if(bSaveLog) {
if (bSaveLog) {
char logname[256];
sprintf(logname, "%s.log", basename);
logFile.open(logname);
}
SCompressionSettings settings;
settings.format = format;
settings.bUseSIMD = bUseSIMD;
@ -309,36 +309,40 @@ int main(int argc, char **argv) {
settings.iJobSize = numJobs;
settings.bUsePVRTexLib = bUsePVRTexLib;
settings.bUseNVTT = bUseNVTT;
if(bSaveLog) {
if (bSaveLog) {
settings.logStream = &logStream;
} else {
settings.logStream = NULL;
}
CompressedImage *ci = CompressImage(&img, settings);
if(NULL == ci) {
fprintf(stderr, "Error compressing image!\n");
if (NULL == ci) {
return 1;
}
double PSNR = img.ComputePSNR(ci);
if(PSNR > 0.0) {
fprintf(stdout, "PSNR: %.3f\n", PSNR);
}
else {
fprintf(stderr, "Error computing PSNR\n");
}
if (ci->GetWidth() != img.GetWidth() ||
ci->GetHeight() != img.GetHeight()) {
fprintf(stderr, "Cannot compute image metrics: compressed and uncompressed dimensions differ.\n");
} else {
double PSNR = img.ComputePSNR(ci);
if(PSNR > 0.0) {
fprintf(stdout, "PSNR: %.3f\n", PSNR);
}
else {
fprintf(stderr, "Error computing PSNR\n");
}
if(bVerbose) {
double SSIM = img.ComputeSSIM(ci);
if(SSIM > 0.0) {
fprintf(stdout, "SSIM: %.9f\n", SSIM);
} else {
fprintf(stderr, "Error computing SSIM\n");
if(bVerbose) {
double SSIM = img.ComputeSSIM(ci);
if(SSIM > 0.0) {
fprintf(stdout, "SSIM: %.9f\n", SSIM);
} else {
fprintf(stderr, "Error computing SSIM\n");
}
}
}
if(!bNoDecompress) {
if(bDecompress) {
if(decompressedOutput[0] != '\0') {
memcpy(basename, decompressedOutput, 256);
} else if(format == FasTC::eCompressionFormat_BPTC) {

View File

@ -45,16 +45,16 @@
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <iostream>
#include <string.h>
#include "ETCCompressor.h"
#include "DXTCompressor.h"
#include "BPTCCompressor.h"
#include "CompressionFormat.h"
#include "CompressionFuncs.h"
#include "Image.h"
#include "DXTCompressor.h"
#include "ETCCompressor.h"
#include "ImageFile.h"
#include "Pixel.h"
#include "PVRTCCompressor.h"
@ -188,7 +188,10 @@ static double CompressImageInSerial(
const SCompressionSettings &settings
) {
CompressionFunc f = ChooseFuncFromSettings(settings);
CompressionFuncWithStats fStats = ChooseFuncFromSettingsWithStats(settings);
CompressionFuncWithStats fStats = NULL;
if (settings.logStream) {
fStats = ChooseFuncFromSettingsWithStats(settings);
}
double cmpTimeTotal = 0.0;
@ -392,30 +395,51 @@ CompressedImage *CompressImage(
) {
if(!img) return NULL;
const uint32 w = img->GetWidth();
const uint32 h = img->GetHeight();
uint32 width = img->GetWidth();
uint32 height = img->GetHeight();
assert(width > 0);
assert(height > 0);
// Make sure that the width and height of the image is a multiple of
// the block size of the format
uint32 blockDims[2];
FasTC::GetBlockDimensions(settings.format, blockDims);
if ((width % blockDims[0]) != 0 || (height % blockDims[1]) != 0) {
ReportError("WARNING - Image size is not a multiple of block size. Padding with zeros...");
uint32 newWidth = ((width + (blockDims[0] - 1)) / blockDims[0]) * blockDims[0];
uint32 newHeight = ((height + (blockDims[1] - 1)) / blockDims[1]) * blockDims[1];
assert(newWidth > width || newHeight > height);
assert(newWidth % blockDims[0] == 0);
assert(newHeight % blockDims[1] == 0);
width = newWidth;
height = newHeight;
}
uint32 dataSz = width * height * 4;
uint32 *data = new uint32[dataSz / 4];
memset(data, 0, dataSz);
CompressedImage *outImg = NULL;
const unsigned int dataSz = w * h * 4;
uint32 *data = new uint32[dataSz / 4];
assert(dataSz > 0);
// Allocate data based on the compression method
uint32 cmpDataSz = CompressedImage::GetCompressedSize(dataSz, settings.format);
// Make sure that we have RGBA data...
img->ComputePixels();
const PixelType *pixels = img->GetPixels();
for(uint32 i = 0; i < img->GetNumPixels(); i++) {
data[i] = pixels[i].Pack();
for(uint32 j = 0; j < img->GetHeight(); j++) {
for(uint32 i = 0; i < img->GetWidth(); i++) {
data[j * width + i] = (*img)(i, j).Pack();
}
}
unsigned char *cmpData = new unsigned char[cmpDataSz];
CompressImageData(reinterpret_cast<uint8 *>(data), w, h, cmpData, cmpDataSz, settings);
uint8 *dataPtr = reinterpret_cast<uint8 *>(data);
if (CompressImageData(dataPtr, width, height, cmpData, cmpDataSz, settings)) {
outImg = new CompressedImage(width, height, settings.format, cmpData);
}
outImg = new CompressedImage(w, h, settings.format, cmpData);
delete [] data;
delete [] cmpData;
return outImg;
@ -433,7 +457,7 @@ bool CompressImageData(
uint8 *compressedData,
const uint32 cmpDataSz,
const SCompressionSettings &settings
) {
) {
uint32 dataSz = width * height * 4;
@ -471,6 +495,19 @@ bool CompressImageData(
}
}
uint32 blockDims[2];
FasTC::GetBlockDimensions(settings.format, blockDims);
if ((width % blockDims[0]) != 0 || (height % blockDims[1]) != 0) {
ReportError("ERROR - CompressImageData: width or height is not multiple of block dimension");
return false;
} else if (settings.format == FasTC::eCompressionFormat_PVRTC4 &&
((width & (width - 1)) != 0 ||
(height & (height - 1)) != 0 ||
width != height)) {
ReportError("ERROR - CompressImageData: PVRTC4 images must be square and power-of-two.");
return false;
}
// Allocate data based on the compression method
uint32 compressedDataSzNeeded =
CompressedImage::GetCompressedSize(dataSz, settings.format);

View File

@ -85,8 +85,8 @@ unsigned int ImageLoader::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
return 0;
}
uint32 prec;
const uint8 *data;
uint32 prec = 0;
const uint8 *data = NULL;
switch(ch) {
case 0:
@ -135,7 +135,7 @@ unsigned int ImageLoader::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
}
}
return ret;
return static_cast<unsigned int>(ret);
}
else if(prec > 8) {
const int32 toShift = prec - 8;
@ -164,10 +164,10 @@ bool ImageLoader::LoadFromPixelBuffer(const uint32 *data, bool flipY) {
if(flipY)
idx = (m_Height - j - 1)*m_Height + i;
uint32 pixel = data[idx];
m_RedData[pIdx] = pixel & 0xFF;
m_GreenData[pIdx] = (pixel >> 8) & 0xFF;
m_BlueData[pIdx] = (pixel >> 16) & 0xFF;
m_AlphaData[pIdx] = (pixel >> 24) & 0xFF;
m_RedData[pIdx] = static_cast<uint8>(pixel & 0xFF);
m_GreenData[pIdx] = static_cast<uint8>((pixel >> 8) & 0xFF);
m_BlueData[pIdx] = static_cast<uint8>((pixel >> 16) & 0xFF);
m_AlphaData[pIdx] = static_cast<uint8>((pixel >> 24) & 0xFF);
}
}
@ -189,24 +189,13 @@ FasTC::Image<> *ImageLoader::LoadImage() {
m_Width = GetWidth();
m_Height = GetHeight();
// Populate buffer in block stream order... make
// sure that width and height are aligned to multiples of four.
const unsigned int aw = ((m_Width + 3) >> 2) << 2;
const unsigned int ah = ((m_Height + 3) >> 2) << 2;
// Create RGBA buffer
const unsigned int dataSz = 4 * aw * ah;
const unsigned int dataSz = 4 * GetWidth() * GetHeight();
m_PixelData = new unsigned char[dataSz];
#ifndef NDEBUG
if(aw != m_Width || ah != m_Height)
fprintf(stderr, "Warning: Image dimension not multiple of four. "
"Space will be filled with black.\n");
#endif
int byteIdx = 0;
for(uint32 j = 0; j < ah; j++) {
for(uint32 i = 0; i < aw; i++) {
for(uint32 j = 0; j < GetHeight(); j++) {
for(uint32 i = 0; i < GetWidth(); i++) {
unsigned int redVal = GetChannelForPixel(i, j, 0);
if(redVal == INT_MAX) {
@ -239,22 +228,19 @@ FasTC::Image<> *ImageLoader::LoadImage() {
}
// Red channel
m_PixelData[byteIdx++] = redVal & 0xFF;
m_PixelData[byteIdx++] = static_cast<uint8>(redVal & 0xFF);
// Green channel
m_PixelData[byteIdx++] = greenVal & 0xFF;
m_PixelData[byteIdx++] = static_cast<uint8>(greenVal & 0xFF);
// Blue channel
m_PixelData[byteIdx++] = blueVal & 0xFF;
m_PixelData[byteIdx++] = static_cast<uint8>(blueVal & 0xFF);
// Alpha channel
m_PixelData[byteIdx++] = alphaVal & 0xFF;
m_PixelData[byteIdx++] = static_cast<uint8>(alphaVal & 0xFF);
}
}
m_Width = aw;
m_Height = ah;
uint32 *pixels = reinterpret_cast<uint32 *>(m_PixelData);
return new FasTC::Image<>(m_Width, m_Height, pixels);
}