Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginDDS.cpp view on Meta::CPAN
static void
SwapHeader(DDSHEADER *header) {
SwapLong(&header->dwMagic);
SwapLong(&header->surfaceDesc.dwSize);
SwapLong(&header->surfaceDesc.dwFlags);
SwapLong(&header->surfaceDesc.dwHeight);
SwapLong(&header->surfaceDesc.dwWidth);
SwapLong(&header->surfaceDesc.dwPitchOrLinearSize);
SwapLong(&header->surfaceDesc.dwDepth);
SwapLong(&header->surfaceDesc.dwMipMapCount);
for(int i=0; i<11; i++) {
SwapLong(&header->surfaceDesc.dwReserved1[i]);
}
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwSize);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFlags);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwFourCC);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBBitCount);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRBitMask);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwGBitMask);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwBBitMask);
SwapLong(&header->surfaceDesc.ddpfPixelFormat.dwRGBAlphaBitMask);
SwapLong(&header->surfaceDesc.ddsCaps.dwCaps1);
SwapLong(&header->surfaceDesc.ddsCaps.dwCaps2);
SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[0]);
SwapLong(&header->surfaceDesc.ddsCaps.dwReserved[1]);
SwapLong(&header->surfaceDesc.dwReserved2);
}
#endif
// ==========================================================
// Get the 4 possible colors for a block
//
static void
GetBlockColors (const DXTColBlock &block, Color8888 colors[4], bool isDXT1) {
int i;
// expand from 565 to 888
for (i = 0; i < 2; i++) {
colors[i].a = 0xff;
/*
colors[i].r = (BYTE)(block.colors[i].r * 0xff / 0x1f);
colors[i].g = (BYTE)(block.colors[i].g * 0xff / 0x3f);
colors[i].b = (BYTE)(block.colors[i].b * 0xff / 0x1f);
*/
colors[i].r = (BYTE)((block.colors[i].r << 3U) | (block.colors[i].r >> 2U));
colors[i].g = (BYTE)((block.colors[i].g << 2U) | (block.colors[i].g >> 4U));
colors[i].b = (BYTE)((block.colors[i].b << 3U) | (block.colors[i].b >> 2U));
}
WORD *wCol = (WORD *)block.colors;
if (wCol[0] > wCol[1] || !isDXT1) {
// 4 color block
for (i = 0; i < 2; i++) {
colors[i + 2].a = 0xff;
colors[i + 2].r = (BYTE)((WORD (colors[0].r) * (2 - i) + WORD (colors[1].r) * (1 + i)) / 3);
colors[i + 2].g = (BYTE)((WORD (colors[0].g) * (2 - i) + WORD (colors[1].g) * (1 + i)) / 3);
colors[i + 2].b = (BYTE)((WORD (colors[0].b) * (2 - i) + WORD (colors[1].b) * (1 + i)) / 3);
}
}
else {
// 3 color block, number 4 is transparent
colors[2].a = 0xff;
colors[2].r = (BYTE)((WORD (colors[0].r) + WORD (colors[1].r)) / 2);
colors[2].g = (BYTE)((WORD (colors[0].g) + WORD (colors[1].g)) / 2);
colors[2].b = (BYTE)((WORD (colors[0].b) + WORD (colors[1].b)) / 2);
colors[3].a = 0x00;
colors[3].g = 0x00;
colors[3].b = 0x00;
colors[3].r = 0x00;
}
}
struct DXT_INFO_1 {
typedef DXT1Block Block;
enum {
isDXT1 = 1,
bytesPerBlock = 8
};
};
struct DXT_INFO_3 {
typedef DXT3Block Block;
enum {
isDXT1 = 1,
bytesPerBlock = 16
};
};
struct DXT_INFO_5 {
typedef DXT5Block Block;
enum
{
isDXT1 = 1,
bytesPerBlock = 16
};
};
template <class INFO> class DXT_BLOCKDECODER_BASE {
protected:
Color8888 m_colors[4];
const typename INFO::Block *m_pBlock;
unsigned m_colorRow;
public:
void Setup (const BYTE *pBlock) {
m_pBlock = (const typename INFO::Block *)pBlock;
GetBlockColors (m_pBlock->color, m_colors, INFO::isDXT1);
}
void SetY (int y) {
m_colorRow = m_pBlock->color.row[y];
}
void GetColor (int x, int y, Color8888 &color) {
unsigned bits = (m_colorRow >> (x * 2)) & 3;
color = m_colors[bits];
}
};
class DXT_BLOCKDECODER_1 : public DXT_BLOCKDECODER_BASE <DXT_INFO_1> {
src/Source/FreeImage/PluginDDS.cpp view on Meta::CPAN
DECODER decoder;
decoder.Setup (srcBlock);
for (int y = 0; y < bh; y++) {
BYTE *dst = dstData - y * dstPitch;
decoder.SetY (y);
for (int x = 0; x < bw; x++) {
decoder.GetColor (x, y, (Color8888 &)*dst);
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
INPLACESWAP(dst[FI_RGBA_RED], dst[FI_RGBA_BLUE]);
#endif
dst += 4;
}
}
}
// ==========================================================
// Plugin Interface
// ==========================================================
static int s_format_id;
// ==========================================================
// Internal functions
// ==========================================================
static FIBITMAP *
LoadRGB (DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
int width = (int)desc.dwWidth & ~3;
int height = (int)desc.dwHeight & ~3;
int bpp = (int)desc.ddpfPixelFormat.dwRGBBitCount;
// allocate a new dib
FIBITMAP *dib = FreeImage_Allocate (width, height, bpp, desc.ddpfPixelFormat.dwRBitMask,
desc.ddpfPixelFormat.dwGBitMask, desc.ddpfPixelFormat.dwBBitMask);
if (dib == NULL)
return NULL;
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
// Calculate the number of bytes per pixel (3 for 24-bit or 4 for 32-bit)
int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
#endif
// read the file
int line = CalculateLine(width, bpp);
int filePitch = (desc.dwFlags & DDSD_PITCH) ? (int)desc.dwPitchOrLinearSize : line;
long delta = (long)filePitch - (long)line;
for (int i = 0; i < height; i++) {
BYTE *pixels = FreeImage_GetScanLine(dib, height - i - 1);
io->read_proc (pixels, 1, line, handle);
io->seek_proc (handle, delta, SEEK_CUR);
#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
for(int x = 0; x < width; x++) {
INPLACESWAP(pixels[FI_RGBA_RED],pixels[FI_RGBA_BLUE]);
pixels += bytespp;
}
#endif
}
// enable transparency
FreeImage_SetTransparent (dib, (desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) ? TRUE : FALSE);
if (!(desc.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) && bpp == 32) {
// no transparency: convert to 24-bit
FIBITMAP *old = dib;
dib = FreeImage_ConvertTo24Bits (old);
FreeImage_Unload (old);
}
return dib;
}
template <class DECODER> static void
LoadDXT_Helper (FreeImageIO *io, fi_handle handle, int page, int flags, void *data, FIBITMAP *dib, int width, int height, int line) {
typedef typename DECODER::INFO INFO;
typedef typename INFO::Block Block;
Block *input_buffer = new(std::nothrow) Block[(width + 3) / 4];
if(!input_buffer) return;
int widthRest = (int) width & 3;
int heightRest = (int) height & 3;
int inputLine = (width + 3) / 4;
int y = 0;
if (height >= 4) {
for (; y < height; y += 4) {
io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
// TODO: probably need some endian work here
BYTE *pbSrc = (BYTE *)input_buffer;
BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);
if (width >= 4) {
for (int x = 0; x < width; x += 4) {
DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, 4);
pbSrc += INFO::bytesPerBlock;
pbDst += 4 * 4;
}
}
if (widthRest) {
DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, 4);
}
}
}
if (heightRest) {
io->read_proc (input_buffer, sizeof (typename INFO::Block), inputLine, handle);
// TODO: probably need some endian work here
BYTE *pbSrc = (BYTE *)input_buffer;
BYTE *pbDst = FreeImage_GetScanLine (dib, height - y - 1);
if (width >= 4) {
for (int x = 0; x < width; x += 4) {
DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, 4, heightRest);
pbSrc += INFO::bytesPerBlock;
pbDst += 4 * 4;
}
}
if (widthRest) {
DecodeDXTBlock <DECODER> (pbDst, pbSrc, line, widthRest, heightRest);
}
}
( run in 1.342 second using v1.01-cache-2.11-cpan-fa01517f264 )