wxStaticBitmap scales image unnecessarily on Windows (Issue #23168)

151 views
Skip to first unread message

lszl84

unread,
Jan 22, 2023, 10:27:34 AM1/22/23
to wx-...@googlegroups.com, Subscribed

Description

wxStaticBitmap and wxGenericStaticBitmap tend to upscale images on Windows. This does not reproduce on Mac or on Linux.

Here's simple code with wxStaticBitmap, wxGenericStaticBitmap, and a custom control that draws the bitmap using GC. On windows only the custom control draws correct size (as compared to the system image viewer with 100% zoom).

#include <wx/wx.h>
#include <wx/generic/statbmpg.h>
#include <wx/graphics.h>
#include <wx/dcbuffer.h>

class BufferedBitmap : public wxWindow
{
public:
    BufferedBitmap(wxWindow *parent, wxWindowID id, const wxBitmap &b, const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = 0)
        : wxWindow(parent, id, pos, size, wxFULL_REPAINT_ON_RESIZE)
    {
        this->SetBackgroundStyle(wxBG_STYLE_PAINT); // needed for windows

        this->Bind(wxEVT_PAINT, &BufferedBitmap::OnPaint, this);
        this->SetBitmap(b);
    }

    void OnPaint(wxPaintEvent &evt)
    {
        wxAutoBufferedPaintDC dc(this);
        dc.Clear();

        wxGraphicsContext *gc = wxGraphicsContext::Create(dc);

        if (gc)
        {
            const wxSize drawSize = GetClientSize();

            const wxSize bmpSize = bitmap.GetSize();

            double w = bmpSize.GetWidth();
            double h = bmpSize.GetHeight();

            double x = (drawSize.GetWidth() - w) / 2;
            double y = (drawSize.GetHeight() - h) / 2;

            gc->DrawBitmap(bitmap, x, y, w, h);

            delete gc;
        }
    }

    void SetBitmap(const wxBitmap &bitmap)
    {
        this->bitmap = bitmap;
        this->Refresh();
    }

    const wxBitmap &GetBitmap()
    {
        return bitmap;
    }

private:
    wxBitmap bitmap;
};

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
};

class MyFrame : public wxFrame
{
public:
    MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size);

private:
    wxStaticBitmap *staticBitmap;
    wxGenericStaticBitmap *genericBitmap;
    BufferedBitmap *bufferedBitmap;

    wxImage image;
};

bool MyApp::OnInit()
{
    wxInitAllImageHandlers();

    MyFrame *frame = new MyFrame("Hello World", wxDefaultPosition, wxDefaultSize);
    frame->Show(true);
    return true;
}

wxIMPLEMENT_APP(MyApp);

MyFrame::MyFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
    : wxFrame(NULL, wxID_ANY, title, pos, size)
{
    if (!image.LoadFile("/Users/lukasz/Desktop/OIP.jpg"))
    {
        wxLogError("Failed to load image file");
        return;
    }

    auto sizer = new wxBoxSizer(wxVERTICAL);

    auto tvStatic = new wxStaticText(this, wxID_ANY, "Static Bitmap");
    staticBitmap = new wxStaticBitmap(this, wxID_ANY, wxBitmap(image), wxDefaultPosition, FromDIP(wxSize(500, 200)));
    staticBitmap->SetScaleMode(wxStaticBitmap::Scale_None);

    auto tvGeneric = new wxStaticText(this, wxID_ANY, "Generic Bitmap");
    genericBitmap = new wxGenericStaticBitmap(this, wxID_ANY, wxBitmap(image), wxDefaultPosition, FromDIP(wxSize(500, 200)));
    genericBitmap->SetScaleMode(wxStaticBitmap::Scale_None);

    auto tvBuffered = new wxStaticText(this, wxID_ANY, "Buffered Bitmap");
    bufferedBitmap = new BufferedBitmap(this, wxID_ANY, wxBitmap(image), wxDefaultPosition, FromDIP(wxSize(500, 200)));

    std::initializer_list<wxWindow *> controls = {tvStatic, staticBitmap, tvGeneric, genericBitmap, tvBuffered, bufferedBitmap};

    for (const auto c : controls)
    {
        sizer->Add(c, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT | wxTOP, FromDIP(10));
    }

    this->SetSizerAndFit(sizer);
}

The offending image and the screenshots for the platforms are attached.

Platform and version information

  • wxWidgets version you use: current master; also reproduces on 3.1.7
  • wxWidgets port you use: wxMSW
  • OS and its version: Windows 10

Screenshot 2023-01-22 at 16 18 38

Screenshot 2023-01-22 at 16 16 45

Screenshot 2023-01-22 at 16 14 17

OIP


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23168@github.com>

Maarten

unread,
Jan 22, 2023, 10:54:25 AM1/22/23
to wx-...@googlegroups.com, Subscribed

Looks like you have 200% scaling?
When drawing on a wxDC or wxGraphicsContext you'll also need to used FromDIP().
I would change it to this:

const wxSize drawSize = ToDIP(GetClientSize());

so the w/h/x/y calculations are all dpi independent, and then when drawing use:

gc->DrawBitmap(bitmap, gc->FromDIP(x), gc->FromDIP(y), gc->FromDIP(w), gc->FromDIP(h));


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23168/1399528193@github.com>

lszl84

unread,
Jan 22, 2023, 11:10:48 AM1/22/23
to wx-...@googlegroups.com, Subscribed

That would make the scaling consistent with the wxStaticBitmap, but what throws me off is that the System Image Viewer shows the small image at 100%.

The same goes for GIMP (see screenshot).

So if it's not a bug in wxWidgets, then it means both the Windows Image Viewer and GIMP are broken.

What do you think?
Screenshot 2023-01-22 at 17 08 51


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23168/1399532414@github.com>

Maarten

unread,
Jan 22, 2023, 11:19:36 AM1/22/23
to wx-...@googlegroups.com, Subscribed

I don't think it is a bug, just a matter of choice.

GIMP and Image viewer show the image/pixels as they are, we choose to scale them so the size remains consistent with other gui elements.
Same on macOS and Ubuntu. The image viewer says 474x316 pixels, when you measure the image it is 948x632 pixels.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23168/1399534622@github.com>

lszl84

unread,
Jan 22, 2023, 11:26:29 AM1/22/23
to wx-...@googlegroups.com, Subscribed

Alright, this explanation makes sense to me. Closing the issue. Thanks!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issues/23168/1399536083@github.com>

lszl84

unread,
Jan 22, 2023, 11:26:29 AM1/22/23
to wx-...@googlegroups.com, Subscribed

Closed #23168 as completed.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/issue/23168/issue_event/8329096197@github.com>

Reply all
Reply to author
Forward
0 new messages