Merge branch 'master' into DecompressASTC

This commit is contained in:
Pavel Krajcevski 2014-03-12 13:29:17 -04:00
commit 0a4726bfe2
15 changed files with 194 additions and 84 deletions

16
.travis.yml Normal file
View file

@ -0,0 +1,16 @@
language: cpp
git:
submodules: false
compiler:
- gcc
- clang
before_script:
- mkdir build
- cd build
- cmake .. -DCMAKE_BUILD_TYPE=Release
script: make && make test
after_failure: if [ -d Testing ]; then cat Testing/Temporary/LastTest.log; fi

View file

@ -73,7 +73,7 @@ namespace FasTC {
// principal eigenvector. However, that may be due to
// poor initialization of the random vector, so rerandomize
// and try again.
const float newBlen = newB.Length();
const T newBlen = newB.Length();
if(newBlen < 1e-10) {
if(badEigenValue) {
eigVec = b;

View file

@ -94,7 +94,8 @@ namespace FasTC {
}
T LengthSq() const { return this->Dot(*this); }
T Length() const { return sqrt(LengthSq()); }
T Length() const { return static_cast<T>(
sqrt(static_cast<long double>(LengthSq())));}
void Normalize() {
T len = Length();
@ -110,7 +111,7 @@ namespace FasTC {
const VectorTypeTwo &v2) {
VectorTypeOne a(v1);
for(int i = 0; i < VectorTypeOne::Size; i++) {
a(i) += v2[i];
a(i) += static_cast<typename VectorTypeOne::ScalarType>(v2[i]);
}
return a;
}
@ -132,7 +133,7 @@ namespace FasTC {
const VectorTypeTwo &v2) {
VectorTypeOne a(v1);
for(int i = 0; i < VectorTypeOne::Size; i++) {
a(i) -= v2[i];
a(i) -= static_cast<typename VectorTypeOne::ScalarType>(v2[i]);
}
return a;
}
@ -183,9 +184,10 @@ namespace FasTC {
return a;
}
// !WTF! MSVC bug with enums in template parameters =(
template<
EVectorType kVectorTypeOne,
EVectorType kVectorTypeTwo,
/* EVectorType */unsigned kVectorTypeOne,
/* EVectorType */unsigned kVectorTypeTwo,
typename TypeOne,
typename TypeTwo>
class MultSwitch {

View file

@ -53,13 +53,28 @@
#include "gtest/gtest.h"
#include "MatrixBase.h"
static const float kEpsilon = 1e-6;
static const float kEpsilon = 1e-6f;
TEST(MatrixBase, Constructors) {
FasTC::MatrixBase<float, 3, 4> m3f;
for(int j = 0; j < 3; j++)
for(int i = 0; i < 4; i++)
m3f[j*4+i] = static_cast<float>(i) / static_cast<float>(j+1);
FasTC::MatrixBase<double, 1, 1> m1d;
for(int j = 0; j < 1; j++)
for(int i = 0; i < 1; i++)
m1d[j*1+i] = 0.0;
FasTC::MatrixBase<int, 7, 200> m7i;
for(int j = 0; j < 7; j++)
for(int i = 0; i < 200; i++)
m7i[j*200+i] = i*j;
FasTC::MatrixBase<unsigned, 16, 16> m16u;
for(int j = 0; j < 16; j++)
for(int i = 0; i < 16; i++)
m16u[j*16+i] = j-i;
#define TEST_VECTOR_COPY_CONS(mat, t, n, m) \
do { \
@ -123,7 +138,7 @@ TEST(MatrixBase, PointerConversion) {
}
TEST(MatrixBase, CastVector) {
srand(time(NULL));
srand(static_cast<unsigned>(time(NULL)));
FasTC::MatrixBase<float, 3, 2> v3f;
for(int i = 0; i < 6; i++) {
@ -239,8 +254,8 @@ TEST(MatrixSquare, PowerMethod) {
FasTC::VectorBase<double, 2> x;
A.PowerMethod(x, &e, 20, 200);
EXPECT_NEAR(x[0], 0.83205f, 0.0001);
EXPECT_NEAR(x[1], 0.5547f, 0.0001);
EXPECT_NEAR(x[0], 0.83205f, 0.0002);
EXPECT_NEAR(x[1], 0.5547f, 0.0002);
EXPECT_NEAR(e, 1.f, 0.0001);
}

View file

@ -53,13 +53,19 @@
#include "gtest/gtest.h"
#include "VectorBase.h"
static const float kEpsilon = 1e-6;
static const float kEpsilon = 1e-6f;
TEST(VectorBase, Constructors) {
FasTC::VectorBase<float, 3> v3f;
v3f[0] = 1.1f; v3f[1] = 1.2f; v3f[2] = 1.3f;
FasTC::VectorBase<double, 1> v1d;
v1d[0] = 1.1;
FasTC::VectorBase<int, 7> v7i;
for(int i = 0; i < 7; i++)
v7i[i] = -i;
FasTC::VectorBase<unsigned, 16> v16u;
for(int i = 0; i < 7; i++)
v16u[i] = i;
#define TEST_VECTOR_COPY_CONS(v, t, n) \
do { \
@ -118,6 +124,10 @@ TEST(VectorBase, PointerConversion) {
TEST(VectorBase, CastVector) {
FasTC::VectorBase<float, 3> v3f;
v3f[0] = 1000000.0f;
v3f[1] = -2.0f;
v3f[2] = -1.1f;
FasTC::VectorBase<double, 3> v3d = v3f;
FasTC::VectorBase<int, 3> v3i = v3f;
for(int i = 0; i < 3; i++) {
@ -133,11 +143,11 @@ TEST(VectorBase, DotProduct) {
unsigned uv[5] = { 1, 2, 3, 4, 5 };
FasTC::VectorBase<unsigned, 5> v5u(uv);
EXPECT_EQ(v5i.Dot(v5u), 10);
EXPECT_EQ(v5u.Dot(v5i), 10);
EXPECT_EQ(v5i.Dot(v5u), static_cast<int>(10));
EXPECT_EQ(v5u.Dot(v5i), static_cast<unsigned>(10));
EXPECT_EQ(v5i * v5u, 10);
EXPECT_EQ(v5u * v5i, 10);
EXPECT_EQ(v5i * v5u, static_cast<int>(10));
EXPECT_EQ(v5u * v5i, static_cast<unsigned>(10));
}
TEST(VectorBase, Length) {
@ -166,10 +176,10 @@ TEST(VectorBase, Normalization) {
unsigned uv[2] = {2, 2};
FasTC::VectorBase<unsigned, 2> v2u (uv);
v2u.Normalize();
EXPECT_EQ(v2u[0], 1);
EXPECT_EQ(v2u[1], 1);
EXPECT_EQ(v2u[0], static_cast<unsigned>(1));
EXPECT_EQ(v2u[1], static_cast<unsigned>(1));
const float sqrt2 = sqrt(2)/2.0f;
const double sqrt2 = sqrt(2.0f)/2.0f;
for(int i = 2; i < 10; i++) {
v2f[0] = static_cast<float>(i);
v2f[1] = static_cast<float>(i);
@ -197,12 +207,12 @@ TEST(VectorBase, Scaling) {
unsigned uv[2] = {1, 3};
FasTC::VectorBase<unsigned, 2> v2u (uv);
FasTC::VectorBase<unsigned, 2> v2ud = v2u * 0.5;
EXPECT_EQ(v2ud[0], 0);
EXPECT_EQ(v2ud[1], 1);
EXPECT_EQ(v2ud[0], static_cast<unsigned>(0));
EXPECT_EQ(v2ud[1], static_cast<unsigned>(1));
v2ud = v2u / 0.5f;
EXPECT_EQ(v2ud[0], 2);
EXPECT_EQ(v2ud[1], 6);
EXPECT_EQ(v2ud[0], static_cast<unsigned>(2));
EXPECT_EQ(v2ud[1], static_cast<unsigned>(6));
}
TEST(VectorBase, Addition) {
@ -225,7 +235,7 @@ TEST(VectorBase, Addition) {
EXPECT_NEAR(af[1], 5.2f, kEpsilon);
au = v2u - v2f;
EXPECT_EQ(au[0], 3);
EXPECT_EQ(au[0], 4);
EXPECT_EQ(au[1], -1);
af = v2f - v2u;
@ -244,10 +254,12 @@ TEST(VectorBase, Addition) {
TEST(Vector2, BaseFunctionality) {
FasTC::Vec2f v2f;
FasTC::Vec2d v2d;
v2d.X() = 3.0;
v2d.Y() = -10.0;
v2f = v2d;
EXPECT_NEAR(v2f[0], v2d[0], kEpsilon);
EXPECT_NEAR(v2f[1], v2d[1], kEpsilon);
EXPECT_EQ(v2f[0], v2d[0]);
EXPECT_EQ(v2f[1], v2d[1]);
}
TEST(Vector2, Accessors) {
@ -300,10 +312,13 @@ TEST(Vector2, Swizzle) {
TEST(Vector3, BaseFunctionality) {
FasTC::Vec3f vf;
FasTC::Vec3d vd;
vd.X() = 3.0;
vd.Y() = -10.0;
vd.Z() = 0.0;
vf = vd;
for(int i = 0; i < 3; i++) {
EXPECT_NEAR(vf[i], vd[i], kEpsilon);
EXPECT_EQ(vf[i], vd[i]);
}
}
@ -383,10 +398,14 @@ TEST(Vector3, CrossProduct) {
TEST(Vector4, BaseFunctionality) {
FasTC::Vec4f vf;
FasTC::Vec4d vd;
vd.X() = 3.0;
vd.Y() = -10.0;
vd.Z() = 0.0;
vd.W() = 100000000.0;
vf = vd;
for(int i = 0; i < 4; i++) {
EXPECT_NEAR(vf[i], vd[i], kEpsilon);
EXPECT_EQ(vf[i], vd[i]);
}
}

View file

@ -59,12 +59,7 @@
#include "TexComp.h"
#include "ThreadSafeStreambuf.h"
#ifdef _MSC_VER
int _tmain(int argc, _TCHAR* argv[]) {
#else
int main(int argc, char **argv) {
#endif
if(argc != 3) {
fprintf(stderr, "Usage: compare <img1> <img2>\n");
return 1;
@ -82,8 +77,8 @@ int main(int argc, char **argv) {
return 1;
}
FasTC::Image<> img1(*img1f.GetImage());
FasTC::Image<> img2(*img2f.GetImage());
FasTC::Image<> &img1 = *img1f.GetImage();
FasTC::Image<> &img2 = *img2f.GetImage();
double PSNR = img1.ComputePSNR(&img2);
if(PSNR > 0.0) {

View file

@ -46,6 +46,7 @@
#include "ImageFileFormat.h"
#include "TexCompTypes.h"
#include "ImageFwd.h"
class ImageLoader {
@ -142,7 +143,7 @@ class ImageLoader {
uint32 GetHeight() const { return m_Height; }
uint32 GetImageDataSz() const { return m_Width * m_Height * 4; }
bool LoadImage();
virtual FasTC::Image<> *LoadImage();
const uint8 *GetImageData() const { return m_PixelData; }
};

View file

@ -57,6 +57,11 @@
# ifdef __APPLE__
# include <OpenGL/gl.h>
# else
# ifdef _MSC_VER
# define WIN32_LEAN_AND_MEAN
# include "Windows.h"
# undef LoadImage
# endif
# include <GL/gl.h>
# endif
#endif

View file

@ -221,28 +221,13 @@ FasTC::Image<> *ImageFile::LoadImage() const {
if(!loader)
return NULL;
if(!(loader->LoadImage())) {
FasTC::Image<> *i = loader->LoadImage();
if(i == NULL) {
fprintf(stderr, "Unable to load image!\n");
delete loader;
return NULL;
}
uint8 *pixelData = NULL;
if(loader->GetImageData()) {
pixelData = new uint8[ loader->GetImageDataSz() ];
if(!pixelData) { fprintf(stderr, "%s\n", "Out of memory!"); exit(1); }
memcpy(pixelData, loader->GetImageData(), loader->GetImageDataSz());
}
else {
fprintf(stderr, "%s\n", "Failed to get data from image loader!");
}
uint32 *pixels = reinterpret_cast<uint32 *>(pixelData);
FasTC::Image<> *i = new FasTC::Image<>(loader->GetWidth(), loader->GetHeight(), pixels);
// Cleanup
delete loader;
delete [] pixelData;
return i;
}

View file

@ -48,6 +48,7 @@
#include <limits.h>
#include <assert.h>
#include "Image.h"
///////////////////////////////////////////////////////////////////////////////
//
// Static helper functions
@ -166,15 +167,17 @@ bool ImageLoader::LoadFromPixelBuffer(const uint32 *data, bool flipY) {
return true;
}
bool ImageLoader::LoadImage() {
FasTC::Image<> *ImageLoader::LoadImage() {
// Do we already have pixel data?
if(m_PixelData)
return true;
if(m_PixelData) {
uint32 *pixels = reinterpret_cast<uint32 *>(m_PixelData);
return new FasTC::Image<>(m_Width, m_Height, pixels);
}
// Read the image data!
if(!ReadData())
return false;
return NULL;
m_Width = GetWidth();
m_Height = GetHeight();
@ -201,7 +204,7 @@ bool ImageLoader::LoadImage() {
unsigned int redVal = GetChannelForPixel(i, j, 0);
if(redVal == INT_MAX)
return false;
return NULL;
unsigned int greenVal = redVal;
unsigned int blueVal = redVal;
@ -209,20 +212,20 @@ bool ImageLoader::LoadImage() {
if(GetGreenChannelPrecision() > 0) {
greenVal = GetChannelForPixel(i, j, 1);
if(greenVal == INT_MAX)
return false;
return NULL;
}
if(GetBlueChannelPrecision() > 0) {
blueVal = GetChannelForPixel(i, j, 2);
if(blueVal == INT_MAX)
return false;
return NULL;
}
unsigned int alphaVal = 0xFF;
if(GetAlphaChannelPrecision() > 0) {
alphaVal = GetChannelForPixel(i, j, 3);
if(alphaVal == INT_MAX)
return false;
return NULL;
}
// Red channel
@ -239,5 +242,6 @@ bool ImageLoader::LoadImage() {
}
}
return true;
uint32 *pixels = reinterpret_cast<uint32 *>(m_PixelData);
return new FasTC::Image<>(m_Width, m_Height, pixels);
}

View file

@ -62,6 +62,8 @@
#include "ScopedAllocator.h"
#include "GLDefines.h"
#include "Image.h"
#include "CompressedImage.h"
class ByteReader {
private:
@ -73,7 +75,7 @@ class ByteReader {
{ }
bool Advance(uint32 nBytes) {
if(nBytes < m_BytesLeft) {
if(nBytes > m_BytesLeft) {
assert(!"Cannot read any more, unexpected bytes!");
return false;
}
@ -99,6 +101,7 @@ class IntLoader {
data.Advance(4);
return true;
}
virtual ~IntLoader() { }
};
class BigEndianIntLoader : public IntLoader {
@ -137,8 +140,31 @@ ImageLoaderKTX::ImageLoaderKTX(const uint8 *rawData, const int32 rawDataSz)
ImageLoaderKTX::~ImageLoaderKTX() { }
FasTC::Image<> *ImageLoaderKTX::LoadImage() {
// Get rid of the pixel data if it exists...
if(m_PixelData) {
delete m_PixelData;
m_PixelData = NULL;
}
if(!ReadData()) {
return NULL;
}
if(!m_bIsCompressed) {
uint32 *pixels = reinterpret_cast<uint32 *>(m_PixelData);
return new FasTC::Image<>(m_Width, m_Height, pixels);
}
return new CompressedImage(m_Width, m_Height, m_Format, m_PixelData);
}
bool ImageLoaderKTX::ReadData() {
// Default is uncompressed
m_bIsCompressed = false;
ByteReader rdr (m_RawData, m_NumRawDataBytes);
// First, check to make sure that the identifier is present...
@ -245,13 +271,25 @@ bool ImageLoaderKTX::ReadData() {
return false;
}
if(glType == 0 &&
glFormat == 0 &&
glInternalFormat == GL_COMPRESSED_RGBA_BPTC_UNORM) {
fprintf(stderr, "KTX loader - BPTC compressed textures unsupported!\n");
return false;
// Load compressed texture...
// rdr.Advance(pixelWidth * pixelHeight);
m_Width = pixelWidth;
m_Height = pixelHeight;
if(glType == 0 && glFormat == 0) {
switch(glInternalFormat) {
case GL_COMPRESSED_RGBA_BPTC_UNORM:
m_Format = FasTC::eCompressionFormat_BPTC;
break;
default:
fprintf(stderr, "KTX loader - texture format (0x%x) unsupported!\n", glInternalFormat);
return false;
}
uint32 dataSize = CompressedImage::GetCompressedSize(pixelWidth * pixelHeight * 4, m_Format);
m_PixelData = new uint8[dataSize];
memcpy(m_PixelData, rdr.GetData(), dataSize);
rdr.Advance(dataSize);
m_bIsCompressed = true;
} else {
if(glType != GL_BYTE) {
@ -266,10 +304,10 @@ bool ImageLoaderKTX::ReadData() {
// We should have RGBA8 data here so we can simply load it
// as we normally would.
m_Width = pixelWidth;
m_Height = pixelHeight;
LoadFromPixelBuffer(reinterpret_cast<const uint32 *>(rdr.GetData()));
rdr.Advance(pixelWidth * pixelHeight * 4);
uint32 pixelDataSz = m_Width * m_Height * 4;
m_PixelData = new uint8[pixelDataSz];
memcpy(m_PixelData, rdr.GetData(), pixelDataSz);
rdr.Advance(pixelDataSz);
}
return rdr.GetBytesLeft() == 0;
}

View file

@ -54,6 +54,7 @@
#define _IO_SRC_IMAGE_LOADER_KTX_H_
#include "ImageLoader.h"
#include "CompressionFormat.h"
class ImageLoaderKTX : public ImageLoader {
public:
@ -68,8 +69,12 @@ class ImageLoaderKTX : public ImageLoader {
m_Processor = proc;
}
virtual FasTC::Image<> *LoadImage();
private:
KTXKeyValueProcessor m_Processor;
bool m_bIsCompressed;
FasTC::ECompressionFormat m_Format;
};
#endif // _IO_SRC_IMAGE_LOADER_KTX_H_

View file

@ -110,10 +110,12 @@ bool ImageWriterKTX::WriteImage() {
wtr.Write(0x04030201);
const char *orientationKey = "KTXorientation";
const char *orientationValue = "S=r,T=u";
const uint32 kvSz =
strlen(orientationKey) + 1 // key
+ strlen(orientationValue) + 1; // value
uint32 oKeyLen = static_cast<uint32>(strlen(orientationKey));
const char *orientationValue = "S=r,T=d";
uint32 oValLen = static_cast<uint32>(strlen(orientationValue));
const uint32 kvSz = oKeyLen + 1 + oValLen + 1;
uint32 tkvSz = kvSz + 4; // total kv size
tkvSz = (tkvSz + 3) & ~0x3; // 4-byte aligned
@ -121,7 +123,7 @@ bool ImageWriterKTX::WriteImage() {
if(ci) {
wtr.Write(0); // glType
wtr.Write(1); // glTypeSize
wtr.Write(GL_RGBA); // glFormat
wtr.Write(0); // glFormat must be zero for compressed images...
switch(ci->GetFormat()) {
case FasTC::eCompressionFormat_BPTC:
wtr.Write(GL_COMPRESSED_RGBA_BPTC_UNORM); // glInternalFormat
@ -153,8 +155,8 @@ bool ImageWriterKTX::WriteImage() {
wtr.Write(1); // numberOfMipmapLevels
wtr.Write(tkvSz); // total key value size
wtr.Write(kvSz); // key value size
wtr.Write(orientationKey, strlen(orientationKey) + 1); // key
wtr.Write(orientationValue, strlen(orientationValue) + 1); // value
wtr.Write(orientationKey, oKeyLen + 1); // key
wtr.Write(orientationValue, oValLen + 1); // value
wtr.Write(orientationKey, tkvSz - kvSz - 4); // padding
if(ci && ci->GetFormat() == FasTC::eCompressionFormat_BPTC) {

View file

@ -465,9 +465,11 @@ namespace PVRTCC {
}
#if 0
static void DilateImage(CompressionLabel *labels, uint32 w, uint32 h) {
static void DilateImage(CompressionLabel *labels, const uint8 *inBuf, uint32 w, uint32 h) {
for(uint32 j = 0; j < h; j++)
for(uint32 i = 0; i < w; i++) {
ComputeLocalExtrema(labels, inBuf, i, j, w, h);
uint32 idx = j*w + i;
uint32 minLowDist = labels[idx].lowLabel.distance == 0? 5 : labels[idx].lowLabel.distance - 1;
@ -484,11 +486,11 @@ namespace PVRTCC {
minHighDist = ::std::min<uint32>(minHighDist, labels[cidx].highLabel.distance);
}
if(minLowDist != labels[idx].lowLabel.distance - 1) {
if(static_cast<int32>(minLowDist) != labels[idx].lowLabel.distance - 1) {
labels[idx].lowLabel.nLabels = 0;
}
if(minHighDist != labels[idx].highLabel.distance - 1) {
if(static_cast<int32>(minHighDist) != labels[idx].highLabel.distance - 1) {
labels[idx].highLabel.nLabels = 0;
}
@ -963,6 +965,27 @@ namespace PVRTCC {
DebugOutputImage("HighImg", labels, width, height, HighPixel);
DebugOutputImage("LowImg", labels, width, height, LowPixel);
Image outputHigh(width, height);
Image outputLow(width, height);
for(uint32 j = 0; j < height; j++)
for(uint32 i = 0; i < width; i++) {
uint32 idx = j*width + i;
if(labels[idx].highLabel.distance == 1) {
outputHigh(i, j).Unpack(gDbgPixels[idx]);
} else {
outputHigh(i, j).Unpack(0xFF000000U);
}
if(labels[idx].lowLabel.distance == 1) {
outputLow(i, j).Unpack(gDbgPixels[idx]);
} else {
outputLow(i, j).Unpack(0xFF000000U);
}
}
outputHigh.DebugOutput("HighPixels");
outputLow.DebugOutput("LowPixels");
#endif
// Then combine everything...

View file

@ -1,4 +1,4 @@
FasTC
FasTC [![Build Status](https://travis-ci.org/Mokosha/FasTC.png)](https://travis-ci.org/Mokosha/FasTC)
=======
A **Fas**t **T**exture **C**ompressor for a variety of formats. This compressor