Switched to using Basis's own RGB transcode

Removed the DXT->RGB conversion now that the transcoder has an RGB option.
This commit is contained in:
Carl Woffenden
2019-10-03 19:26:46 +02:00
parent 5987afa171
commit 582d8c8488
3 changed files with 21 additions and 138 deletions

View File

@@ -85,12 +85,13 @@ IFACEMETHODIMP BasisThumbProvider::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALP
basisu_file_info fileInfo;
transcoder.get_file_info(data, size, fileInfo);
if (transcoder.start_transcoding(data, size)) {
if (void* dxtBuf = malloc(basis_get_bytes_per_block(transcoder_texture_format::cTFETC1_RGB) * blocks)) {
if (transcoder.transcode_image_level(data, size, 0, level, dxtBuf, blocks, transcoder_texture_format::cTFETC1_RGB)) {
if (void* rgbBuf = malloc(basis_get_bytes_per_block(transcoder_texture_format::cTFRGBA32) * blocks)) {
// Note: the API expects total pixels here instead of blocks
if (transcoder.transcode_image_level(data, size, 0, level, rgbBuf, descW * descH, transcoder_texture_format::cTFRGBA32)) {
dprintf("Decoded!!!!");
*phbmp = dxtToBitmap(static_cast<uint8_t*>(dxtBuf), descW, descH, fileInfo.m_y_flipped);
*phbmp = rgbToBitmap(static_cast<uint32_t*>(rgbBuf), descW, descH, fileInfo.m_y_flipped);
}
delete dxtBuf;
delete rgbBuf;
}
}
}

View File

@@ -3,122 +3,6 @@
#include <cassert>
#include <cstdio>
//************************* See cubic/texture-dxt.cpp ************************/
/**
* Expands an RGB565 format colour into BGR888.
*
* \note Unlike the original code, which was RGB888, for a Windows bitmap we
* need this is as \e BGR.
*
* \param[in] color RGB565 format colour
* \return a \e bit \e expansion of the supplied colour as 8-bit per channel (with zero alpha)
*/
static uint32_t rgbFrom565(unsigned const color) {
unsigned r = (color >> 11) & 0x1F;
unsigned g = (color >> 5) & 0x3F;
unsigned b = (color >> 0) & 0x1F;
return (((r << 3) | (r >> 2)) << 16)
| (((g << 2) | (g >> 4)) << 8)
| (((b << 3) | (b >> 2)) << 0);
}
/**
* Calculates the DXT decompressor's \e midpoint colour, where the weighting
* is \c 2:1 (the parameters can be exchanged to calculate both midpoints).
* Used by the DXT block decode.
*
* \param[in] color0 \c endpoint colour receiving a double weighting
* \param[in] color1 \c endpoint colour receiving a single weighting
* \return blended colour (excluding alpha)
*/
static uint32_t midpoint21(uint32_t const color0, uint32_t const color1) {
return (((2 * (color0 & 0x0000FF) + (color1 & 0x0000FF)) / 3) & 0x0000FF)
| (((2 * (color0 & 0x00FF00) + (color1 & 0x00FF00)) / 3) & 0x00FF00)
| (((2 * (color0 & 0xFF0000) + (color1 & 0xFF0000)) / 3) & 0xFF0000);
}
/**
* Calculates the DXT decompressor's \e midpoint colour, where the weighting
* is \c 1:1. Used by the DXT block decode.
*
* \param[in] color0 \c endpoint colour (any of the endpoints)
* \param[in] color1 \c endpoint colour (any of the endpoints)
* \return blended colour (excluding alpha)
*/
static uint32_t midpoint11(uint32_t const color0, uint32_t const color1) {
return ((((color0 & 0x0000FF) + (color1 & 0x0000FF)) / 2) & 0x0000FF)
| ((((color0 & 0x00FF00) + (color1 & 0x00FF00)) / 2) & 0x00FF00)
| ((((color0 & 0xFF0000) + (color1 & 0xFF0000)) / 2) & 0xFF0000);
}
/**
* Decodes a DXT1 block.
*
* \note Unlike the original code, which was RGB888, for a Windows bitmap we
* need this is as \e BGR.
*
* \param[in] src start of the encoded data (eight contiguous bytes)
* \param[in] dst destination of the block's top-left pixel
* \param[in] span number of pixels to advance to the next line (usually the texture width)
*/
static void decodeDxt1(const uint8_t* const src, uint32_t* dst, unsigned const span) {
assert(src && dst && span);
/*
* Extract the two 16-bit 'endpoints'. These are little Endian, regardless
* of the platform. Note that the midpoint choices are made against these
* (not the platform Endian RGB/BGR versions) and that (specifically in
* this implementation) DXT1 will always have solid alpha (which we bake
* into the colour table). The color 'codes' are collated here into a
* 32-bit value (which simplifies addressing the bits directly later).
*/
#if defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)
unsigned const color0((src[0] << 0) | (src[1] << 8));
unsigned const color1((src[2] << 0) | (src[3] << 8));
unsigned const ccodes((src[4] << 0) | (src[5] << 8)
| (src[6] << 16) | (src[7] << 24));
#else
unsigned const color0(*reinterpret_cast<const uint16_t*>(src + 0));
unsigned const color1(*reinterpret_cast<const uint16_t*>(src + 2));
unsigned const ccodes(*reinterpret_cast<const uint32_t*>(src + 4));
#endif
uint32_t color[4];
color[0] = 0xFF000000 | rgbFrom565(color0);
color[1] = 0xFF000000 | rgbFrom565(color1);
color[2] = 0xFF000000 | ((color0 > color1)
? midpoint21(color[0], color[1])
: midpoint11(color[0], color[1]));
color[3] = 0xFF000000 | ((color0 > color1)
? midpoint21(color[1], color[0])
: 0);
/*
* The 4x4 block is unrolled. For destinations smaller than 4x4 the pixel
* overwrites here are inefficient, but the overhead isn't enough to worry
* about (when compared with the GL texture upload).
*/
dst[0] = color[(ccodes >> 0) & 0x03];
dst[1] = color[(ccodes >> 2) & 0x03];
dst[2] = color[(ccodes >> 4) & 0x03];
dst[3] = color[(ccodes >> 6) & 0x03];
dst += span;
dst[0] = color[(ccodes >> 8) & 0x03];
dst[1] = color[(ccodes >> 10) & 0x03];
dst[2] = color[(ccodes >> 12) & 0x03];
dst[3] = color[(ccodes >> 14) & 0x03];
dst += span;
dst[0] = color[(ccodes >> 16) & 0x03];
dst[1] = color[(ccodes >> 18) & 0x03];
dst[2] = color[(ccodes >> 20) & 0x03];
dst[3] = color[(ccodes >> 22) & 0x03];
dst += span;
dst[0] = color[(ccodes >> 24) & 0x03];
dst[1] = color[(ccodes >> 26) & 0x03];
dst[2] = color[(ccodes >> 28) & 0x03];
dst[3] = color[(ccodes >> 30) & 0x03];
}
//******************************** Public API ********************************/
void dprintf(char* const fmt, ...) {
va_list args;
char buf[256];
@@ -131,41 +15,39 @@ void dprintf(char* const fmt, ...) {
}
}
HBITMAP dxtToBitmap(const uint8_t* src, uint32_t const imgW, uint32_t const imgH, bool const flip) {
assert(src && imgW && imgH);
HBITMAP rgbToBitmap(const uint32_t* src, uint32_t const imgW, uint32_t const imgH, bool const flip) {
/*
* Creates a bitmap (a DIB) for the passed-in pixel size. Note that
* negation of the height means top-down, origin upper-left, which is the
* regular case.
*
* TODO: 16-bit variant instead?
* TODO: we're growing the nearest 4x4 but not cropping afterwards (what about shrinking and skipping the last blocks?)
*/
uint32_t nearW = (imgW + 3) & ~3;
uint32_t nearH = (imgH + 3) & ~3;
assert(src && imgW && imgH);
BITMAPINFO bmi = {
sizeof(bmi.bmiHeader)
};
bmi.bmiHeader.biWidth = nearW;
bmi.bmiHeader.biHeight = (flip) ? nearH : -static_cast<int32_t>(nearH);
bmi.bmiHeader.biWidth = imgW;
bmi.bmiHeader.biHeight = (flip) ? imgH : -static_cast<int32_t>(imgH);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
void* pixels = NULL;
HBITMAP hbmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &pixels, NULL, 0);
/*
* Decode the BC1 blocks.
* RGBA to BGRA conversion.
*
* Note: we keep the alpha.
*/
if (hbmp && pixels) {
uint32_t* dst = static_cast<uint32_t*>(pixels);
for (unsigned y = 0; y < nearH; y += 4) {
uint32_t* row = dst;
for (unsigned x = 0; x < nearW; x += 4) {
decodeDxt1(src, row, nearW);
src += 8;
row += 4;
for (unsigned y = 0; y < imgH; y++) {
for (unsigned x = 0; x < imgW; x++) {
uint32_t rgba = *src++;
*dst++ = ((rgba & 0x000000FF) << 16)
| ((rgba & 0xFF00FF00) )
| ((rgba & 0x00FF0000) >> 16);
}
dst += 4 * nearW;
}
GdiFlush();
}

View File

@@ -12,11 +12,11 @@
void dprintf(char* const fmt, ...);
/**
* Software decodes BC1 format data.
* Converts raw RGBA data to a Windows BGRA bitmap.
*
* \param[in] src BC1 source blocks (the number of blocks being determined by the image dimensions)
* \param[in] src raw RGBA data
* \param[in] imgW width of the decoded image
* \param[in] imgH height of the decoded image
* \return handle to a bitmap (ownership passed to the caller)
*/
HBITMAP dxtToBitmap(const uint8_t* src, uint32_t const imgW, uint32_t const imgH, bool const flip = false);
HBITMAP rgbToBitmap(const uint32_t* src, uint32_t const imgW, uint32_t const imgH, bool const flip = false);