Fleshed out some more of the library

This commit is contained in:
Pavel Krajcevski 2012-08-27 18:34:37 -04:00
parent 39d7f2c942
commit a076d1efb8
9 changed files with 342 additions and 6 deletions

View File

@ -3,3 +3,4 @@ PROJECT(TexC)
ADD_SUBDIRECTORY(BPTCEncoder) ADD_SUBDIRECTORY(BPTCEncoder)
ADD_SUBDIRECTORY(IO) ADD_SUBDIRECTORY(IO)
ADD_SUBDIRECTORY(Core)

View File

@ -1,15 +1,21 @@
SET( SOURCES SET( SOURCES
"src/TexComp.cpp" "src/TexComp.cpp"
"src/CompressedImage.cpp"
) )
SET( HEADERS SET( HEADERS
"include/TexComp.h" "include/TexComp.h"
"include/CompressedImage.h"
) )
INCLUDE_DIRECTORIES( ${TexC_BINARY_DIR}/IO/include )
INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/IO/include )
INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/Core/include ) INCLUDE_DIRECTORIES( ${TexC_SOURCE_DIR}/Core/include )
ADD_LIBRARY( TexCompCore ADD_LIBRARY( TexCompCore
${HEADERS} ${HEADERS}
${SOURCES} ${SOURCES}
) )
TARGET_LINK_LIBRARIES( TexCompCore TexCompIO )

View File

@ -0,0 +1,34 @@
#ifndef _COMPRESSED_IMAGE_H_
#define _COMPRESSED_IMAGE_H_
enum ECompressionFormat {
eCompressionFormat_DXT1,
eCompressionFormat_DXT5,
eCompressionFormat_BPTC,
kNumCompressionFormats
};
class CompressedImage {
private:
unsigned char *m_Data;
unsigned int m_DataSz;
unsigned int m_Width;
unsigned int m_Height;
ECompressionFormat m_Format;
void InitData(const unsigned char *withData);
public:
CompressedImage(
const unsigned int width,
const unsigned int height,
const ECompressionFormat format,
const unsigned char *data
);
CompressedImage( const CompressedImage &other );
~CompressedImage();
};
#endif // _COMPRESSED_IMAGE_H_

View File

@ -1,4 +1,27 @@
#ifndef _TEX_COMP_H_ #ifndef _TEX_COMP_H_
#define _TEX_COMP_H_ #define _TEX_COMP_H_
#include "ImageFile.h"
#include "CompressedImage.h"
struct SCompressionSettings {
SCompressionSettings(); // defaults
ECompressionFormat format;
bool bUseSIMD;
int iNumThreads;
};
extern void CompressImage(
const ImageFile &,
CompressedImage &,
const SCompressionSettings &settings
);
typedef void (* CompressionFunc)(
const unsigned char *inData,
unsigned char *outData,
unsigned int width,
unsigned int height
);
#endif //_TEX_COMP_H_ #endif //_TEX_COMP_H_

View File

@ -0,0 +1,50 @@
#include "CompressedImage.h"
#include <string.h>
#include <stdlib.h>
CompressedImage::CompressedImage( const CompressedImage &other )
: m_Width(other.m_Width)
, m_Height(other.m_Height)
, m_Format(other.m_Format)
, m_Data(0)
{
InitData(other.m_Data);
}
CompressedImage::CompressedImage(
const unsigned int width,
const unsigned int height,
const ECompressionFormat format,
const unsigned char *data
)
: m_Width(width)
, m_Height(height)
, m_Format(format)
, m_Data(0)
{
InitData(data);
}
void CompressedImage::InitData(const unsigned char *withData) {
unsigned int dataSz = 0;
int uncompDataSz = m_Width * m_Height * 4;
switch(m_Format) {
case eCompressionFormat_DXT1: dataSz = uncompDataSz / 8; break;
case eCompressionFormat_DXT5: dataSz = uncompDataSz / 4; break;
case eCompressionFormat_BPTC: dataSz = uncompDataSz / 4; break;
}
if(dataSz > 0) {
m_Data = new unsigned char[dataSz];
memcpy(m_Data, withData, dataSz);
}
}
CompressedImage::~CompressedImage() {
if(m_Data) {
delete [] m_Data;
m_Data = NULL;
}
}

View File

@ -1 +1,55 @@
#include "TexComp.h" #include "TexComp.h"
#include <stdlib.h>
#include <stdio.h>
SCompressionSettings:: SCompressionSettings()
: format(eCompressionFormat_BPTC)
, bUseSIMD(false)
, iNumThreads(1)
{}
static CompressionFunc ChooseFuncFromSettings(const SCompressionSettings &s) {
return NULL;
}
static void ReportError(const char *msg) {
fprintf(stderr, "TexComp -- %s\n", msg);
}
void CompressImage(
const ImageFile &img,
CompressedImage &outImg,
const SCompressionSettings &settings
) {
const unsigned int dataSz = img.GetWidth() * img.GetHeight() * 4;
// Allocate data based on the compression method
int cmpDataSz = 0;
switch(settings.format) {
case eCompressionFormat_DXT1: cmpDataSz = dataSz / 8;
case eCompressionFormat_DXT5: cmpDataSz = dataSz / 4;
case eCompressionFormat_BPTC: cmpDataSz = dataSz / 4;
}
if(cmpDataSz == 0) {
ReportError("Unknown compression format");
return;
}
unsigned char *cmpData = new unsigned char[cmpDataSz];
CompressionFunc f = ChooseFuncFromSettings(settings);
if(f) {
(*f)(img.GetPixels(), cmpData, img.GetWidth(), img.GetHeight());
outImg = CompressedImage(img.GetWidth(), img.GetHeight(), settings.format, cmpData);
}
else {
ReportError("Could not find adequate compression function for specified settings");
// return
}
// Cleanup
delete [] cmpData;
}

View File

@ -12,7 +12,6 @@ FIND_PACKAGE( PNG )
IF( PNG_FOUND ) IF( PNG_FOUND )
INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} ) INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
SET( SOURCES ${SOURCES} "src/ImageLoaderPNG.cpp" ) SET( SOURCES ${SOURCES} "src/ImageLoaderPNG.cpp" )
SET( HEADERS ${HEADERS} "src/ImageLoaderPNG.h" ) SET( HEADERS ${HEADERS} "src/ImageLoaderPNG.h" )
ENDIF() ENDIF()

View File

@ -62,16 +62,19 @@ class ImageLoader {
virtual bool ReadData() = 0; virtual bool ReadData() = 0;
int GetRedChannelPrecision() const { return m_RedChannelPrecision; } int GetRedChannelPrecision() const { return m_RedChannelPrecision; }
unsigned char * GetRedPixelData() const { return m_RedData; } const unsigned char * GetRedPixelData() const { return m_RedData; }
int GetGreenChannelPrecision() const { return m_GreenChannelPrecision; } int GetGreenChannelPrecision() const { return m_GreenChannelPrecision; }
unsigned char * GetGreenPixelData() const { return m_GreenData; } const unsigned char * GetGreenPixelData() const { return m_GreenData; }
int GetBlueChannelPrecision() const { return m_BlueChannelPrecision; } int GetBlueChannelPrecision() const { return m_BlueChannelPrecision; }
unsigned char * GetBluePixelData() const { return m_BlueData; } const unsigned char * GetBluePixelData() const { return m_BlueData; }
int GetAlphaChannelPrecision() const { return m_AlphaChannelPrecision; } int GetAlphaChannelPrecision() const { return m_AlphaChannelPrecision; }
unsigned char * GetAlphaPixelData() const { return m_AlphaData; } const unsigned char * GetAlphaPixelData() const { return m_AlphaData; }
int GetWidth() const { return m_Width; }
int GetHeight() const { return m_Height; }
}; };
#cmakedefine PNG_FOUND #cmakedefine PNG_FOUND

View File

@ -1,6 +1,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h>
#include <assert.h> #include <assert.h>
#include "ImageFile.h" #include "ImageFile.h"
@ -9,6 +10,101 @@
# include "ImageLoaderPNG.h" # include "ImageLoaderPNG.h"
#endif #endif
//////////////////////////////////////////////////////////////////////////////////////////
//
// Static helper functions
//
//////////////////////////////////////////////////////////////////////////////////////////
static inline void ReportError(const char *msg) {
fprintf(stderr, "ImageFile -- %s\n", msg);
}
template <typename T>
static inline T abs(const T &a) {
return a > 0? a : -a;
}
template <typename T>
static inline T min(const T &a, const T &b) {
return (a < b)? a : b;
}
static unsigned int GetChannelForPixel(
const ImageLoader *loader,
unsigned int x, unsigned int y,
int ch
) {
unsigned int prec;
const unsigned char *data;
switch(ch) {
case 0:
prec = loader->GetRedChannelPrecision();
data = loader->GetRedPixelData();
break;
case 1:
prec = loader->GetGreenChannelPrecision();
data = loader->GetGreenPixelData();
break;
case 2:
prec = loader->GetBlueChannelPrecision();
data = loader->GetBluePixelData();
break;
case 3:
prec = loader->GetAlphaChannelPrecision();
data = loader->GetAlphaPixelData();
break;
default:
ReportError("Unspecified channel");
return INT_MAX;
}
if(0 == prec)
return 0;
assert(x < loader->GetWidth());
assert(y < loader->GetHeight());
int pixelIdx = y * loader->GetWidth() + x;
const unsigned int val = data[pixelIdx];
if(prec < 8) {
unsigned int ret = 0;
for(unsigned int precLeft = 8; precLeft > 0; precLeft -= min(prec, abs(prec - precLeft))) {
if(prec > precLeft) {
const int toShift = prec - precLeft;
ret = ret << precLeft;
ret |= val >> toShift;
}
else {
ret = ret << prec;
ret |= val;
}
}
return ret;
}
else if(prec > 8) {
const int toShift = prec - 8;
return val >> toShift;
}
return val;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// ImageFile implementation
//
//////////////////////////////////////////////////////////////////////////////////////////
ImageFile::ImageFile(const char *filename) : ImageFile::ImageFile(const char *filename) :
m_PixelData(0), m_PixelData(0),
m_FileFormat( DetectFileFormat(filename) ) m_FileFormat( DetectFileFormat(filename) )
@ -80,7 +176,77 @@ bool ImageFile::LoadImage(const unsigned char *rawImageData) {
break; break;
} }
m_Width = loader->GetWidth();
m_Height = loader->GetHeight();
// Create RGBA buffer
const unsigned int dataSz = 4 * m_Width * m_Height;
m_PixelData = new unsigned char[dataSz];
// 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;
int byteIdx = 0;
for(int i = 0; i < ah; i+=4) {
for(int j = 0; j < aw; j+= 4) {
// For each block, visit the pixels in sequential order
for(int y = i; y < i+4; y++) {
for(int x = j; x < j+4; x++) {
if(y >= m_Height || x >= m_Width) {
m_PixelData[byteIdx++] = 0; // r
m_PixelData[byteIdx++] = 0; // g
m_PixelData[byteIdx++] = 0; // b
m_PixelData[byteIdx++] = 0; // a
continue;
}
unsigned int redVal = GetChannelForPixel(loader, x, y, 0);
if(redVal == INT_MAX)
return false; return false;
unsigned int greenVal = redVal;
unsigned int blueVal = redVal;
if(loader->GetGreenChannelPrecision() > 0) {
greenVal = GetChannelForPixel(loader, x, y, 1);
if(greenVal == INT_MAX)
return false;
}
if(loader->GetBlueChannelPrecision() > 0) {
blueVal = GetChannelForPixel(loader, x, y, 2);
if(blueVal == INT_MAX)
return false;
}
unsigned int alphaVal = 0xFF;
if(loader->GetAlphaChannelPrecision() > 0) {
alphaVal = GetChannelForPixel(loader, 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;
}
}
}
}
return true;
} }
#ifdef _MSC_VER #ifdef _MSC_VER