Remove a bunch of code that assumes that we get our pixel data in block stream order...

This commit is contained in:
Pavel Krajcevski 2013-11-06 18:23:19 -05:00
parent f67bcc400b
commit 8e76d149ba
11 changed files with 105 additions and 212 deletions

View File

@ -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;
} }
} }
} }

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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);
} }

View File

@ -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();
}
} }
} }

View File

@ -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;
}; };