mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-09-18 16:34:29 +00:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user