| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "gfx/bitmap/bitmapUtils.h"
- #include "platform/platform.h"
- #ifndef STB_IMAGE_RESIZE2_IMPLEMENTATION
- #define STB_IMAGE_RESIZE2_IMPLEMENTATION
- #define STBIR_PROFILE
- #include "gfx/bitmap/loaders/stb/stb_image_resize2.h"
- #endif // !STB_IMAGE_RESIZE2_IMPLEMENTATION
- void bitmapExtrude5551_c(const void *srcMip, void *mip, U32 srcHeight, U32 srcWidth)
- {
- const U16 *src = (const U16 *) srcMip;
- U16 *dst = (U16 *) mip;
- U32 stride = srcHeight != 1 ? srcWidth : 0;
- U32 width = srcWidth >> 1;
- U32 height = srcHeight >> 1;
- if (width == 0) width = 1;
- if (height == 0) height = 1;
- if (srcWidth != 1)
- {
- for(U32 y = 0; y < height; y++)
- {
- for(U32 x = 0; x < width; x++)
- {
- U32 a = src[0];
- U32 b = src[1];
- U32 c = src[stride];
- U32 d = src[stride+1];
- #if defined(TORQUE_BIG_ENDIAN)
- dst[x] = ((( (a >> 10) + (b >> 10) + (c >> 10) + (d >> 10)) >> 2) << 10) |
- ((( ((a >> 5) & 0x1F) + ((b >> 5) & 0x1F) + ((c >> 5) & 0x1F) + ((d >> 5) & 0x1F)) >> 2) << 5) |
- ((( ((a >> 0) & 0x1F) + ((b >> 0) & 0x1F) + ((c >> 0) & 0x1F) + ((d >> 0) & 0x1F)) >> 2) << 0);
- #else
- dst[x] = ((( (a >> 11) + (b >> 11) + (c >> 11) + (d >> 11)) >> 2) << 11) |
- ((( ((a >> 6) & 0x1F) + ((b >> 6) & 0x1F) + ((c >> 6) & 0x1F) + ((d >> 6) & 0x1F)) >> 2) << 6) |
- ((( ((a >> 1) & 0x1F) + ((b >> 1) & 0x1F) + ((c >> 1) & 0x1F) + ((d >> 1) & 0x1F)) >> 2) << 1);
- #endif
- src += 2;
- }
- src += stride;
- dst += width;
- }
- }
- else
- {
- for(U32 y = 0; y < height; y++)
- {
- U32 a = src[0];
- U32 c = src[stride];
- #if defined(TORQUE_BIG_ENDIAN)
- dst[y] = ((( (a >> 10) + (c >> 10)) >> 1) << 10) |
- ((( ((a >> 5) & 0x1F) + ((c >> 5) & 0x1f)) >> 1) << 5) |
- ((( ((a >> 0) & 0x1F) + ((c >> 0) & 0x1f)) >> 1) << 0);
- #else
- dst[y] = ((( (a >> 11) + (c >> 11)) >> 1) << 11) |
- ((( ((a >> 6) & 0x1f) + ((c >> 6) & 0x1f)) >> 1) << 6) |
- ((( ((a >> 1) & 0x1F) + ((c >> 1) & 0x1f)) >> 1) << 1);
- #endif
- src += 1 + stride;
- }
- }
- }
- //--------------------------------------------------------------------------
- template <typename T>
- void bitmapExtrudeGeneric(
- const T* src, T* dst,
- U32 srcWidth, U32 srcHeight,
- U32 channels, U32 bpp)
- {
- U32 srcRowStride = srcHeight != 1 ? (srcWidth * bpp) / sizeof(T) : 0;
- U32 dstWidth = srcWidth > 1 ? srcWidth / 2 : 1;
- U32 dstHeight = srcHeight > 1 ? srcHeight / 2 : 1;
- U32 dstRowStride = dstHeight != 1 ? (dstWidth * bpp) / sizeof(T) : 0;
- for (U32 y = 0; y < dstHeight; ++y)
- {
- for (U32 x = 0; x < dstWidth; ++x)
- {
- for (U32 c = 0; c < channels; ++c)
- {
- U32 x0 = x * 2;
- U32 y0 = y * 2;
- U32 x1 = (x0 + 1 < srcWidth) ? x0 + 1 : x0;
- U32 y1 = (y0 + 1 < srcHeight) ? y0 + 1 : y0;
- if constexpr (std::is_floating_point_v<T>)
- {
- T sum = 0;
- sum += src[y0 * srcRowStride + x0 * channels + c];
- sum += src[y0 * srcRowStride + x1 * channels + c];
- sum += src[y1 * srcRowStride + x0 * channels + c];
- sum += src[y1 * srcRowStride + x1 * channels + c];
- dst[y * dstRowStride + x * channels + c] = sum * 0.25f;
- }
- else
- {
- U32 sum = 0;
- sum += src[y0 * srcRowStride + x0 * channels + c];
- sum += src[y0 * srcRowStride + x1 * channels + c];
- sum += src[y1 * srcRowStride + x0 * channels + c];
- sum += src[y1 * srcRowStride + x1 * channels + c];
- dst[y * dstRowStride + x * channels + c] = T((sum + 2) >> 2);
- }
- }
- }
- }
- }
- // 8-bit RGBA
- auto bitmapExtrudeU8_RGBA = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
- bitmapExtrudeGeneric((const U8*)src, (U8*)dst, w, h, 4, bpp);
- };
- // 16-bit RGBA (U16 / F32 stored as U16)
- auto bitmapExtrudeU16_RGBA = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
- bitmapExtrudeGeneric((const U16*)src, (U16*)dst, w, h, 4, bpp);
- };
- // 32-bit float RGBA
- auto bitmapExtrudeF32_RGBA = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
- bitmapExtrudeGeneric((const F32*)src, (F32*)dst, w, h, 4, bpp);
- };
- // RGB U8
- auto bitmapExtrudeU8_RGB = [](const void* src, void* dst, U32 h, U32 w, U32 bpp) {
- bitmapExtrudeGeneric((const U8*)src, (U8*)dst, w, h, 3, bpp);
- };
- void (*bitmapExtrude5551)(const void* srcMip, void* mip, U32 height, U32 width) = bitmapExtrude5551_c;
- void (*bitmapExtrudeRGB)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU8_RGB;
- void (*bitmapExtrudeRGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU8_RGBA;
- void (*bitmapExtrude16BitRGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU16_RGBA;
- void (*bitmapExtrudeFPRGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeU16_RGBA;
- void (*bitmapExtrudeF32RGBA)(const void* srcMip, void* mip, U32 srcHeight, U32 srcWidth, U32 bpp) = bitmapExtrudeF32_RGBA;
- struct StbResizeDesc
- {
- stbir_datatype datatype;
- stbir_pixel_layout layout;
- U32 bytesPerPixel;
- };
- inline bool getStbResizeDesc(GFXFormat fmt, StbResizeDesc& out)
- {
- switch (fmt)
- {
- // ---- 1 channel ----
- case GFXFormatA8:
- case GFXFormatL8:
- out = { STBIR_TYPE_UINT8, STBIR_1CHANNEL, 1 };
- return true;
- case GFXFormatL16:
- out = { STBIR_TYPE_UINT16, STBIR_1CHANNEL, 2 };
- return true;
- case GFXFormatR16F:
- out = { STBIR_TYPE_HALF_FLOAT, STBIR_1CHANNEL, 2 };
- return true;
- case GFXFormatR32F:
- out = { STBIR_TYPE_FLOAT, STBIR_1CHANNEL, 4 };
- return true;
- // ---- 2 channel ----
- case GFXFormatA8L8:
- out = { STBIR_TYPE_UINT8, STBIR_2CHANNEL, 2 };
- return true;
- case GFXFormatR16G16:
- out = { STBIR_TYPE_UINT16, STBIR_2CHANNEL, 4 };
- return true;
- case GFXFormatR16G16F:
- out = { STBIR_TYPE_HALF_FLOAT, STBIR_2CHANNEL, 4 };
- return true;
- // ---- RGB ----
- case GFXFormatR8G8B8:
- out = { STBIR_TYPE_UINT8, STBIR_RGB, 3 };
- return true;
- case GFXFormatR8G8B8_SRGB:
- out = { STBIR_TYPE_UINT8_SRGB, STBIR_RGB, 3 };
- return true;
- // ---- RGBA / RGBX ----
- case GFXFormatR8G8B8A8:
- case GFXFormatR8G8B8X8:
- out = { STBIR_TYPE_UINT8, STBIR_RGBA, 4 };
- return true;
- case GFXFormatR8G8B8A8_SRGB:
- out = { STBIR_TYPE_UINT8_SRGB_ALPHA, STBIR_RGBA, 4 };
- return true;
- case GFXFormatB8G8R8A8:
- out = { STBIR_TYPE_UINT8, STBIR_BGRA, 4 };
- return true;
- // ---- 16-bit RGBA ----
- case GFXFormatR16G16B16A16:
- out = { STBIR_TYPE_UINT16, STBIR_RGBA, 8 };
- return true;
- case GFXFormatR16G16B16A16F:
- out = { STBIR_TYPE_HALF_FLOAT, STBIR_RGBA, 8 };
- return true;
- // ---- 32-bit RGBA ----
- case GFXFormatR32G32B32A32F:
- out = { STBIR_TYPE_FLOAT, STBIR_RGBA, 16 };
- return true;
- default:
- return false;
- }
- }
- void bitmapStbResizeToOutput(const void* src, U32 srcHeight, U32 srcWidth, void* out, U32 outHeight, U32 outWidth, U32 bpp, GFXFormat format)
- {
- StbResizeDesc desc;
- if (!getStbResizeDesc(format, desc))
- {
- return;
- }
- const int srcStride = srcWidth * bpp;
- const int dstStride = outWidth * bpp;
- stbir_resize(
- src,
- srcWidth,
- srcHeight,
- srcStride,
- out,
- outWidth,
- outHeight,
- dstStride,
- desc.layout,
- desc.datatype,
- STBIR_EDGE_CLAMP,
- STBIR_FILTER_MITCHELL);
- }
- void(*bitmapResizeToOutput)(const void* src, U32 srcHeight, U32 srcWidth, void* out, U32 outHeight, U32 outWidth, U32 bpp, GFXFormat format) = bitmapStbResizeToOutput;
- //--------------------------------------------------------------------------------
- // Format description
- //--------------------------------------------------------------------------------
- // Channel semantics
- enum ChannelSemantic : U8
- {
- CH_NONE,
- CH_L,
- CH_A,
- CH_R,
- CH_G,
- CH_B
- };
- //--------------------------------------------------------------------------------
- // Bitmap format descriptor
- struct GBitmapFormatDesc
- {
- U8 channels;
- ChannelSemantic semantic[4]; // per-channel meaning
- stbir_datatype datatype;
- bool srgb;
- bool premultiplied;
- bool isFloat;
- U8 bytesPerChannel;
- bool is8() const { return !isFloat && bytesPerChannel == 1; }
- bool is16() const { return !isFloat && bytesPerChannel == 2; }
- };
- //--------------------------------------------------------------------------------
- // Table mapping GFXFormat -> descriptor
- GBitmapFormatDesc getFormatDesc(GFXFormat fmt)
- {
- switch (fmt)
- {
- // 8-bit formats
- case GFXFormatA8:
- return { 1, {CH_A, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatL8:
- return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatA4L4:
- return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- // 16-bit formats
- case GFXFormatR5G6B5:
- return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatR5G5B5A1:
- return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatR5G5B5X1:
- return { 4, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatA8L8:
- return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatL16:
- return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
- case GFXFormatR16F:
- return { 1, {CH_R, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_HALF_FLOAT, false, false, true, 2 };
- case GFXFormatD16:
- return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
- // 24-bit formats
- case GFXFormatR8G8B8:
- return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatR8G8B8_SRGB:
- return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8_SRGB, true, false, false, 1 };
- // 32-bit formats
- case GFXFormatR8G8B8A8:
- case GFXFormatR8G8B8X8:
- return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatB8G8R8A8:
- return { 4, {CH_B, CH_G, CH_R, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
- case GFXFormatR8G8B8A8_SRGB:
- return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8_SRGB_ALPHA, true, false, false, 1 };
- case GFXFormatR16G16:
- return { 2, {CH_R, CH_G, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
- case GFXFormatR16G16F:
- return { 2, {CH_R, CH_G, CH_NONE, CH_NONE}, STBIR_TYPE_HALF_FLOAT, false, false, true, 2 };
- // 64-bit formats
- case GFXFormatR16G16B16A16:
- return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT16, false, false, false, 2 };
- case GFXFormatR16G16B16A16F:
- return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_HALF_FLOAT, false, false, true, 2 };
- // 128-bit formats
- case GFXFormatR32G32B32A32F:
- return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_FLOAT, false, false, true, 4 };
- default: // fallback
- return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
- }
- }
- //--------------------------------------------------------------------------------
- // Conversion plan
- struct ConversionPlan
- {
- bool bitDepthChange;
- bool channelRepack;
- bool colorspaceChange;
- };
- ConversionPlan decideConversion(const GBitmapFormatDesc& src, const GBitmapFormatDesc& dst)
- {
- ConversionPlan plan = {};
- plan.bitDepthChange = src.bytesPerChannel != dst.bytesPerChannel || src.isFloat != dst.isFloat;
- plan.channelRepack = src.channels != dst.channels || dMemcmp(src.semantic, dst.semantic, sizeof(src.semantic)) != 0;
- plan.colorspaceChange = src.srgb != dst.srgb;
- return plan;
- }
- //--------------------------------------------------------------------------------
- // Linear representation
- struct LinearPixel
- {
- float r = 0.f, g = 0.f, b = 0.f, a = 1.f;
- };
- inline float srgbToLinear(float c)
- {
- return (c <= 0.04045f) ? c / 12.92f : powf((c + 0.055f) / 1.055f, 2.4f);
- }
- inline float linearToSrgb(float c)
- {
- return (c <= 0.0031308f) ? c * 12.92f : 1.055f * powf(c, 1.f / 2.4f) - 0.055f;
- }
- //--------------------------------------------------------------------------------
- // Load a pixel from src format into LinearPixel
- static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fmt, U32 index)
- {
- LinearPixel p;
- const U8* base = (const U8*)src + index * fmt.channels * fmt.bytesPerChannel;
- for (U32 c = 0; c < fmt.channels; ++c)
- {
- float v = 0.f;
- if (fmt.is8())
- v = float(base[c]) / 255.f;
- else if (fmt.is16())
- v = float(convert16To8(*(const U16*)(base + c * 2))) / 255.f;
- else if (fmt.isFloat)
- {
- if (fmt.bytesPerChannel == 2) // half float
- v = convertHalfToFloat(*(const U16*)(base + c * 2));
- else // full float
- v = *(const float*)(base + c * 4);
- }
- if (fmt.srgb && fmt.semantic[c] != CH_A)
- v = srgbToLinear(v);
- switch (fmt.semantic[c])
- {
- case CH_R: p.r = v; break;
- case CH_G: p.g = v; break;
- case CH_B: p.b = v; break;
- case CH_A: p.a = v; break;
- case CH_L: p.r = p.g = p.b = v; break;
- default: break;
- }
- }
- return p;
- }
- //--------------------------------------------------------------------------------
- // Store a LinearPixel into dst format
- static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index, const LinearPixel& p)
- {
- U8* base = (U8*)dst + index * fmt.channels * fmt.bytesPerChannel;
- for (U32 c = 0; c < fmt.channels; ++c)
- {
- float v = 0.f;
- switch (fmt.semantic[c])
- {
- case CH_R: v = p.r; break;
- case CH_G: v = p.g; break;
- case CH_B: v = p.b; break;
- case CH_A: v = p.a; break;
- case CH_L: v = (p.r + p.g + p.b) / 3.f; break;
- default: break;
- }
- if (fmt.srgb && fmt.semantic[c] != CH_A)
- v = linearToSrgb(v);
- if (fmt.is8())
- base[c] = uint8_t(mClamp(v * 255.f, 0.f, 255.f));
- else if (fmt.is16())
- *(U16*)(base + c * 2) = convert8To16(uint8_t(mClamp(v * 255.f, 0.f, 255.f)));
- else if (fmt.isFloat)
- {
- if (fmt.bytesPerChannel == 2) // half float
- *(U16*)(base + c * 2) = convertFloatToHalf(v);
- else
- *(float*)(base + c * 4) = v;
- }
- }
- }
- //--------------------------------------------------------------------------------
- // Main generalized converter
- bool bitmapConvertFormat(U8** srcBuffer, U32 pixels, const GBitmapFormatDesc& srcFmt, const GBitmapFormatDesc& dstFmt)
- {
- ConversionPlan plan = decideConversion(srcFmt, dstFmt);
- if (!plan.bitDepthChange && !plan.channelRepack && !plan.colorspaceChange)
- return true; // nothing to do
- void* dstBuffer = *srcBuffer;
- if (plan.bitDepthChange || plan.channelRepack)
- dstBuffer = new U8[pixels * dstFmt.channels * dstFmt.bytesPerChannel];
- for (U32 i = 0; i < pixels; ++i)
- {
- LinearPixel p = loadPixel(*srcBuffer, srcFmt, i);
- storePixel(dstBuffer, dstFmt, i, p);
- }
- if (dstBuffer != *srcBuffer)
- {
- delete[](U8*)* srcBuffer;
- *srcBuffer = (U8*)dstBuffer;
- }
- return true;
- }
- //--------------------------------------------------------------------------------
- // Entry point for GBitmap::setFormat
- bool bitmapALLConvertToOutput(U8** src, U32 pixels, GFXFormat srcFormat, GFXFormat dstFormat)
- {
- const GBitmapFormatDesc& srcFmt = getFormatDesc(srcFormat);
- const GBitmapFormatDesc& dstFmt = getFormatDesc(dstFormat);
- return bitmapConvertFormat(src, pixels, srcFmt, dstFmt);
- }
- bool(*bitmapConvertToOutput)(U8** src, U32 pixels, GFXFormat srcFormat, GFXFormat dstFormat) = bitmapALLConvertToOutput;
- //--------------------------------------------------------------------------
- void bitmapConvertRGB_to_1555_c(U8 *src, U32 pixels)
- {
- U16 *dst = (U16 *)src;
- for(U32 j = 0; j < pixels; j++)
- {
- U32 r = src[0] >> 3;
- U32 g = src[1] >> 3;
- U32 b = src[2] >> 3;
- #if defined(TORQUE_BIG_ENDIAN)
- *dst++ = 0x8000 | (b << 10) | (g << 5) | (r << 0);
- #else
- *dst++ = b | (g << 5) | (r << 10) | 0x8000;
- #endif
- src += 3;
- }
- }
- void (*bitmapConvertRGB_to_1555)(U8 *src, U32 pixels) = bitmapConvertRGB_to_1555_c;
- //------------------------------------------------------------------------------
- void bitmapConvertRGB_to_5551_c(U8 *src, U32 pixels)
- {
- U16 *dst = (U16 *)src;
- for(U32 j = 0; j < pixels; j++)
- {
- U32 r = src[0] >> 3;
- U32 g = src[1] >> 3;
- U32 b = src[2] >> 3;
- #if defined(TORQUE_BIG_ENDIAN)
- *dst++ = (1 << 15) | (b << 10) | (g << 5) | (r << 0);
- #else
- *dst++ = (b << 1) | (g << 6) | (r << 11) | 1;
- #endif
- src += 3;
- }
- }
- void (*bitmapConvertRGB_to_5551)(U8 *src, U32 pixels) = bitmapConvertRGB_to_5551_c;
- //------------------------------------------------------------------------------
- void bitmapConvertRGB_to_RGBX_c( U8 **src, U32 pixels )
- {
- const U8 *oldBits = *src;
- U8 *newBits = new U8[pixels * 4];
- dMemset( newBits, 0xFF, pixels * 4 ); // This is done to set alpha values -patw
- // Copy the bits over to the new memory
- for( U32 i = 0; i < pixels; i++ )
- dMemcpy( &newBits[i * 4], &oldBits[i * 3], sizeof(U8) * 3 );
- // Now hose the old bits
- delete [] *src;
- *src = newBits;
- }
- void (*bitmapConvertRGB_to_RGBX)( U8 **src, U32 pixels ) = bitmapConvertRGB_to_RGBX_c;
- //------------------------------------------------------------------------------
- void bitmapConvertRGBX_to_RGB_c( U8 **src, U32 pixels )
- {
- const U8 *oldBits = *src;
- U8 *newBits = new U8[pixels * 3];
- // Copy the bits over to the new memory
- for( U32 i = 0; i < pixels; i++ )
- dMemcpy( &newBits[i * 3], &oldBits[i * 4], sizeof(U8) * 3 );
- // Now hose the old bits
- delete [] *src;
- *src = newBits;
- }
- void (*bitmapConvertRGBX_to_RGB)( U8 **src, U32 pixels ) = bitmapConvertRGBX_to_RGB_c;
- //------------------------------------------------------------------------------
- void bitmapConvertA8_to_RGBA_c( U8 **src, U32 pixels )
- {
- const U8 *oldBits = *src;
- U8 *newBits = new U8[pixels * 4];
- // Zero new bits
- dMemset( newBits, 0, pixels * 4 );
- // Copy Alpha values
- for( U32 i = 0; i < pixels; i++ )
- newBits[i * 4 + 3] = oldBits[i];
- // Now hose the old bits
- delete [] *src;
- *src = newBits;
- }
- void (*bitmapConvertA8_to_RGBA)( U8 **src, U32 pixels ) = bitmapConvertA8_to_RGBA_c;
|