Opened 5 months ago

Closed 5 months ago

#16084 closed defect (fixed)

wxStaticBitmap holding 32-bit 0RGB bitmap is not displayed

Reported by: awi Owned by:
Priority: normal Milestone:
Component: wxMSW Version: dev-latest
Keywords: wxStaticBitmap alpha Cc:
Blocked By: Blocking:
Patch: yes

Description

When wxStaticBitmap with 32-bit bitmap with alpha channel is created then internally there is also created a temporary copy of this bitmap with de-premultiplied RGB data (according to the STM_SETIMAGE requirements).
If on input there is provided 0RGB bitmap (in fact 32-bit with no real alpha) then the result of de-premultiplication is RGB (24-bit) only bitmap. A handle to this bitmap is next submitted to the control via STM_SETIMAGE and just after that the bitmap is destroyed. Because this is not a 32-bit bitmap STM_SETIMAGE handler doesn't create a "secret copy" of the bitmap and in effect nothing is displayed because the bitmap no longer exists.
Screenshot with sample output attached.

Generally, every bitmap submitted to STM_SETIMAGE must exist as long as the control exists. For 32-bit bitmaps STM_SETIMAGE creates a "secret copy" on its own, but for 24-bit it doesn't and this is a responsibility of caller to hold the bitmap.

Possible combinations of bitmaps are as follows:
Input    Temp.     Secret
bitmap   bitmap    copy
ARGB     ARGB      Y       need to manually destroy temp. bitmap and secret copy
0RGB     RGB       N       need to manually destroy temp. bitmap
RGB      -         N

In order to fix the issue there is necessary to hold the temporary bitmap over the control lifetime - patch attached.

Patch to reproduce the issue below:

  • samples/minimal/minimal.cpp

    old new  
    172172    CreateStatusBar(2); 
    173173    SetStatusText("Welcome to wxWidgets!"); 
    174174#endif // wxUSE_STATUSBAR 
     175    wxImage::AddHandler( new wxPNGHandler ); 
     176    SetBackgroundColour(wxColour(180, 210, 230)); 
     177    // RGB 
     178    wxBitmap bmpRGB(50,50,24); 
     179    { 
     180        wxMemoryDC dc(bmpRGB); 
     181        { 
     182            dc.SetBackground(*wxGREEN_BRUSH); 
     183            dc.SetTextForeground(*wxRED); 
     184            dc.Clear(); 
     185            dc.DrawText(wxT("RGB"), 10, 15); 
     186        } 
     187    } 
     188    wxASSERT( !bmpRGB.HasAlpha() && bmpRGB.GetDepth() == 24 ); 
     189    // 0RGB 
     190    wxBitmap bmp0RGB(50,50,32); 
     191    bmp0RGB.UseAlpha(); 
     192    { 
     193        wxMemoryDC dc(bmp0RGB); 
     194        { 
     195            dc.SetBackground(*wxYELLOW_BRUSH); 
     196            dc.SetTextForeground(*wxBLUE); 
     197            dc.Clear(); 
     198            dc.DrawText(wxT("0RGB"), 5, 15); 
     199        } 
     200    } 
     201    wxASSERT( bmp0RGB.HasAlpha() && bmp0RGB.GetDepth() == 32 ); 
     202    // ARGB 
     203    wxBitmap bmpARGB(wxT("arrow_argb.png"),  wxBITMAP_TYPE_PNG); 
     204    wxASSERT( bmpARGB.HasAlpha() && bmpARGB.GetDepth() == 32 ); 
     205 
     206    new wxStaticBitmap(this, wxID_ANY, bmpRGB, wxPoint(5, 5)); 
     207    new wxStaticBitmap(this, wxID_ANY, bmp0RGB, wxPoint(60, 5)); 
     208    new wxStaticBitmap(this, wxID_ANY, bmpARGB, wxPoint(115, 5)); 
    175209} 
    176210 

Attachments (3)

arrow_argb.png download (3.5 KB) - added by awi 5 months ago.
Sample ARGB bitmap.
screenshot-static-bitmaps.png download (11.5 KB) - added by awi 5 months ago.
Screenshot with sample output.
statbitmap-tmp.patch download (2.3 KB) - added by awi 5 months ago.
Maintaining temporary bitmap.

Download all attachments as: .zip

Change History (5)

Changed 5 months ago by awi

Sample ARGB bitmap.

Changed 5 months ago by awi

Screenshot with sample output.

Changed 5 months ago by awi

Maintaining temporary bitmap.

comment:1 Changed 5 months ago by vadz

Thanks for finding and fixing yet another bug in this code!

I'm applying this to the trunk but it can't be done in 3.0 (not ABI-compatible because of a new member field addition). So I wonder if we couldn't fix this in a different way: check if the bitmap is really 0RGB and not ARGB and just use the original handle in this case, as premultiplied or not shouldn't matter anyhow in this case.

What do you think?

comment:2 Changed 5 months ago by VZ

  • Resolution set to fixed
  • Status changed from new to closed

(In [76148]) Fix showing of 32bpp bitmaps without alpha in wxMSW wxStaticBitmap.

The native control doesn't make a secret copy of the image in this case (0RGB
bitmap, i.e. 32bpp ARGB bitmap with all alpha values set to 0) and just shows
the bitmap we assigned to it directly, so we must not delete it in this case,
otherwise nothing is shown at all.

Closes #16084.

Note: See TracTickets for help on using tickets.