mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-24 07:05:39 +01:00
Remove a bunch of code that assumes that we get our pixel data in block stream order...
This commit is contained in:
parent
f67bcc400b
commit
8e76d149ba
@ -503,19 +503,6 @@ static inline uint32 fastrand() {
|
|||||||
return (g_seed>>16) & RAND_MAX;
|
return (g_seed>>16) & RAND_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const int kNumStepDirections = 8;
|
|
||||||
static const RGBADir kStepDirections[kNumStepDirections] = {
|
|
||||||
// For pBit changes, we have 8 possible directions.
|
|
||||||
RGBADir(RGBAVector(1.0f, 1.0f, 1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(-1.0f, 1.0f, 1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(1.0f, -1.0f, 1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(-1.0f, -1.0f, 1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(1.0f, 1.0f, -1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(-1.0f, 1.0f, -1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(1.0f, -1.0f, -1.0f, 0.0f)),
|
|
||||||
RGBADir(RGBAVector(-1.0f, -1.0f, -1.0f, 0.0f))
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ChangePointForDirWithoutPbitChange(
|
static void ChangePointForDirWithoutPbitChange(
|
||||||
RGBAVector &v, uint32 dir, const float step[kNumColorChannels]
|
RGBAVector &v, uint32 dir, const float step[kNumColorChannels]
|
||||||
) {
|
) {
|
||||||
@ -1641,26 +1628,33 @@ namespace BC7C {
|
|||||||
// large enough to store the compressed image. This implementation has an 4:1
|
// large enough to store the compressed image. This implementation has an 4:1
|
||||||
// compression ratio.
|
// compression ratio.
|
||||||
void Compress(const CompressionJob &cj) {
|
void Compress(const CompressionJob &cj) {
|
||||||
const unsigned char *inBuf = cj.inBuf;
|
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.inBuf);
|
||||||
unsigned char *outBuf = cj.outBuf;
|
unsigned char *outBuf = cj.outBuf;
|
||||||
for(uint32 j = 0; j < cj.height; j += 4) {
|
for(uint32 j = 0; j < cj.height; j += 4) {
|
||||||
for(uint32 i = 0; i < cj.width; i += 4) {
|
for(uint32 i = 0; i < cj.width; i += 4) {
|
||||||
|
|
||||||
CompressBC7Block((const uint32 *)inBuf, outBuf);
|
uint32 block[16];
|
||||||
|
memcpy(block, inPixels + j*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
memcpy(block + 4, inPixels + (j+1)*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
memcpy(block + 8, inPixels + (j+2)*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
memcpy(block + 12, inPixels + (j+3)*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
|
||||||
|
CompressBC7Block(block, outBuf);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
uint8 *block = reinterpret_cast<uint8 *>(outBuf);
|
const uint8 *inBlock = reinterpret_cast<const uint8 *>(block);
|
||||||
|
const uint8 *cmpblock = reinterpret_cast<const uint8 *>(outBuf);
|
||||||
uint32 unComp[16];
|
uint32 unComp[16];
|
||||||
DecompressBC7Block(block, unComp);
|
DecompressBC7Block(cmpblock, unComp);
|
||||||
uint8* unCompData = reinterpret_cast<uint8 *>(unComp);
|
const uint8* unCompData = reinterpret_cast<const uint8 *>(unComp);
|
||||||
|
|
||||||
double diffSum = 0.0;
|
double diffSum = 0.0;
|
||||||
for(int k = 0; k < 64; k+=4) {
|
for(int k = 0; k < 64; k+=4) {
|
||||||
double rdiff = sad(unCompData[k], inBuf[k]);
|
double rdiff = sad(unCompData[k], inBlock[k]);
|
||||||
double gdiff = sad(unCompData[k+1], inBuf[k+1]);
|
double gdiff = sad(unCompData[k+1], inBlock[k+1]);
|
||||||
double bdiff = sad(unCompData[k+2], inBuf[k+2]);
|
double bdiff = sad(unCompData[k+2], inBlock[k+2]);
|
||||||
double adiff = sad(unCompData[k+3], inBuf[k+3]);
|
double adiff = sad(unCompData[k+3], inBlock[k+3]);
|
||||||
const double asrc = static_cast<double>(inBuf[k+3]);
|
const double asrc = static_cast<double>(inBlock[k+3]);
|
||||||
const double adst = static_cast<double>(unCompData[k+3]);
|
const double adst = static_cast<double>(unCompData[k+3]);
|
||||||
double avga = ((asrc + adst)*0.5)/255.0;
|
double avga = ((asrc + adst)*0.5)/255.0;
|
||||||
diffSum += (rdiff + gdiff + bdiff + adiff) * avga;
|
diffSum += (rdiff + gdiff + bdiff + adiff) * avga;
|
||||||
@ -1673,7 +1667,6 @@ namespace BC7C {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
outBuf += 16;
|
outBuf += 16;
|
||||||
inBuf += 64;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1730,29 +1723,35 @@ namespace BC7C {
|
|||||||
#endif // HAS_ATOMICS
|
#endif // HAS_ATOMICS
|
||||||
|
|
||||||
void CompressWithStats(const CompressionJob &cj, std::ostream *logStream) {
|
void CompressWithStats(const CompressionJob &cj, std::ostream *logStream) {
|
||||||
const unsigned char *inBuf = cj.inBuf;
|
const uint32 *inPixels = reinterpret_cast<const uint32 *>(cj.inBuf);
|
||||||
unsigned char *outBuf = cj.outBuf;
|
unsigned char *outBuf = cj.outBuf;
|
||||||
|
|
||||||
for(uint32 j = 0; j < cj.height; j += 4) {
|
for(uint32 j = 0; j < cj.height; j += 4) {
|
||||||
for(uint32 i = 0; i < cj.width; i += 4) {
|
for(uint32 i = 0; i < cj.width; i += 4) {
|
||||||
|
|
||||||
const uint32 *pixelBuf = reinterpret_cast<const uint32 *>(inBuf);
|
uint32 block[16];
|
||||||
|
memcpy(block, inPixels + j*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
memcpy(block + 4, inPixels + (j+1)*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
memcpy(block + 8, inPixels + (j+2)*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
memcpy(block + 12, inPixels + (j+3)*cj.width + i, 4 * sizeof(uint32));
|
||||||
|
|
||||||
if(logStream) {
|
if(logStream) {
|
||||||
uint64 blockIdx = reinterpret_cast<uint64>(pixelBuf);
|
uint64 blockIdx = reinterpret_cast<uint64>(inPixels + j*cj.width + i);
|
||||||
CompressBC7Block(pixelBuf, outBuf, BlockLogger(blockIdx, *logStream));
|
CompressBC7Block(block, outBuf, BlockLogger(blockIdx, *logStream));
|
||||||
} else {
|
} else {
|
||||||
CompressBC7Block(pixelBuf, outBuf);
|
CompressBC7Block(block, outBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
uint8 *block = outBuf;
|
const uint8 *inBlock = reinterpret_cast<const uint8 *>(block);
|
||||||
|
const uint8 *cmpData = outBuf;
|
||||||
uint32 unComp[16];
|
uint32 unComp[16];
|
||||||
DecompressBC7Block(block, unComp);
|
DecompressBC7Block(cmpData, unComp);
|
||||||
uint8* unCompData = reinterpret_cast<uint8 *>(unComp);
|
const uint8* unCompData = reinterpret_cast<uint8 *>(unComp);
|
||||||
|
|
||||||
int diffSum = 0;
|
int diffSum = 0;
|
||||||
for(int i = 0; i < 64; i++) {
|
for(int i = 0; i < 64; i++) {
|
||||||
diffSum += sad(unCompData[i], inBuf[i]);
|
diffSum += sad(unCompData[i], inBlock[i]);
|
||||||
}
|
}
|
||||||
double blockError = static_cast<double>(diffSum) / 64.0;
|
double blockError = static_cast<double>(diffSum) / 64.0;
|
||||||
if(blockError > 50.0) {
|
if(blockError > 50.0) {
|
||||||
@ -1762,7 +1761,6 @@ namespace BC7C {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
outBuf += 16;
|
outBuf += 16;
|
||||||
inBuf += 64;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2759,17 +2757,21 @@ namespace BC7C {
|
|||||||
// Convert the image from a BC7 buffer to a RGBA8 buffer
|
// Convert the image from a BC7 buffer to a RGBA8 buffer
|
||||||
void Decompress(const DecompressionJob &dj) {
|
void Decompress(const DecompressionJob &dj) {
|
||||||
|
|
||||||
unsigned char *outBuf = dj.outBuf;
|
const uint8 *inBuf = dj.inBuf;
|
||||||
unsigned int blockIdx = 0;
|
uint32 *outBuf = reinterpret_cast<uint32 *>(dj.outBuf);
|
||||||
|
|
||||||
for(unsigned int j = 0; j < dj.height; j += 4) {
|
for(unsigned int j = 0; j < dj.height; j += 4) {
|
||||||
for(unsigned int i = 0; i < dj.width; i += 4) {
|
for(unsigned int i = 0; i < dj.width; i += 4) {
|
||||||
|
|
||||||
uint32 pixels[16];
|
uint32 pixels[16];
|
||||||
DecompressBC7Block(dj.inBuf + (16*(blockIdx++)), pixels);
|
DecompressBC7Block(inBuf, pixels);
|
||||||
|
|
||||||
memcpy(outBuf, pixels, sizeof(pixels));
|
memcpy(outBuf + j*dj.width + i, pixels, 4 * sizeof(pixels[0]));
|
||||||
outBuf += 64;
|
memcpy(outBuf + (j+1)*dj.width + i, pixels+4, 4 * sizeof(pixels[0]));
|
||||||
|
memcpy(outBuf + (j+2)*dj.width + i, pixels+8, 4 * sizeof(pixels[0]));
|
||||||
|
memcpy(outBuf + (j+3)*dj.width + i, pixels+12, 4 * sizeof(pixels[0]));
|
||||||
|
|
||||||
|
inBuf += 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,9 @@ namespace FasTC {
|
|||||||
Image() : m_Width(0), m_Height(0), m_Pixels(0) { }
|
Image() : m_Width(0), m_Height(0), m_Pixels(0) { }
|
||||||
Image(uint32 width, uint32 height);
|
Image(uint32 width, uint32 height);
|
||||||
Image(uint32 width, uint32 height,
|
Image(uint32 width, uint32 height,
|
||||||
const PixelType *pixels,
|
const PixelType *pixels);
|
||||||
bool bBlockStreamOrder = false);
|
|
||||||
Image(uint32 width, uint32 height,
|
Image(uint32 width, uint32 height,
|
||||||
const uint32 *pixels,
|
const uint32 *pixels);
|
||||||
bool bBlockStreamOrder = false);
|
|
||||||
Image(const Image<PixelType> &);
|
Image(const Image<PixelType> &);
|
||||||
Image &operator=(const Image<PixelType> &);
|
Image &operator=(const Image<PixelType> &);
|
||||||
virtual ~Image();
|
virtual ~Image();
|
||||||
@ -87,15 +85,6 @@ namespace FasTC {
|
|||||||
uint32 GetHeight() const { return m_Height; }
|
uint32 GetHeight() const { return m_Height; }
|
||||||
uint32 GetNumPixels() const { return GetWidth() * GetHeight(); }
|
uint32 GetNumPixels() const { return GetWidth() * GetHeight(); }
|
||||||
|
|
||||||
void SetBlockStreamOrder(bool flag) {
|
|
||||||
if(flag) {
|
|
||||||
ConvertToBlockStreamOrder();
|
|
||||||
} else {
|
|
||||||
ConvertFromBlockStreamOrder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool GetBlockStreamOrder() const { return m_bBlockStreamOrder; }
|
|
||||||
|
|
||||||
template<typename OtherPixelType>
|
template<typename OtherPixelType>
|
||||||
void ConvertTo(Image<OtherPixelType> &other) const {
|
void ConvertTo(Image<OtherPixelType> &other) const {
|
||||||
for(uint32 j = 0; j < other.GetWidth(); j++) {
|
for(uint32 j = 0; j < other.GetWidth(); j++) {
|
||||||
@ -127,16 +116,11 @@ namespace FasTC {
|
|||||||
uint32 m_Width;
|
uint32 m_Width;
|
||||||
uint32 m_Height;
|
uint32 m_Height;
|
||||||
|
|
||||||
bool m_bBlockStreamOrder;
|
|
||||||
|
|
||||||
PixelType *m_Pixels;
|
PixelType *m_Pixels;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void SetImageData(uint32 width, uint32 height, PixelType *data);
|
void SetImageData(uint32 width, uint32 height, PixelType *data);
|
||||||
|
|
||||||
void ConvertToBlockStreamOrder();
|
|
||||||
void ConvertFromBlockStreamOrder();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void GenerateGaussianKernel(Image<IPixel> &out, uint32 size, float sigma);
|
extern void GenerateGaussianKernel(Image<IPixel> &out, uint32 size, float sigma);
|
||||||
|
@ -70,17 +70,14 @@ template<typename PixelType>
|
|||||||
Image<PixelType>::Image(uint32 width, uint32 height)
|
Image<PixelType>::Image(uint32 width, uint32 height)
|
||||||
: m_Width(width)
|
: m_Width(width)
|
||||||
, m_Height(height)
|
, m_Height(height)
|
||||||
, m_bBlockStreamOrder(false)
|
|
||||||
, m_Pixels(new PixelType[GetNumPixels()])
|
, m_Pixels(new PixelType[GetNumPixels()])
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
template<typename PixelType>
|
template<typename PixelType>
|
||||||
Image<PixelType>::Image(uint32 width, uint32 height,
|
Image<PixelType>::Image(uint32 width, uint32 height,
|
||||||
const PixelType *pixels,
|
const PixelType *pixels)
|
||||||
bool bBlockStreamOrder)
|
|
||||||
: m_Width(width)
|
: m_Width(width)
|
||||||
, m_Height(height)
|
, m_Height(height)
|
||||||
, m_bBlockStreamOrder(false)
|
|
||||||
{
|
{
|
||||||
if(pixels) {
|
if(pixels) {
|
||||||
m_Pixels = new PixelType[GetNumPixels()];
|
m_Pixels = new PixelType[GetNumPixels()];
|
||||||
@ -94,7 +91,6 @@ template<typename PixelType>
|
|||||||
Image<PixelType>::Image(const Image<PixelType> &other)
|
Image<PixelType>::Image(const Image<PixelType> &other)
|
||||||
: m_Width(other.m_Width)
|
: m_Width(other.m_Width)
|
||||||
, m_Height(other.m_Height)
|
, m_Height(other.m_Height)
|
||||||
, m_bBlockStreamOrder(other.GetBlockStreamOrder())
|
|
||||||
, m_Pixels(new PixelType[GetNumPixels()])
|
, m_Pixels(new PixelType[GetNumPixels()])
|
||||||
{
|
{
|
||||||
memcpy(m_Pixels, other.m_Pixels, GetNumPixels() * sizeof(PixelType));
|
memcpy(m_Pixels, other.m_Pixels, GetNumPixels() * sizeof(PixelType));
|
||||||
@ -112,10 +108,9 @@ bool Image<PixelType>::ReadPixels(const uint32 *rgba) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename PixelType>
|
template<typename PixelType>
|
||||||
Image<PixelType>::Image(uint32 width, uint32 height, const uint32 *pixels, bool bBlockStreamOrder)
|
Image<PixelType>::Image(uint32 width, uint32 height, const uint32 *pixels)
|
||||||
: m_Width(width)
|
: m_Width(width)
|
||||||
, m_Height(height)
|
, m_Height(height)
|
||||||
, m_bBlockStreamOrder(bBlockStreamOrder)
|
|
||||||
{
|
{
|
||||||
if(pixels) {
|
if(pixels) {
|
||||||
m_Pixels = new PixelType[GetNumPixels()];
|
m_Pixels = new PixelType[GetNumPixels()];
|
||||||
@ -138,7 +133,6 @@ Image<PixelType> &Image<PixelType>::operator=(const Image &other) {
|
|||||||
|
|
||||||
m_Width = other.m_Width;
|
m_Width = other.m_Width;
|
||||||
m_Height = other.m_Height;
|
m_Height = other.m_Height;
|
||||||
m_bBlockStreamOrder = other.GetBlockStreamOrder();
|
|
||||||
|
|
||||||
if(m_Pixels) {
|
if(m_Pixels) {
|
||||||
delete [] m_Pixels;
|
delete [] m_Pixels;
|
||||||
@ -467,59 +461,6 @@ double Image<PixelType>::ComputeEntropy() {
|
|||||||
return -ret;
|
return -ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// !FIXME! These won't work for non-RGBA8 data.
|
|
||||||
template<typename PixelType>
|
|
||||||
void Image<PixelType>::ConvertToBlockStreamOrder() {
|
|
||||||
if(m_bBlockStreamOrder || !m_Pixels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PixelType *newPixelData = new PixelType[GetWidth() * GetHeight()];
|
|
||||||
for(uint32 j = 0; j < GetHeight(); j+=4) {
|
|
||||||
for(uint32 i = 0; i < GetWidth(); i+=4) {
|
|
||||||
uint32 blockX = i / 4;
|
|
||||||
uint32 blockY = j / 4;
|
|
||||||
uint32 blockIdx = blockY * (GetWidth() / 4) + blockX;
|
|
||||||
|
|
||||||
uint32 offset = blockIdx * 4 * 4;
|
|
||||||
for(uint32 t = 0; t < 16; t++) {
|
|
||||||
uint32 x = i + t % 4;
|
|
||||||
uint32 y = j + t / 4;
|
|
||||||
newPixelData[offset + t] = m_Pixels[y*GetWidth() + x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete m_Pixels;
|
|
||||||
m_Pixels = newPixelData;
|
|
||||||
m_bBlockStreamOrder = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename PixelType>
|
|
||||||
void Image<PixelType>::ConvertFromBlockStreamOrder() {
|
|
||||||
if(!m_bBlockStreamOrder || !m_Pixels)
|
|
||||||
return;
|
|
||||||
|
|
||||||
PixelType *newPixelData = new PixelType[GetWidth() * GetHeight()];
|
|
||||||
for(uint32 j = 0; j < GetHeight(); j+=4) {
|
|
||||||
for(uint32 i = 0; i < GetWidth(); i+=4) {
|
|
||||||
uint32 blockX = i / 4;
|
|
||||||
uint32 blockY = j / 4;
|
|
||||||
uint32 blockIdx = blockY * (GetWidth() / 4) + blockX;
|
|
||||||
|
|
||||||
uint32 offset = blockIdx * 4 * 4;
|
|
||||||
for(uint32 t = 0; t < 16; t++) {
|
|
||||||
uint32 x = i + t % 4;
|
|
||||||
uint32 y = j + t / 4;
|
|
||||||
newPixelData[y*GetWidth() + x] = m_Pixels[offset + t];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete m_Pixels;
|
|
||||||
m_Pixels = newPixelData;
|
|
||||||
m_bBlockStreamOrder = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename PixelType>
|
template<typename PixelType>
|
||||||
void Image<PixelType>::SetImageData(uint32 width, uint32 height, PixelType *data) {
|
void Image<PixelType>::SetImageData(uint32 width, uint32 height, PixelType *data) {
|
||||||
if(m_Pixels) {
|
if(m_Pixels) {
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
void PrintUsage() {
|
void PrintUsage() {
|
||||||
fprintf(stderr, "Usage: tc [OPTIONS] imagefile\n");
|
fprintf(stderr, "Usage: tc [OPTIONS] imagefile\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
fprintf(stderr, "\t-v\t\tVerbose mode: prints out Entropy, Mean Local Entropy, and MSSIM");
|
||||||
fprintf(stderr, "\t-f\t\tFormat to use. Either \"BPTC\", \"ETC1\", \"DXT1\", \"DXT5\", or \"PVRTC\". Default: BPTC\n");
|
fprintf(stderr, "\t-f\t\tFormat to use. Either \"BPTC\", \"ETC1\", \"DXT1\", \"DXT5\", or \"PVRTC\". Default: BPTC\n");
|
||||||
fprintf(stderr, "\t-l\t\tSave an output log.\n");
|
fprintf(stderr, "\t-l\t\tSave an output log.\n");
|
||||||
fprintf(stderr, "\t-q <quality>\tSet compression quality level. Default: 50\n");
|
fprintf(stderr, "\t-q <quality>\tSet compression quality level. Default: 50\n");
|
||||||
@ -102,6 +103,7 @@ int main(int argc, char **argv) {
|
|||||||
bool bSaveLog = false;
|
bool bSaveLog = false;
|
||||||
bool bUseAtomics = false;
|
bool bUseAtomics = false;
|
||||||
bool bUsePVRTexLib = false;
|
bool bUsePVRTexLib = false;
|
||||||
|
bool bVerbose = false;
|
||||||
ECompressionFormat format = eCompressionFormat_BPTC;
|
ECompressionFormat format = eCompressionFormat_BPTC;
|
||||||
|
|
||||||
bool knowArg = false;
|
bool knowArg = false;
|
||||||
@ -154,6 +156,13 @@ int main(int argc, char **argv) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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++;
|
fileArg++;
|
||||||
bUseSIMD = true;
|
bUseSIMD = true;
|
||||||
@ -224,12 +233,11 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FasTC::Image<> img(*file.GetImage());
|
FasTC::Image<> img(*file.GetImage());
|
||||||
if(format != eCompressionFormat_BPTC) {
|
|
||||||
img.SetBlockStreamOrder(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "Entropy: %.5f\n", img.ComputeEntropy());
|
if(bVerbose) {
|
||||||
fprintf(stdout, "Mean Local Entropy: %.5f\n", img.ComputeMeanLocalEntropy());
|
fprintf(stdout, "Entropy: %.5f\n", img.ComputeEntropy());
|
||||||
|
fprintf(stdout, "Mean Local Entropy: %.5f\n", img.ComputeMeanLocalEntropy());
|
||||||
|
}
|
||||||
|
|
||||||
std::ofstream logFile;
|
std::ofstream logFile;
|
||||||
ThreadSafeStreambuf streamBuf(logFile);
|
ThreadSafeStreambuf streamBuf(logFile);
|
||||||
@ -269,11 +277,13 @@ int main(int argc, char **argv) {
|
|||||||
fprintf(stderr, "Error computing PSNR\n");
|
fprintf(stderr, "Error computing PSNR\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
double SSIM = img.ComputeSSIM(ci);
|
if(bVerbose) {
|
||||||
if(SSIM > 0.0) {
|
double SSIM = img.ComputeSSIM(ci);
|
||||||
fprintf(stdout, "SSIM: %.9f\n", SSIM);
|
if(SSIM > 0.0) {
|
||||||
} else {
|
fprintf(stdout, "SSIM: %.9f\n", SSIM);
|
||||||
fprintf(stderr, "Error computing MSSIM\n");
|
} else {
|
||||||
|
fprintf(stderr, "Error computing SSIM\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(format == eCompressionFormat_BPTC) {
|
if(format == eCompressionFormat_BPTC) {
|
||||||
|
@ -85,9 +85,6 @@ int main(int argc, char **argv) {
|
|||||||
FasTC::Image<> img1(*img1f.GetImage());
|
FasTC::Image<> img1(*img1f.GetImage());
|
||||||
FasTC::Image<> img2(*img2f.GetImage());
|
FasTC::Image<> img2(*img2f.GetImage());
|
||||||
|
|
||||||
img1.SetBlockStreamOrder(false);
|
|
||||||
img2.SetBlockStreamOrder(false);
|
|
||||||
|
|
||||||
double PSNR = img1.ComputePSNR(&img2);
|
double PSNR = img1.ComputePSNR(&img2);
|
||||||
if(PSNR > 0.0) {
|
if(PSNR > 0.0) {
|
||||||
fprintf(stdout, "PSNR: %.3f\n", PSNR);
|
fprintf(stdout, "PSNR: %.3f\n", PSNR);
|
||||||
|
@ -74,9 +74,7 @@ CompressedImage::CompressedImage(
|
|||||||
const ECompressionFormat format,
|
const ECompressionFormat format,
|
||||||
const unsigned char *data
|
const unsigned char *data
|
||||||
)
|
)
|
||||||
: FasTC::Image<>(width, height,
|
: FasTC::Image<>(width, height, reinterpret_cast<uint32 *>(NULL))
|
||||||
reinterpret_cast<uint32 *>(NULL),
|
|
||||||
format == eCompressionFormat_BPTC)
|
|
||||||
, m_Format(format)
|
, m_Format(format)
|
||||||
, m_CompressedData(0)
|
, m_CompressedData(0)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +207,7 @@ FasTC::Image<> *ImageFile::LoadImage(const unsigned char *rawImageData) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32 *pixels = reinterpret_cast<uint32 *>(pixelData);
|
uint32 *pixels = reinterpret_cast<uint32 *>(pixelData);
|
||||||
FasTC::Image<> *i = new FasTC::Image<>(loader->GetWidth(), loader->GetHeight(), pixels, true);
|
FasTC::Image<> *i = new FasTC::Image<>(loader->GetWidth(), loader->GetHeight(), pixels);
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
delete loader;
|
delete loader;
|
||||||
|
@ -167,60 +167,46 @@ bool ImageLoader::LoadImage() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
int byteIdx = 0;
|
int byteIdx = 0;
|
||||||
for(uint32 i = 0; i < ah; i+=4) {
|
for(uint32 j = 0; j < ah; j++) {
|
||||||
for(uint32 j = 0; j < aw; j+= 4) {
|
for(uint32 i = 0; i < aw; i++) {
|
||||||
|
|
||||||
// For each block, visit the pixels in sequential order
|
unsigned int redVal = GetChannelForPixel(i, j, 0);
|
||||||
for(uint32 y = i; y < i+4; y++) {
|
if(redVal == INT_MAX)
|
||||||
for(uint32 x = j; x < j+4; x++) {
|
return false;
|
||||||
|
|
||||||
if(y >= m_Height || x >= m_Width) {
|
unsigned int greenVal = redVal;
|
||||||
m_PixelData[byteIdx++] = 0; // r
|
unsigned int blueVal = redVal;
|
||||||
m_PixelData[byteIdx++] = 0; // g
|
|
||||||
m_PixelData[byteIdx++] = 0; // b
|
|
||||||
m_PixelData[byteIdx++] = 0; // a
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int redVal = GetChannelForPixel(x, y, 0);
|
if(GetGreenChannelPrecision() > 0) {
|
||||||
if(redVal == INT_MAX)
|
greenVal = GetChannelForPixel(i, j, 1);
|
||||||
return false;
|
if(greenVal == INT_MAX)
|
||||||
|
return false;
|
||||||
unsigned int greenVal = redVal;
|
|
||||||
unsigned int blueVal = redVal;
|
|
||||||
|
|
||||||
if(GetGreenChannelPrecision() > 0) {
|
|
||||||
greenVal = GetChannelForPixel(x, y, 1);
|
|
||||||
if(greenVal == INT_MAX)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(GetBlueChannelPrecision() > 0) {
|
|
||||||
blueVal = GetChannelForPixel(x, y, 2);
|
|
||||||
if(blueVal == INT_MAX)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int alphaVal = 0xFF;
|
|
||||||
if(GetAlphaChannelPrecision() > 0) {
|
|
||||||
alphaVal = GetChannelForPixel(x, y, 3);
|
|
||||||
if(alphaVal == INT_MAX)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Red channel
|
|
||||||
m_PixelData[byteIdx++] = redVal & 0xFF;
|
|
||||||
|
|
||||||
// Green channel
|
|
||||||
m_PixelData[byteIdx++] = greenVal & 0xFF;
|
|
||||||
|
|
||||||
// Blue channel
|
|
||||||
m_PixelData[byteIdx++] = blueVal & 0xFF;
|
|
||||||
|
|
||||||
// Alpha channel
|
|
||||||
m_PixelData[byteIdx++] = alphaVal & 0xFF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(GetBlueChannelPrecision() > 0) {
|
||||||
|
blueVal = GetChannelForPixel(i, j, 2);
|
||||||
|
if(blueVal == INT_MAX)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int alphaVal = 0xFF;
|
||||||
|
if(GetAlphaChannelPrecision() > 0) {
|
||||||
|
alphaVal = GetChannelForPixel(i, j, 3);
|
||||||
|
if(alphaVal == INT_MAX)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Red channel
|
||||||
|
m_PixelData[byteIdx++] = redVal & 0xFF;
|
||||||
|
|
||||||
|
// Green channel
|
||||||
|
m_PixelData[byteIdx++] = greenVal & 0xFF;
|
||||||
|
|
||||||
|
// Blue channel
|
||||||
|
m_PixelData[byteIdx++] = blueVal & 0xFF;
|
||||||
|
|
||||||
|
// Alpha channel
|
||||||
|
m_PixelData[byteIdx++] = alphaVal & 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,22 +45,5 @@
|
|||||||
#include "Pixel.h"
|
#include "Pixel.h"
|
||||||
|
|
||||||
uint32 ImageWriter::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
|
uint32 ImageWriter::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
|
||||||
|
return m_Pixels[y * GetWidth() + x].Component((ch+1) % 4);
|
||||||
// Assume pixels are in block stream order, hence we would need to first find
|
|
||||||
// the block that contains pixel (x, y) and then find the byte location for it.
|
|
||||||
|
|
||||||
const uint32 blocksPerRow = GetWidth() / 4;
|
|
||||||
const uint32 blockIdxX = x / 4;
|
|
||||||
const uint32 blockIdxY = y / 4;
|
|
||||||
const uint32 blockIdx = blockIdxY * blocksPerRow + blockIdxX;
|
|
||||||
|
|
||||||
// Now we find the offset in the block
|
|
||||||
const uint32 blockOffsetX = x % 4;
|
|
||||||
const uint32 blockOffsetY = y % 4;
|
|
||||||
const uint32 pixelOffset = blockOffsetY * 4 + blockOffsetX;
|
|
||||||
|
|
||||||
// There are 16 pixels per block...
|
|
||||||
uint32 dataOffset = blockIdx * 16 + pixelOffset;
|
|
||||||
|
|
||||||
return m_Pixels[dataOffset].Component((ch+1) % 4);
|
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,6 @@ public:
|
|||||||
|
|
||||||
ImageWriterPNG::ImageWriterPNG(FasTC::Image<> &im)
|
ImageWriterPNG::ImageWriterPNG(FasTC::Image<> &im)
|
||||||
: ImageWriter(im.GetWidth(), im.GetHeight(), im.GetPixels())
|
: ImageWriter(im.GetWidth(), im.GetHeight(), im.GetPixels())
|
||||||
, m_bBlockStreamOrder(im.GetBlockStreamOrder())
|
|
||||||
, m_StreamPosition(0)
|
, m_StreamPosition(0)
|
||||||
{
|
{
|
||||||
im.ComputePixels();
|
im.ComputePixels();
|
||||||
@ -132,13 +131,7 @@ bool ImageWriterPNG::WriteImage() {
|
|||||||
row_pointers[y] = row;
|
row_pointers[y] = row;
|
||||||
|
|
||||||
for (uint32 x = 0; x < m_Width; ++x) {
|
for (uint32 x = 0; x < m_Width; ++x) {
|
||||||
if(m_bBlockStreamOrder) {
|
reinterpret_cast<uint32 *>(row)[x] = m_Pixels[y * m_Width + x].Pack();
|
||||||
for(uint32 ch = 0; ch < 4; ch++) {
|
|
||||||
*row++ = GetChannelForPixel(x, y, ch);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
reinterpret_cast<uint32 *>(row)[x] = m_Pixels[y * m_Width + x].Pack();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ class ImageWriterPNG : public ImageWriter {
|
|||||||
|
|
||||||
virtual bool WriteImage();
|
virtual bool WriteImage();
|
||||||
private:
|
private:
|
||||||
bool m_bBlockStreamOrder;
|
|
||||||
uint32 m_StreamPosition;
|
uint32 m_StreamPosition;
|
||||||
friend class PNGStreamWriter;
|
friend class PNGStreamWriter;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user