From 3d40a28a232a52fef44694d30b9432b7bd12134d Mon Sep 17 00:00:00 2001 From: Ivan Mogilko Date: Sun, 5 Jan 2025 21:23:29 +0300 Subject: [PATCH] Common: fix loaded images without alpha converted to 32-bit --- Common/gfx/bitmap.cpp | 7 +++++-- Common/gfx/bitmapdata.h | 7 +++++-- Common/gfx/image_file.cpp | 9 ++++++++- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Common/gfx/bitmap.cpp b/Common/gfx/bitmap.cpp index ee9ca5b7c17..ae3c4846809 100644 --- a/Common/gfx/bitmap.cpp +++ b/Common/gfx/bitmap.cpp @@ -284,7 +284,7 @@ void ReadPixelsFromMemory(Bitmap *dst, const uint8_t *src_buffer, const size_t s // Converts loaded bitmap to the requested color depth, // optionally fixups color palette -static Bitmap *BitmapColorDepthFixup(Bitmap *bmp, int dst_color_depth, RGB *pal) +static Bitmap *BitmapColorDepthFixup(Bitmap *bmp, int dst_color_depth, RGB *pal, bool src_has_alpha) { int bmp_depth = bmp->GetColorDepth(); int dest_depth = get_color_load_depth(bmp_depth, false); @@ -301,6 +301,9 @@ static Bitmap *BitmapColorDepthFixup(Bitmap *bmp, int dst_color_depth, RGB *pal) bmp->WrapAllegroBitmap(al_bmp, false); } + if ((dest_depth == 32) && !src_has_alpha) + BitmapHelper::MakeOpaqueSkipMask(bmp); + /* construct a fake palette if 8-bit mode is not involved */ if ((bmp_depth != 8) && (dest_depth != 8) && pal) generate_332_palette(pal); @@ -322,7 +325,7 @@ Bitmap* LoadBitmap(Stream *in, const String& ext, int dst_color_depth, RGB *pal) if (!bmp) return nullptr; // Perform color depth and palette fixups - Bitmap *fixed_bmp = BitmapColorDepthFixup(bmp, dst_color_depth, pal); + Bitmap *fixed_bmp = BitmapColorDepthFixup(bmp, dst_color_depth, pal, pxbuf.HasAlphaChannel()); if (fixed_bmp != bmp) delete bmp; return fixed_bmp; diff --git a/Common/gfx/bitmapdata.h b/Common/gfx/bitmapdata.h index 3e431be376a..09b48bba3e3 100644 --- a/Common/gfx/bitmapdata.h +++ b/Common/gfx/bitmapdata.h @@ -41,6 +41,7 @@ enum PixelFormat kPxFmt_R5G6B5, // 16-bit R5G6B5, historical 16-bit pixel format in AGS kPxFmt_R8G8B8, // 24-bit RGB (no alpha) kPxFmt_A8R8G8B8, // 32-bit ARGB + kPxFmt_X8R8G8B8, // 32-bit RGB with no valid alpha }; // Returns bits-per-pixel from format @@ -55,6 +56,7 @@ inline int PixelFormatToPixelBits(PixelFormat fmt) case kPxFmt_R5G6B5: return 16; case kPxFmt_R8G8B8: return 24; case kPxFmt_A8R8G8B8: return 32; + case kPxFmt_X8R8G8B8: return 32; default: return 0; } } @@ -64,7 +66,7 @@ inline int PixelFormatToPixelBytes(PixelFormat fmt) return (PixelFormatToPixelBits(fmt) + 7) / 8; } -inline PixelFormat ColorDepthToPixelFormat(int color_depth) +inline PixelFormat ColorDepthToPixelFormat(int color_depth, bool alpha_valid = true) { switch (color_depth) { @@ -74,7 +76,7 @@ inline PixelFormat ColorDepthToPixelFormat(int color_depth) case 15: return kPxFmt_R5G5B5; case 16: return kPxFmt_R5G6B5; case 24: return kPxFmt_R8G8B8; - case 32: return kPxFmt_A8R8G8B8; + case 32: return alpha_valid ? kPxFmt_A8R8G8B8 : kPxFmt_X8R8G8B8; default: return kPxFmt_Undefined; } } @@ -119,6 +121,7 @@ class BitmapData operator bool() const { return _cbuf != nullptr; } inline PixelFormat GetFormat() const { return _format; } + inline bool HasAlphaChannel() const { return _format == kPxFmt_A8R8G8B8; } inline int GetColorDepth() const { return _bitsPerPixel; } inline int GetWidth() const { return _width; } inline int GetHeight() const { return _height; } diff --git a/Common/gfx/image_file.cpp b/Common/gfx/image_file.cpp index 8b958c5adb0..67ef3975d1d 100644 --- a/Common/gfx/image_file.cpp +++ b/Common/gfx/image_file.cpp @@ -559,6 +559,7 @@ PixelBuffer LoadBMP(Stream *in, RGB *pal) { int rMask = 0; int gMask = 0; int bMask = 0; + bool hasAlpha = false; const soff_t format_at = in->GetPosition(); // starting offset @@ -610,6 +611,8 @@ PixelBuffer LoadBMP(Stream *in, RGB *pal) { rMask = in->ReadInt32(); gMask = in->ReadInt32(); bMask = in->ReadInt32(); + // TODO: might need to support alpha bits, if it's present in the header + // also set hasAlpha = true in such case } else { bmp_read_palette(hdr.offsetBits - 54, pal, in, false); } @@ -643,7 +646,11 @@ PixelBuffer LoadBMP(Stream *in, RGB *pal) { if (bpp < 8) bpp = 8; - PixelBuffer pxdata(w, h, ColorDepthToPixelFormat(bpp)); + // TODO: if we support loading 32-bit ARGB images (existing old BMP loader code doesn't), + // then we might also have to test if there's ANY alpha present in the image + // AFTER decoding the pixel data, and adjust the format info (?). + + PixelBuffer pxdata(w, h, ColorDepthToPixelFormat(bpp, hasAlpha)); if (!pxdata) { return {}; }