GIF transparent colour turning bright pink
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
GIF transparent colour turning bright pink
Hi,
I load a GIF image using wxImage::LoadFile().
Then I draw the image to a wxPaintDc using DrawBitmap().
The image should look like the one on the left, but instead it looks like the one on the right. It seems that the 'transparent' colour has been replaced by a bright pink. Is there some way I can prevent that happening, or turn it back to its original colour? (Note, I don't want to turn on transparency by setting useMask = true).
Hugo
I load a GIF image using wxImage::LoadFile().
Then I draw the image to a wxPaintDc using DrawBitmap().
The image should look like the one on the left, but instead it looks like the one on the right. It seems that the 'transparent' colour has been replaced by a bright pink. Is there some way I can prevent that happening, or turn it back to its original colour? (Note, I don't want to turn on transparency by setting useMask = true).
Hugo
Re: GIF transparent colour turning bright pink
I believe that at least on MSW wxDC does not support transparency aside from the transparency mask. You can easily test this using wxGCDC instead of regular wxDC.
EditActually it seems that PNGs with transparency are drawn properly both by wxDC and wxGCDC while the same image converted to GIF with a transparent color is not drawn with transparency by either (the toucan image is from the image sample):
TBH, I myself would not use GIF in this situation.
EditActually it seems that PNGs with transparency are drawn properly both by wxDC and wxGCDC while the same image converted to GIF with a transparent color is not drawn with transparency by either (the toucan image is from the image sample):
Code: Select all
#include <wx/wx.h>
#include <wx/dcbuffer.h>
#include <wx/dcgraph.h>
class MyCanvas : public wxPanel
{
public:
MyCanvas(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
Bind(wxEVT_PAINT, &MyCanvas::OnPaint, this);
m_bmpGIF = wxBitmap("toucan.gif", wxBITMAP_TYPE_GIF);
m_bmpPNG = wxBitmap("toucan.png", wxBITMAP_TYPE_PNG);
}
private:
wxBitmap m_bmpGIF, m_bmpPNG;
void OnPaint(wxPaintEvent&)
{
wxAutoBufferedPaintDC dc(this);
dc.SetBrush(*wxBLUE_BRUSH);
dc.DrawRectangle(GetClientRect());
dc.DrawBitmap(m_bmpGIF, 0, 0);
dc.DrawBitmap(m_bmpPNG, m_bmpGIF.GetWidth(), 0);
wxGCDC gcdc(dc);
gcdc.DrawBitmap(m_bmpGIF, 0, m_bmpGIF.GetHeight());
gcdc.DrawBitmap(m_bmpPNG, m_bmpGIF.GetWidth(), m_bmpGIF.GetHeight());
}
};
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
wxInitAllImageHandlers();
wxFrame* f = new wxFrame(NULL, wxID_ANY, _("Test"), wxDefaultPosition, wxSize(800, 800));
new MyCanvas(f);
f->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
It does support transparency. You just have to enable it by adding 'true' at the end:
Then it renders the pink stuff as transparent. But I don't want it to be rendered transparent. I want the pink stuff to be rendered in its correct colour, which is grey.
My question is: which bit of code is causing the colour to change? And how can I tell it not to do that?
(As for why I'm using GIF: I'm making an image browser, so I don't have a choice about which images someone browses to.)
Code: Select all
dc.DrawBitmap(bitmap, x, y, true);
My question is: which bit of code is causing the colour to change? And how can I tell it not to do that?
(As for why I'm using GIF: I'm making an image browser, so I don't have a choice about which images someone browses to.)
Re: GIF transparent colour turning bright pink
I do not know why, but the magenta color has been used since I can remember when drawing the "transparent colour".
I also do not understand why you are surprised when the transparency mask is not used when you tell wxWidgets to not use it?
The difference being that GIFs are 8-bit only so they use transparency mask while PNGs can use true alpha (RGBA), right?
You can convert mask to alpha with something like thisbut why?
I also do not understand why you are surprised when the transparency mask is not used when you tell wxWidgets to not use it?
The difference being that GIFs are 8-bit only so they use transparency mask while PNGs can use true alpha (RGBA), right?
You can convert mask to alpha with something like this
Code: Select all
wxImage img("toucan.gif");
wxBitmap bmp;
img.InitAlpha();
bmp = wxBitmap(img);
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
Hi PB,
Perhaps I'm not describing the problem correctly. There should be no pink colour at all. In fact, the original GIF is a greyscale image.
As I said in my original post, the image should look like the one on the left, not the one on the right. Somewhere the pink colour is being added to an image that had no pink colour.
> I also do not understand why you are surprised when the transparency mask is not used when you tell wxWidgets to not use it?
My surprise is not that there is no transparency (I wanted no transparency). My surprise is the appearance of a colour which is not in the original greyscale image.
Here is the original image. Please can you show me the code that will make this image display correctly on the screen, with transparency disabled and no pink in it. Thanks
Hugo
Perhaps I'm not describing the problem correctly. There should be no pink colour at all. In fact, the original GIF is a greyscale image.
As I said in my original post, the image should look like the one on the left, not the one on the right. Somewhere the pink colour is being added to an image that had no pink colour.
> I also do not understand why you are surprised when the transparency mask is not used when you tell wxWidgets to not use it?
My surprise is not that there is no transparency (I wanted no transparency). My surprise is the appearance of a colour which is not in the original greyscale image.
Here is the original image. Please can you show me the code that will make this image display correctly on the screen, with transparency disabled and no pink in it. Thanks
Hugo
Re: GIF transparent colour turning bright pink
It's quite obvious that this image does not have a grey background, it's transparent. You can clearly see the blue-ish background color of the forum behind the image.
This is how it looks when loaded into PhotoShop:
This is how it looks when loaded into PhotoShop:
Use the source, Luke!
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
Hi Doublemax,
As I'm sure you know, in an 8-bit GIF format image, there are three main parts:
When a GIF image is displayed, there is typically a choice about how to display it. Most modern image editing software will convert the 8-bit GIF to a 32-bit image with alpha channel. The alpha channel will be fully transparent for each pixel that matches the 'transparent' colour (in this case 210), and opaque for every other pixel. Alternatively, the transparency tag can be ignored, and the image can be shown without the alpha channel (or the alpha channel set to opaque everywhere). For example, this is what it looks like opened in a very old version of Paintshop Pro, which doesn't support transparency:
And here is the palette. As it's a greyscale image, we just have 256 grey levels. The colour 210 is outlined. As you can see, it is not pink. What's happening in wxWidgets seems to be an additional step which I don't want. The pallet colour marked as transparent is being changed from 0xD2D2D2 to 0xFF00FF.
Is there some way to stop this happening?
As I'm sure you know, in an 8-bit GIF format image, there are three main parts:
- the compressed 8-bit pixel data
- the palette
- the transparency tag
When a GIF image is displayed, there is typically a choice about how to display it. Most modern image editing software will convert the 8-bit GIF to a 32-bit image with alpha channel. The alpha channel will be fully transparent for each pixel that matches the 'transparent' colour (in this case 210), and opaque for every other pixel. Alternatively, the transparency tag can be ignored, and the image can be shown without the alpha channel (or the alpha channel set to opaque everywhere). For example, this is what it looks like opened in a very old version of Paintshop Pro, which doesn't support transparency:
And here is the palette. As it's a greyscale image, we just have 256 grey levels. The colour 210 is outlined. As you can see, it is not pink. What's happening in wxWidgets seems to be an additional step which I don't want. The pallet colour marked as transparent is being changed from 0xD2D2D2 to 0xFF00FF.
Is there some way to stop this happening?
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
I think I have found the place it's happening:
on line 162 of gifdecod.cpp, in the function wxGIFDecoder::ConvertToImage()
The palette colour marked as transparent is actually being changed to pink.
on line 162 of gifdecod.cpp, in the function wxGIFDecoder::ConvertToImage()
Code: Select all
pal[3 * transparent + 0] = 255,
pal[3 * transparent + 1] = 0,
pal[3 * transparent + 2] = 255;
image->SetMaskColour(255, 0, 255);
Re: GIF transparent colour turning bright pink
As I told you before, magenta (RGB 255, 0, 255) is used by convenience when simple graphics APIs draw the parts of image that should be fully transparent.Rocketmagnet wrote:Is there some way to stop this happening?
If you do not want to draw the transparent pixels (and you do not want that), either tell the wxDC to use the mask when drawing the bitmap or convert the mask to alpha, as shown in my previous post. There is nothing else you can or should do.
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
Hi PB,
Perhaps I'm failing to communicate my needs, or perhaps I'm being very thick. What I want to do is draw this GIF, so that it looks exactly like this:
Shouldn't the code be more like this:
Or, even better, like this:
I tried this, and it seems to work. The cat image renders correctly.
Perhaps I'm failing to communicate my needs, or perhaps I'm being very thick. What I want to do is draw this GIF, so that it looks exactly like this:
Shouldn't the code be more like this:
Code: Select all
transparent = GetTransparentColourIndex(frame);
// set transparent colour mask
if (transparent != -1)
{
image->SetMaskColour(pal[3 * transparent + 0], pal[3 * transparent + 1], pal[3 * transparent + 2]);
}
else
{
image->SetMask(false);
}
Code: Select all
transparent = GetTransparentColourIndex(frame);
// set transparent colour mask
if (transparent != -1)
{
for (i = 0; i < GetNcolours(frame); i++) // Prevent duplicate colours becoming transparent
{ // by changing them slightly
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;
}
}
image->SetMaskColour(pal[3 * transparent + 0], pal[3 * transparent + 1], pal[3 * transparent + 2]);
}
else
{
image->SetMask(false);
}
Last edited by Rocketmagnet on Fri Dec 01, 2017 12:40 pm, edited 1 time in total.
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
There's another reason why the code shouldn't really be changing the colours. Look what happens when my application creates a thumbnail of a GIF that contains transparency information.
When I create a thumbnail of this image, using bilinear rescaling, the pink colour leaks into all adjacent pixels. Now it's impossible to draw the image without some pink showing.
Using the modified code in gifdecod.cpp, the rescaled image now looks like this:
Code: Select all
if (image.LoadFile(fullPath.GetFullPath()))
{
wxSize newSize = GetTnImageSize(image.GetSize(), size);
image.Rescale(newSize.GetWidth(), newSize.GetHeight(), wxIMAGE_QUALITY_BILINEAR);
bitmap = wxBitmap(image);
image.Destroy();
}
Using the modified code in gifdecod.cpp, the rescaled image now looks like this:
Re: GIF transparent colour turning bright pink
So, all you want is to draw the GIF on a gray background? Just draw the gray background first and then draw the GIF using transparent mask. Goal achieved. I must admit I am really confused...
Edit
I can confirm magenta "leaking" into the image when rescaling with wxIMAGE_QUALITY_BILINEAR. I have no idea why this happens and cannot allocate more time to investigate. The image looks as expected when wxIMAGE_QUALITY_HIGH is used instead:
Edit
I can confirm magenta "leaking" into the image when rescaling with wxIMAGE_QUALITY_BILINEAR. I have no idea why this happens and cannot allocate more time to investigate. The image looks as expected when wxIMAGE_QUALITY_HIGH is used instead:
Code: Select all
#include <wx/wx.h>
#include <wx/dcbuffer.h>
#include <wx/dcgraph.h>
class MyCanvas : public wxPanel
{
public:
MyCanvas(wxWindow* parent)
: wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
{
SetBackgroundStyle(wxBG_STYLE_PAINT);
Bind(wxEVT_PAINT, &MyCanvas::OnPaint, this);
m_gifBmp = wxBitmap("cat.gif", wxBITMAP_TYPE_GIF);
wxImage img("cat.gif");
// wxSize newSize = m_gifBmp.GetSize() * 2;
wxSize newSize = m_gifBmp.GetSize() / 2;
img.InitAlpha();
img.Rescale(newSize.GetWidth(), newSize.GetHeight(), wxIMAGE_QUALITY_HIGH);
m_gifBmpResized = wxBitmap(img);
}
private:
wxBitmap m_gifBmp;
wxBitmap m_gifBmpResized;
void DrawTransparentBitmap(wxDC& dc, const wxPoint& pos, const wxBitmap& bmp,
const wxColour& backClr)
{
wxRect rect(pos, bmp.GetSize());
wxBrush brush(backClr);
wxPen pen(backClr);
dc.SetBrush(brush);
dc.DrawRectangle(rect);
dc.SetPen(pen);
dc.DrawBitmap(bmp, pos, bmp.GetMask() != NULL);
dc.SetBrush(wxNullBrush);
dc.SetPen(wxNullPen);
}
void OnPaint(wxPaintEvent&)
{
wxAutoBufferedPaintDC dc(this);
wxBrush brush(*wxBLUE);
dc.SetBrush(*wxBLUE_BRUSH);
dc.SetPen(*wxBLUE_PEN);
dc.DrawRectangle(GetClientRect());
DrawTransparentBitmap(dc, wxPoint(0, 0), m_gifBmp, *wxRED);
DrawTransparentBitmap(dc, wxPoint(m_gifBmp.GetWidth(), 0), m_gifBmp, *wxLIGHT_GREY);
DrawTransparentBitmap(dc, wxPoint(m_gifBmp.GetWidth() * 2, 0), m_gifBmp, *wxBLACK);
DrawTransparentBitmap(dc, wxPoint(0, m_gifBmp.GetHeight()),
m_gifBmpResized, *wxRED);
DrawTransparentBitmap(dc, wxPoint(m_gifBmpResized.GetWidth(), m_gifBmp.GetHeight()),
m_gifBmpResized, *wxLIGHT_GREY);
DrawTransparentBitmap(dc, wxPoint(m_gifBmpResized.GetWidth() * 2, m_gifBmp.GetHeight()),
m_gifBmpResized, *wxBLACK);
}
};
class MyApp : public wxApp
{
public:
virtual bool OnInit()
{
wxInitAllImageHandlers();
wxFrame* f = new wxFrame(NULL, wxID_ANY, _("Test"), wxDefaultPosition, wxSize(600, 240));
new MyCanvas(f);
f->Show();
return true;
}
}; wxIMPLEMENT_APP(MyApp);
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
Hi PB,
Thanks for being patient with me.
The application I'm making is an image browser. It shows thumbnails of the images in a directory. Here are some screenshots of my application so far:
This is what I started with: So I tried setting useMask=true, but that still shows lots of pink because of the bilinear filtering. After I modified gifdecod.cpp, it now looks how it should look. The cats and flag are drawn with the correct background colour as it appears in the original file. As you can see, there are a couple of different cat GIFs there, with two different background colours. Can you see that your suggestion of drawing the cat over a grey rectangle is not a solution? It's not a solution for the following two reasons:
Thanks for being patient with me.
The application I'm making is an image browser. It shows thumbnails of the images in a directory. Here are some screenshots of my application so far:
This is what I started with: So I tried setting useMask=true, but that still shows lots of pink because of the bilinear filtering. After I modified gifdecod.cpp, it now looks how it should look. The cats and flag are drawn with the correct background colour as it appears in the original file. As you can see, there are a couple of different cat GIFs there, with two different background colours. Can you see that your suggestion of drawing the cat over a grey rectangle is not a solution? It's not a solution for the following two reasons:
- There's no way for my application to know what colour rectangle to draw underneath.
- Because of the bilinear filtering (which happens after the pink is added), you'd still end up with lots of pink pixels which shouldn't be there.
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
Furthermore, two other applications agree with me.
This is another image browser, ACDSee. It draws the GIFs correctly, without any pink: And this is Paint Shop Pro: Would you at least agree with me that adding the pink colour is not standard, and that there are applications which draw GIFs correctly?
Hugo
This is another image browser, ACDSee. It draws the GIFs correctly, without any pink: And this is Paint Shop Pro: Would you at least agree with me that adding the pink colour is not standard, and that there are applications which draw GIFs correctly?
Hugo
-
- Experienced Solver
- Posts: 84
- Joined: Wed Aug 09, 2006 11:14 pm
- Location: London
- Contact:
Re: GIF transparent colour turning bright pink
Hi PB
> I have no idea why this happens and cannot allocate more time to investigate.
Well, my modifications to gifdecod.cpp seem to fix this problem. Do you think I should suggest this as a modification?
Hugo
> I have no idea why this happens and cannot allocate more time to investigate.
Well, my modifications to gifdecod.cpp seem to fix this problem. Do you think I should suggest this as a modification?
Hugo