mirror of
https://github.com/yuzu-emu/FasTC.git
synced 2024-11-30 20:24:24 +01:00
Fleshed out some more of the library
This commit is contained in:
parent
39d7f2c942
commit
a076d1efb8
@ -3,3 +3,4 @@ PROJECT(TexC)
|
||||
|
||||
ADD_SUBDIRECTORY(BPTCEncoder)
|
||||
ADD_SUBDIRECTORY(IO)
|
||||
ADD_SUBDIRECTORY(Core)
|
||||
|
@ -1,15 +1,21 @@
|
||||
|
||||
SET( SOURCES
|
||||
"src/TexComp.cpp"
|
||||
"src/CompressedImage.cpp"
|
||||
)
|
||||
|
||||
SET( HEADERS
|
||||
"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 )
|
||||
|
||||
ADD_LIBRARY( TexCompCore
|
||||
${HEADERS}
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES( TexCompCore TexCompIO )
|
||||
|
34
Core/include/CompressedImage.h
Normal file
34
Core/include/CompressedImage.h
Normal 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_
|
@ -1,4 +1,27 @@
|
||||
#ifndef _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_
|
||||
|
50
Core/src/CompressedImage.cpp
Normal file
50
Core/src/CompressedImage.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -1 +1,55 @@
|
||||
#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;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ FIND_PACKAGE( PNG )
|
||||
IF( PNG_FOUND )
|
||||
INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
|
||||
|
||||
|
||||
SET( SOURCES ${SOURCES} "src/ImageLoaderPNG.cpp" )
|
||||
SET( HEADERS ${HEADERS} "src/ImageLoaderPNG.h" )
|
||||
ENDIF()
|
||||
|
@ -62,16 +62,19 @@ class ImageLoader {
|
||||
virtual bool ReadData() = 0;
|
||||
|
||||
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; }
|
||||
unsigned char * GetGreenPixelData() const { return m_GreenData; }
|
||||
const unsigned char * GetGreenPixelData() const { return m_GreenData; }
|
||||
|
||||
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; }
|
||||
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
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ImageFile.h"
|
||||
@ -9,6 +10,101 @@
|
||||
# include "ImageLoaderPNG.h"
|
||||
#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) :
|
||||
m_PixelData(0),
|
||||
m_FileFormat( DetectFileFormat(filename) )
|
||||
@ -80,7 +176,77 @@ bool ImageFile::LoadImage(const unsigned char *rawImageData) {
|
||||
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;
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user