From 28bf0e8687465e5d1f031faf6b07ff94a3cc76d7 Mon Sep 17 00:00:00 2001 From: Hugo Elias Date: Sun, 24 Dec 2017 15:14:00 +0100 Subject: [PATCH] Add wxIMAGE_OPTION_GIF_TRANSPARENCY for GIF image loading Allow to keep the originally defined transparent pixels colour instead of replacing it with bright pink (which is still the default behaviour). Closes #18014. --- docs/changes.txt | 1 + include/wx/imaggif.h | 4 +++ interface/wx/image.h | 16 +++++++++++ src/common/gifdecod.cpp | 60 ++++++++++++++++++++++++++++++++--------- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 373590c364..7fc8529dd0 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -183,6 +183,7 @@ All (GUI): - Extend wxRendererNative::DrawGauge() to work for vertical gauges too. - Add wxHD_BITMAP_ON_RIGHT style to wxHeaderCtrl. - Send wxEVT_DATAVIEW_ITEM_EDITING_DONE when editing was cancelled too. +- Add wxIMAGE_OPTION_GIF_TRANSPARENCY (Hugo Elias). wxGTK: diff --git a/include/wx/imaggif.h b/include/wx/imaggif.h index b59744c0cb..48b07dc147 100644 --- a/include/wx/imaggif.h +++ b/include/wx/imaggif.h @@ -20,6 +20,10 @@ #define wxIMAGE_OPTION_GIF_COMMENT wxT("GifComment") +#define wxIMAGE_OPTION_GIF_TRANSPARENCY wxS("Transparency") +#define wxIMAGE_OPTION_GIF_TRANSPARENCY_HIGHLIGHT wxS("Highlight") +#define wxIMAGE_OPTION_GIF_TRANSPARENCY_UNCHANGED wxS("Unchanged") + struct wxRGB; struct GifHashTableType; class WXDLLIMPEXP_FWD_CORE wxImageArray; // anidecod.h diff --git a/interface/wx/image.h b/interface/wx/image.h index 0b3c85b315..9a6f39737f 100644 --- a/interface/wx/image.h +++ b/interface/wx/image.h @@ -93,6 +93,9 @@ enum wxImagePNGType #define wxIMAGE_OPTION_CUR_HOTSPOT_Y wxString("HotSpotY") #define wxIMAGE_OPTION_GIF_COMMENT wxString("GifComment") +#define wxIMAGE_OPTION_GIF_TRANSPARENCY wxString("Transparency") +#define wxIMAGE_OPTION_GIF_TRANSPARENCY_HIGHLIGHT wxString("Highlight") +#define wxIMAGE_OPTION_GIF_TRANSPARENCY_UNCHANGED wxString("Unchanged") #define wxIMAGE_OPTION_PNG_FORMAT wxString("PngFormat") #define wxIMAGE_OPTION_PNG_BITDEPTH wxString("PngBitDepth") @@ -1287,6 +1290,19 @@ public: PHOTOMETRIC_MINISWHITE or PHOTOMETRIC_MINISBLACK. The other values are taken care of. + Options specific to wxGIFHandler: + @li @c wxIMAGE_OPTION_GIF_TRANSPARENCY: How to deal with transparent pixels. + By default, the color of transparent pixels is changed to bright pink, so + that if the image is accidentally drawn without transparency, it will be + obvious. + Normally, this would not be noticed, as these pixels will not be rendered. + But in some cases it might be useful to load a GIF without making any + modifications to its colours. + Use @c wxIMAGE_OPTION_GIF_TRANSPARENCY_UNCHANGED to keep the colors correct. + Use @c wxIMAGE_OPTION_GIF_TRANSPARENCY_HIGHLIGHT to convert transparent pixels + to pink (default). + This option has been added in wxWidgets 3.1.1. + @note Be careful when combining the options @c wxIMAGE_OPTION_TIFF_SAMPLESPERPIXEL, @c wxIMAGE_OPTION_TIFF_BITSPERSAMPLE, and @c wxIMAGE_OPTION_TIFF_PHOTOMETRIC. diff --git a/src/common/gifdecod.cpp b/src/common/gifdecod.cpp index bea6addc38..7872120eb7 100644 --- a/src/common/gifdecod.cpp +++ b/src/common/gifdecod.cpp @@ -130,8 +130,10 @@ bool wxGIFDecoder::ConvertToImage(unsigned int frame, wxImage *image) const unsigned long i; int transparent; - // just in case... - image->Destroy(); + // Store the original value of the transparency option, before it is reset + // by Create(). + const wxString& + transparency = image->GetOption(wxIMAGE_OPTION_GIF_TRANSPARENCY); // create the image wxSize sz = GetFrameSize(frame); @@ -149,24 +151,58 @@ bool wxGIFDecoder::ConvertToImage(unsigned int frame, wxImage *image) const // set transparent colour mask if (transparent != -1) { - for (i = 0; i < GetNcolours(frame); i++) + if ( transparency.empty() || + transparency == wxIMAGE_OPTION_GIF_TRANSPARENCY_HIGHLIGHT ) { - if ((pal[3 * i + 0] == 255) && - (pal[3 * i + 1] == 0) && - (pal[3 * i + 2] == 255)) + // By default, we assign bright pink to transparent pixels to make + // them perfectly noticeable if someone accidentally draws the + // image without taking transparency into account. Due to this use + // of pink, we need to change any existing image pixels with this + // colour to use something different. + for (i = 0; i < GetNcolours(frame); i++) { - pal[3 * i + 2] = 254; + if ((pal[3 * i + 0] == 255) && + (pal[3 * i + 1] == 0) && + (pal[3 * i + 2] == 255)) + { + pal[3 * i + 2] = 254; + } } + + pal[3 * transparent + 0] = 255; + pal[3 * transparent + 1] = 0; + pal[3 * transparent + 2] = 255; + + image->SetMaskColour(255, 0, 255); } + else if ( transparency == wxIMAGE_OPTION_GIF_TRANSPARENCY_UNCHANGED ) + { + // Leave the GIF exactly as as it was, just adjust (in the least + // noticeable way, by just flipping a single bit) non-transparent + // pixels colour, + for (i = 0; i < GetNcolours(frame); i++) + { + if ((pal[3 * i + 0] == pal[3 * transparent + 0]) && + (pal[3 * i + 1] == pal[3 * transparent + 1]) && + (pal[3 * i + 2] == pal[3 * transparent + 2])) + { + pal[3 * i + 2] ^= 1; + } + } - pal[3 * transparent + 0] = 255, - pal[3 * transparent + 1] = 0, - pal[3 * transparent + 2] = 255; - - image->SetMaskColour(255, 0, 255); + image->SetMaskColour(pal[3 * transparent + 0], + pal[3 * transparent + 1], + pal[3 * transparent + 2]); + } + else + { + wxFAIL_MSG( wxS("Unknown wxIMAGE_OPTION_GIF_TRANSPARENCY value") ); + } } else + { image->SetMask(false); + } #if wxUSE_PALETTE unsigned char r[256];