mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-13 07:34:45 +00:00
Merge pull request #1650 from marauder2k9-torque/development
Some checks failed
Linux Build / ${{matrix.config.name}} (map[build_type:Release cc:gcc cxx:g++ generator:Ninja name:Ubuntu Latest GCC]) (push) Has been cancelled
MacOSX Build / ${{matrix.config.name}} (map[build_type:Release cc:clang cxx:clang++ generator:Ninja name:MacOSX Latest Clang]) (push) Has been cancelled
Windows Build / ${{matrix.config.name}} (map[build_type:Release cc:cl cxx:cl environment_script:C:/Program Files (x86)/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat generator:Visual Studio 17 2022 name:Windows Latest MSVC]) (push) Has been cancelled
Some checks failed
Linux Build / ${{matrix.config.name}} (map[build_type:Release cc:gcc cxx:g++ generator:Ninja name:Ubuntu Latest GCC]) (push) Has been cancelled
MacOSX Build / ${{matrix.config.name}} (map[build_type:Release cc:clang cxx:clang++ generator:Ninja name:MacOSX Latest Clang]) (push) Has been cancelled
Windows Build / ${{matrix.config.name}} (map[build_type:Release cc:cl cxx:cl environment_script:C:/Program Files (x86)/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat generator:Visual Studio 17 2022 name:Windows Latest MSVC]) (push) Has been cancelled
Update bitmapUtils.cpp
This commit is contained in:
commit
199ca6b3af
1 changed files with 171 additions and 7 deletions
|
|
@ -288,6 +288,13 @@ enum ChannelSemantic : U8
|
||||||
CH_B
|
CH_B
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PackedChannelDesc
|
||||||
|
{
|
||||||
|
ChannelSemantic semantic;
|
||||||
|
U8 bits;
|
||||||
|
U8 shift;
|
||||||
|
};
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// Bitmap format descriptor
|
// Bitmap format descriptor
|
||||||
struct GBitmapFormatDesc
|
struct GBitmapFormatDesc
|
||||||
|
|
@ -299,7 +306,9 @@ struct GBitmapFormatDesc
|
||||||
bool premultiplied;
|
bool premultiplied;
|
||||||
bool isFloat;
|
bool isFloat;
|
||||||
U8 bytesPerChannel;
|
U8 bytesPerChannel;
|
||||||
|
bool isPacked = false;
|
||||||
|
U8 bytesPerPixel = 0;
|
||||||
|
PackedChannelDesc packed[4] = {};
|
||||||
bool is8() const { return !isFloat && bytesPerChannel == 1; }
|
bool is8() const { return !isFloat && bytesPerChannel == 1; }
|
||||||
bool is16() const { return !isFloat && bytesPerChannel == 2; }
|
bool is16() const { return !isFloat && bytesPerChannel == 2; }
|
||||||
};
|
};
|
||||||
|
|
@ -316,17 +325,47 @@ GBitmapFormatDesc getFormatDesc(GFXFormat fmt)
|
||||||
case GFXFormatL8:
|
case GFXFormatL8:
|
||||||
return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
||||||
case GFXFormatA4L4:
|
case GFXFormatA4L4:
|
||||||
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 1,
|
||||||
|
{
|
||||||
|
{ CH_L, 4, 0 }, // CH_L must be declared before CH_A
|
||||||
|
{ CH_A, 4, 4 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 16-bit formats
|
// 16-bit formats
|
||||||
case GFXFormatR5G6B5:
|
case GFXFormatR5G6B5:
|
||||||
return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
return { 3, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||||
|
{
|
||||||
|
{ CH_R, 5, 11 },
|
||||||
|
{ CH_G, 6, 5 },
|
||||||
|
{ CH_B, 5, 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
case GFXFormatR5G5B5A1:
|
case GFXFormatR5G5B5A1:
|
||||||
return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
return { 4, {CH_R, CH_G, CH_B, CH_A}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||||
|
{
|
||||||
|
{ CH_R, 5, 11 },
|
||||||
|
{ CH_G, 5, 6 },
|
||||||
|
{ CH_B, 5, 1 },
|
||||||
|
{ CH_A, 1, 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
case GFXFormatR5G5B5X1:
|
case GFXFormatR5G5B5X1:
|
||||||
return { 4, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
return { 4, {CH_R, CH_G, CH_B, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||||
|
{
|
||||||
|
{ CH_R, 5, 11 },
|
||||||
|
{ CH_G, 5, 6 },
|
||||||
|
{ CH_B, 5, 1 },
|
||||||
|
{ CH_A, 1, 0 }
|
||||||
|
}
|
||||||
|
};
|
||||||
case GFXFormatA8L8:
|
case GFXFormatA8L8:
|
||||||
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 1 };
|
return { 2, {CH_L, CH_A, CH_NONE, CH_NONE}, STBIR_TYPE_UINT8, false, false, false, 0, true, 2,
|
||||||
|
{
|
||||||
|
{ CH_L, 8, 0 }, // CH_L must be declared before CH_A
|
||||||
|
{ CH_A, 8, 8 }
|
||||||
|
}
|
||||||
|
};
|
||||||
case GFXFormatL16:
|
case GFXFormatL16:
|
||||||
return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
|
return { 1, {CH_L, CH_NONE, CH_NONE, CH_NONE}, STBIR_TYPE_UINT16, false, false, false, 2 };
|
||||||
case GFXFormatR16F:
|
case GFXFormatR16F:
|
||||||
|
|
@ -403,10 +442,73 @@ inline float linearToSrgb(float c)
|
||||||
return (c <= 0.0031308f) ? c * 12.92f : 1.055f * powf(c, 1.f / 2.4f) - 0.055f;
|
return (c <= 0.0031308f) ? c * 12.92f : 1.055f * powf(c, 1.f / 2.4f) - 0.055f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline LinearPixel loadPackedPixel(
|
||||||
|
const void* src,
|
||||||
|
const GBitmapFormatDesc& fmt,
|
||||||
|
U32 index)
|
||||||
|
{
|
||||||
|
LinearPixel p;
|
||||||
|
p.r = p.g = p.b = 0.f;
|
||||||
|
p.a = 1.f;
|
||||||
|
|
||||||
|
const U8* base = (const U8*)src + index * fmt.bytesPerPixel;
|
||||||
|
|
||||||
|
U32 raw = 0;
|
||||||
|
dMemcpy(&raw, base, fmt.bytesPerPixel);
|
||||||
|
|
||||||
|
#ifdef TORQUE_BIG_ENDIAN
|
||||||
|
if (fmt.bytesPerPixel == 2)
|
||||||
|
raw = convertLEndianToHost((U16)raw);
|
||||||
|
else if (fmt.bytesPerPixel == 4)
|
||||||
|
raw = convertLEndianToHost((U32)raw);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (U32 i = 0; i < fmt.channels; ++i)
|
||||||
|
{
|
||||||
|
const PackedChannelDesc& ch = fmt.packed[i];
|
||||||
|
|
||||||
|
U32 mask = (1u << ch.bits) - 1u;
|
||||||
|
U32 v = (raw >> ch.shift) & mask;
|
||||||
|
|
||||||
|
// Expand to 8-bit exactly like GBitmap getColor code
|
||||||
|
U8 expanded8;
|
||||||
|
if (ch.bits == 5)
|
||||||
|
expanded8 = (v << 3) | (v >> 2);
|
||||||
|
else if (ch.bits == 6)
|
||||||
|
expanded8 = (v << 2) | (v >> 4);
|
||||||
|
else if (ch.bits == 4)
|
||||||
|
expanded8 = v * 17;
|
||||||
|
else if (ch.bits == 1)
|
||||||
|
expanded8 = v ? 255 : 0;
|
||||||
|
else // 8-bit
|
||||||
|
expanded8 = (U8)v;
|
||||||
|
|
||||||
|
float f = expanded8 / 255.f;
|
||||||
|
|
||||||
|
switch (ch.semantic)
|
||||||
|
{
|
||||||
|
case CH_R: p.r = f; break;
|
||||||
|
case CH_G: p.g = f; break;
|
||||||
|
case CH_B: p.b = f; break;
|
||||||
|
case CH_A: p.a = f; break;
|
||||||
|
case CH_L:
|
||||||
|
p.r = p.g = p.b = f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// Load a pixel from src format into LinearPixel
|
// Load a pixel from src format into LinearPixel
|
||||||
static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fmt, U32 index)
|
static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fmt, U32 index)
|
||||||
{
|
{
|
||||||
|
if (fmt.isPacked)
|
||||||
|
return loadPackedPixel(src, fmt, index);
|
||||||
|
|
||||||
LinearPixel p;
|
LinearPixel p;
|
||||||
const U8* base = (const U8*)src + index * fmt.channels * fmt.bytesPerChannel;
|
const U8* base = (const U8*)src + index * fmt.channels * fmt.bytesPerChannel;
|
||||||
|
|
||||||
|
|
@ -441,10 +543,72 @@ static inline LinearPixel loadPixel(const void* src, const GBitmapFormatDesc& fm
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void storePackedPixel(
|
||||||
|
void* dst,
|
||||||
|
const GBitmapFormatDesc& fmt,
|
||||||
|
U32 index,
|
||||||
|
const LinearPixel& p)
|
||||||
|
{
|
||||||
|
U32 raw = 0;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < fmt.channels; ++i)
|
||||||
|
{
|
||||||
|
const PackedChannelDesc& ch = fmt.packed[i];
|
||||||
|
|
||||||
|
float v = 0.f;
|
||||||
|
switch (ch.semantic)
|
||||||
|
{
|
||||||
|
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; break; // legacy behavior
|
||||||
|
default: continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp
|
||||||
|
v = mClamp(v, 0.f, 1.f);
|
||||||
|
|
||||||
|
// Canonical float → U8
|
||||||
|
U32 expanded8 = U32(v * 255.f + 0.5f);
|
||||||
|
|
||||||
|
// Contract to bit depth EXACTLY like Gbitmap setColor code
|
||||||
|
U32 maxv = (1u << ch.bits) - 1u;
|
||||||
|
U32 iv;
|
||||||
|
|
||||||
|
if (ch.bits == 8)
|
||||||
|
iv = expanded8;
|
||||||
|
else
|
||||||
|
iv = expanded8 * maxv / 255;
|
||||||
|
|
||||||
|
raw |= (iv & maxv) << ch.shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TORQUE_BIG_ENDIAN
|
||||||
|
if (fmt.bytesPerPixel == 2)
|
||||||
|
{
|
||||||
|
U16 v = convertLEndianToHost((U16)raw);
|
||||||
|
dMemcpy((U8*)dst + index * fmt.bytesPerPixel, &v, 2);
|
||||||
|
}
|
||||||
|
else if (fmt.bytesPerPixel == 4)
|
||||||
|
{
|
||||||
|
U32 v = convertLEndianToHost(raw);
|
||||||
|
dMemcpy((U8*)dst + index * fmt.bytesPerPixel, &v, 4);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
dMemcpy((U8*)dst + index * fmt.bytesPerPixel, &raw, fmt.bytesPerPixel);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
// Store a LinearPixel into dst format
|
// Store a LinearPixel into dst format
|
||||||
static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index, const LinearPixel& p)
|
static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index, const LinearPixel& p)
|
||||||
{
|
{
|
||||||
|
if (fmt.isPacked)
|
||||||
|
{
|
||||||
|
storePackedPixel(dst, fmt, index, p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
U8* base = (U8*)dst + index * fmt.channels * fmt.bytesPerChannel;
|
U8* base = (U8*)dst + index * fmt.channels * fmt.bytesPerChannel;
|
||||||
for (U32 c = 0; c < fmt.channels; ++c)
|
for (U32 c = 0; c < fmt.channels; ++c)
|
||||||
{
|
{
|
||||||
|
|
@ -455,7 +619,7 @@ static inline void storePixel(void* dst, const GBitmapFormatDesc& fmt, U32 index
|
||||||
case CH_G: v = p.g; break;
|
case CH_G: v = p.g; break;
|
||||||
case CH_B: v = p.b; break;
|
case CH_B: v = p.b; break;
|
||||||
case CH_A: v = p.a; break;
|
case CH_A: v = p.a; break;
|
||||||
case CH_L: v = (p.r + p.g + p.b) / 3.f; break;
|
case CH_L: v = p.r; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue