From 582d8c8488063df1d969a1335577cd331c74d69d Mon Sep 17 00:00:00 2001 From: Carl Woffenden Date: Thu, 3 Oct 2019 19:26:46 +0200 Subject: [PATCH] Switched to using Basis's own RGB transcode Removed the DXT->RGB conversion now that the transcoder has an RGB option. --- contrib/previewers/win/basisthumbprovider.cpp | 9 +- contrib/previewers/win/helpers.cpp | 144 ++---------------- contrib/previewers/win/helpers.h | 6 +- 3 files changed, 21 insertions(+), 138 deletions(-) diff --git a/contrib/previewers/win/basisthumbprovider.cpp b/contrib/previewers/win/basisthumbprovider.cpp index bb7cf2f..6aaa07b 100644 --- a/contrib/previewers/win/basisthumbprovider.cpp +++ b/contrib/previewers/win/basisthumbprovider.cpp @@ -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(dxtBuf), descW, descH, fileInfo.m_y_flipped); + *phbmp = rgbToBitmap(static_cast(rgbBuf), descW, descH, fileInfo.m_y_flipped); } - delete dxtBuf; + delete rgbBuf; } } } diff --git a/contrib/previewers/win/helpers.cpp b/contrib/previewers/win/helpers.cpp index d592ac4..937601c 100644 --- a/contrib/previewers/win/helpers.cpp +++ b/contrib/previewers/win/helpers.cpp @@ -3,122 +3,6 @@ #include #include -//************************* 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(src + 0)); - unsigned const color1(*reinterpret_cast(src + 2)); - unsigned const ccodes(*reinterpret_cast(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(nearH); + bmi.bmiHeader.biWidth = imgW; + bmi.bmiHeader.biHeight = (flip) ? imgH : -static_cast(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(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(); } diff --git a/contrib/previewers/win/helpers.h b/contrib/previewers/win/helpers.h index 1a4a955..691d561 100644 --- a/contrib/previewers/win/helpers.h +++ b/contrib/previewers/win/helpers.h @@ -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);