?? plugindds.cpp
字號:
protected:
unsigned m_alphas[8];
unsigned m_alphaBits;
int m_offset;
public:
void Setup (const BYTE *pBlock) {
base::Setup (pBlock);
const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
m_alphas[0] = block.alpha[0];
m_alphas[1] = block.alpha[1];
if (m_alphas[0] > m_alphas[1]) {
// 8 alpha block
for (int i = 0; i < 6; i++) {
m_alphas[i + 2] = ((6 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 3) / 7;
}
}
else {
// 6 alpha block
for (int i = 0; i < 4; i++) {
m_alphas[i + 2] = ((4 - i) * m_alphas[0] + (1 + i) * m_alphas[1] + 2) / 5;
}
m_alphas[6] = 0;
m_alphas[7] = 0xFF;
}
}
void SetY (int y) {
base::SetY (y);
int i = y / 2;
const DXTAlphaBlock3BitLinear &block = m_pBlock->alpha;
m_alphaBits = unsigned(block.data[0 + i * 3]) | (unsigned(block.data[1 + i * 3]) << 8)
| (unsigned(block.data[2 + i * 3]) << 16);
m_offset = (y & 1) * 12;
}
void GetColor (int x, int y, Color8888 &color) {
base::GetColor (x, y, color);
unsigned bits = (m_alphaBits >> (x * 3 + m_offset)) & 7;
color.a = m_alphas[bits];
}
};
template <class DECODER> void DecodeDXTBlock (BYTE *dstData, const BYTE *srcBlock, long dstPitch, int bw, int bh) {
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);
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;
int height = (int)desc.dwHeight;
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;
#ifdef FREEIMAGE_BIGENDIAN
// 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);
#ifdef FREEIMAGE_BIGENDIAN
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, BYTE *bits, int width, int height, int line) {
typedef typename DECODER::INFO INFO;
typedef typename INFO::Block Block;
Block *input_buffer = new Block[(width + 3) / 4];
int widthFullBlocks = width / 4;
int heightFullBlocks = height / 4;
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);
}
}
}
static FIBITMAP *
LoadDXT (int type, DDSURFACEDESC2 &desc, FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
int width = (int)desc.dwWidth;
int height = (int)desc.dwHeight;
// allocate a 32-bit dib
FIBITMAP *dib = FreeImage_Allocate (width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
if (dib == NULL)
return NULL;
int bpp = FreeImage_GetBPP (dib);
int line = CalculateLine (width, bpp);
BYTE *bits = FreeImage_GetBits (dib);
// select the right decoder
switch (type) {
case 1:
LoadDXT_Helper <DXT_BLOCKDECODER_1> (io, handle, page, flags, data, dib, bits, width, height, line);
break;
case 3:
LoadDXT_Helper <DXT_BLOCKDECODER_3> (io, handle, page, flags, data, dib, bits, width, height, line);
break;
case 5:
LoadDXT_Helper <DXT_BLOCKDECODER_5> (io, handle, page, flags, data, dib, bits, width, height, line);
break;
}
return dib;
}
// ==========================================================
// Plugin Implementation
// ==========================================================
static const char * DLL_CALLCONV
Format() {
return "DDS";
}
static const char * DLL_CALLCONV
Description() {
return "DirectX Surface";
}
static const char * DLL_CALLCONV
Extension() {
return "dds";
}
static const char * DLL_CALLCONV
RegExpr() {
return NULL;
}
static const char * DLL_CALLCONV
MimeType() {
return "image/freeimage-dds";
}
static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
DDSHEADER header;
io->read_proc(&header, 1, sizeof(header), handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapHeader(&header);
#endif
if (header.dwMagic != MAKEFOURCC ('D','D','S',' '))
return FALSE;
if (header.surfaceDesc.dwSize != sizeof (header.surfaceDesc) ||
header.surfaceDesc.ddpfPixelFormat.dwSize != sizeof (header.surfaceDesc.ddpfPixelFormat))
return FALSE;
return TRUE;
}
static BOOL DLL_CALLCONV
SupportsExportDepth(int depth) {
return FALSE;
}
static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type) {
return (type == FIT_BITMAP) ? TRUE : FALSE;
}
// ----------------------------------------------------------
static void * DLL_CALLCONV
Open(FreeImageIO *io, fi_handle handle, BOOL read) {
return NULL;
}
static void DLL_CALLCONV
Close(FreeImageIO *io, fi_handle handle, void *data) {
}
// ----------------------------------------------------------
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
DDSHEADER header;
FIBITMAP *dib = NULL;
io->read_proc(&header, 1, sizeof(header), handle);
#ifdef FREEIMAGE_BIGENDIAN
SwapHeader(&header);
#endif
if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_RGB) {
dib = LoadRGB (header.surfaceDesc, io, handle, page, flags, data);
}
else if (header.surfaceDesc.ddpfPixelFormat.dwFlags & DDPF_FOURCC) {
switch (header.surfaceDesc.ddpfPixelFormat.dwFourCC) {
case FOURCC_DXT1:
dib = LoadDXT (1, header.surfaceDesc, io, handle, page, flags, data);
break;
case FOURCC_DXT3:
dib = LoadDXT (3, header.surfaceDesc, io, handle, page, flags, data);
break;
case FOURCC_DXT5:
dib = LoadDXT (5, header.surfaceDesc, io, handle, page, flags, data);
break;
}
}
return dib;
}
static BOOL DLL_CALLCONV
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
return FALSE;
}
// ==========================================================
// Init
// ==========================================================
void DLL_CALLCONV
InitDDS(Plugin *plugin, int format_id) {
s_format_id = format_id;
plugin->format_proc = Format;
plugin->description_proc = Description;
plugin->extension_proc = Extension;
plugin->regexpr_proc = RegExpr;
plugin->open_proc = Open;
plugin->close_proc = Close;
plugin->pagecount_proc = NULL;
plugin->pagecapability_proc = NULL;
plugin->load_proc = Load;
plugin->save_proc = NULL; //Save; // not implemented (yet?)
plugin->validate_proc = Validate;
plugin->mime_proc = MimeType;
plugin->supports_export_bpp_proc = SupportsExportDepth;
plugin->supports_export_type_proc = SupportsExportType;
plugin->supports_icc_profiles_proc = NULL;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -