Multiplatform support for high dpi displays. In particular macos

I have a crossplatform application (linux, macos and ms windows) that generates bitmaps dynamically from images via a custom artprovider.

The concrete problem I am having is that the way I used to handle bitmaps that would display correctly in high dpi displays in MacOS was by setting a size for the wx.Bitmap that was different from that of the underlying image. However after the recent update of wxpython to track the master branch of wxwidgets, the size of a bitmap can no longer be set once it has been created from an image. (This is a change in wxWidgets)

The following code exemplifies my former approach:

import wx

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, 'test')
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        img = wx.Image('mytestimage.png').ConvertToBitmap()
        scale = wx.GetApp().GetTopWindow().GetContentScaleFactor()
        print(f"scale={scale}, originalSize={img.GetSize()}")
        img.SetSize((img.GetWidth() // int(scale), img.GetHeight() // int(scale)))
        print(f"newSize={img.GetSize()}")
        bmp = wx.StaticBitmap(self, wx.ID_ANY, img)
        sizer.Add(bmp, 0, wx.ALL, 0)

        self.SetSizer(sizer)
        self.Show()

app = wx.App(False)
mf = MainFrame()
app.MainLoop()

But after the update, the line img.SetSize ... is illegal and the program doesn’t run. The concrete error is Bitmap scaling failed: wxAssertionError, C++ assertion "GetHeight() == h" failed at /Users/robind/projects/bb2/dist-osx-py38/build/ext/wxWidgets/src/osx/core/bitmap.cpp(1380) in SetHeight(): Changing the bitmap height is not supported

To illustrate the effect of the SetSize line in a display with ContentScaleFactor=2.0, see the following image:

The smaller, sharp, image on the right shows the bitmap at its natural size, while the image on the left shows what happens when removing the now-illegal line img.SetSize ..., which is that the macos toolkit scales it up by ContentScaleFactor.

So my question is, what is the correct way of telling the macos toolkit that my application (or at least this bitmap) is dpi aware and need not be rescaled? I am aware of ctypes.windll.shcore.SetProcessDpiAwareness in ms windows to inform the underlying toolkit that my application is dpi aware and the bitmaps it produces need not be rescaled. Is there something similar for macos?

I remark that using @x2 filenames is not an option for me, because as I mentioned above, in my real application (not the minimal sample above) I create the bitmaps from a custom artprovider and the images are not read from files.

Thank you.

If all else fails, would piping the data through a temporary
file named …@x2 help any ?

Karsten

I have the exact same problem at PyFa.

This is not currently possible in wxPython.

If you compile from source you may try, as a temporary solution, to apply the following patch that I created: https://github.com/wxWidgets/wxWidgets/pull/1963

However, if you want a long term solution, you should wait until the API is finalized in wxWidgets version 3.2, hopefully before the end of the year. See the discussion at https://groups.google.com/g/wx-dev/c/QY965dseicg for more details about what form this might take when it is available.