From 88e737c6f4d9c46cac22c2742da338e424b7082b Mon Sep 17 00:00:00 2001 From: thrust26 Date: Thu, 17 Aug 2023 20:31:42 +0200 Subject: [PATCH] some changes for alpha channel support (still doesn't work :( ) --- src/common/FBBackendSDL2.hxx | 5 +++++ src/common/PNGLibrary.cxx | 24 +++++++++++++++--------- src/common/PNGLibrary.hxx | 4 ++-- src/emucore/FBBackend.hxx | 9 +++++++++ src/emucore/FrameBuffer.cxx | 4 ++-- src/emucore/FrameBuffer.hxx | 11 +++++++++++ 6 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/common/FBBackendSDL2.hxx b/src/common/FBBackendSDL2.hxx index 76098d971..99536924b 100644 --- a/src/common/FBBackendSDL2.hxx +++ b/src/common/FBBackendSDL2.hxx @@ -111,6 +111,11 @@ class FBBackendSDL2 : public FBBackend inline uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const override { return SDL_MapRGB(myPixelFormat, r, g, b); } + inline uInt32 mapRGBA(uInt8 r, uInt8 g, uInt8 b, uInt8 a) const override + { + return SDL_MapRGBA(myPixelFormat, r, g, b, a); + } + /** This method is called to get a copy of the specified ARGB data from the viewable FrameBuffer area. Note that this isn't the same as any diff --git a/src/common/PNGLibrary.cxx b/src/common/PNGLibrary.cxx index 56459aab5..37e21732c 100644 --- a/src/common/PNGLibrary.cxx +++ b/src/common/PNGLibrary.cxx @@ -40,6 +40,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi png_infop info_ptr{nullptr}; png_uint_32 iwidth{0}, iheight{0}; int bit_depth{0}, color_type{0}, interlace_type{0}; + bool hasAlpha = false; const auto loadImageERROR = [&](string_view s) { if(png_ptr) @@ -80,7 +81,8 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi // Only normal RBG(A) images are supported (without the alpha channel) if(color_type == PNG_COLOR_TYPE_RGBA) { - png_set_strip_alpha(png_ptr); + hasAlpha = true; + //png_set_strip_alpha(png_ptr); } else if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { @@ -96,7 +98,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi } // Create/initialize storage area for the current image - if(!allocateStorage(iwidth, iheight)) + if(!allocateStorage(iwidth, iheight, hasAlpha)) loadImageERROR("Not enough memory to read PNG image"); // The PNG read function expects an array of rows, not a single 1-D array @@ -113,7 +115,7 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantLi readMetaData(png_ptr, info_ptr, metaData); // Load image into the surface, setting the correct dimensions - loadImagetoSurface(surface); + loadImagetoSurface(surface, hasAlpha); // Cleanup if(png_ptr) @@ -381,10 +383,10 @@ void PNGLibrary::takeSnapshot(uInt32 number) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool PNGLibrary::allocateStorage(size_t width, size_t height) +bool PNGLibrary::allocateStorage(size_t width, size_t height, bool hasAlpha) { // Create space for the entire image (3 bytes per pixel in RGB format) - const size_t req_buffer_size = width * height * 3; + const size_t req_buffer_size = width * height * (hasAlpha ? 4 : 3); if(req_buffer_size > ReadInfo.buffer.capacity()) ReadInfo.buffer.reserve(req_buffer_size * 1.5); @@ -394,13 +396,13 @@ bool PNGLibrary::allocateStorage(size_t width, size_t height) ReadInfo.width = static_cast(width); ReadInfo.height = static_cast(height); - ReadInfo.pitch = static_cast(width * 3); + ReadInfo.pitch = static_cast(width * (hasAlpha ? 4 : 3)); return true; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void PNGLibrary::loadImagetoSurface(FBSurface& surface) +void PNGLibrary::loadImagetoSurface(FBSurface& surface, bool hasAlpha) { // First determine if we need to resize the surface const uInt32 iw = ReadInfo.width, ih = ReadInfo.height; @@ -423,8 +425,12 @@ void PNGLibrary::loadImagetoSurface(FBSurface& surface) { const uInt8* i_ptr = i_buf; uInt32* s_ptr = s_buf; - for(uInt32 icol = 0; icol < ReadInfo.width; ++icol, i_ptr += 3) - *s_ptr++ = fb.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2)); + if(hasAlpha) + for(uInt32 icol = 0; icol < ReadInfo.width; ++icol, i_ptr += 4) + *s_ptr++ = fb.mapRGBA(*i_ptr, *(i_ptr+1), *(i_ptr+2), 85/* *(i_ptr+3)*/); + else + for(uInt32 icol = 0; icol < ReadInfo.width; ++icol, i_ptr += 3) + *s_ptr++ = fb.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2)); } } diff --git a/src/common/PNGLibrary.hxx b/src/common/PNGLibrary.hxx index faf0bdeec..a10e51d9a 100644 --- a/src/common/PNGLibrary.hxx +++ b/src/common/PNGLibrary.hxx @@ -153,7 +153,7 @@ class PNGLibrary @param width The width of the PNG image @param height The height of the PNG image */ - static bool allocateStorage(size_t width, size_t height); + static bool allocateStorage(size_t width, size_t height, bool hasAlpha); /** The actual method which saves a PNG image. @@ -173,7 +173,7 @@ class PNGLibrary @param surface The FBSurface into which to place the PNG data */ - void loadImagetoSurface(FBSurface& surface); + void loadImagetoSurface(FBSurface& surface, bool hasAlpha); /** Write PNG tEXt chunks to the image. diff --git a/src/emucore/FBBackend.hxx b/src/emucore/FBBackend.hxx index d7da1a7d4..7ad3455c1 100644 --- a/src/emucore/FBBackend.hxx +++ b/src/emucore/FBBackend.hxx @@ -137,6 +137,15 @@ class FBBackend */ virtual uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const = 0; + /** + This method is called to map a given R/G/B triple to the screen palette. + + @param r The red component of the color. + @param g The green component of the color. + @param b The blue component of the color. + */ + virtual uInt32 mapRGBA(uInt8 r, uInt8 g, uInt8 b, uInt8 a) const = 0; + /** This method is called to get the specified ARGB data from the viewable FrameBuffer area. Note that this isn't the same as any internal diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 9fe62f406..d33d70df9 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -1320,8 +1320,8 @@ FBInitStatus FrameBuffer::applyVideoMode() const string& path = myOSystem.snapshotLoadDir().getPath(); //loadBezel(path + "Atari-2600.png"); - //loadBezel(path + "Combat.png"); - loadBezel(path + "Asteroids (USA).png"); + loadBezel(path + "Combat (USA).png"); + //loadBezel(path + "Asteroids (USA).png"); } resetSurfaces(); diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 7ec5b5c62..d0deb2cd7 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -360,6 +360,17 @@ class FrameBuffer return myBackend->mapRGB(r, g, b); } + /** + This method is called to map a given R/G/B triple to the screen palette. + + @param r The red component of the color. + @param g The green component of the color. + @param b The blue component of the color. + */ + uInt32 mapRGBA(uInt8 r, uInt8 g, uInt8 b, uInt8 a) const { + return myBackend->mapRGBA(r, g, b, a); + } + /** This method is called to get the specified ARGB data from the viewable FrameBuffer area. Note that this isn't the same as any internal