wxPython canvas drawing save

vegaseat 1 Tallied Votes 2K Views Share

This little code snippet shows you how you save a wxPython canvas drawing to a standard image file.

# create a canvas on top of a blank bitmap
# any canvas drawings can now be saved to a standard image file
# tested with Python27 and wxPython28  by vegaseat  05jan2011

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent=None, id=-1, title=None):
        wx.Frame.__init__(self, parent, id, title, size=(380,400))
        self.statbmp = wx.StaticBitmap(self)
        self.draw_image()
        self.save_image()

    def draw_image(self):
        # select the width and height of the blank bitmap
        # should fit the client frame
        w, h = 340, 340
        # create the blank bitmap as a draw background
        draw_bmp = wx.EmptyBitmap(w, h)
        # create the canvas on top of the draw_bmp
        canvas_dc = wx.MemoryDC(draw_bmp)
        # fill the canvas white
        canvas_dc.SetBrush(wx.Brush('white'))
        canvas_dc.Clear()

        # draw a bunch of circles ...
        # pen colour
        canvas_dc.SetPen(wx.Pen('red', 1))
        # fill colour
        canvas_dc.SetBrush(wx.Brush('yellow'))
        for x in range(10, 180, 10):
            y = x
            r = x
            canvas_dc.DrawCircle(x, y, r)

        # now put the canvas drawing into a bitmap to display it
        # remember the canvas is on top of the draw_bmp
        self.statbmp.SetBitmap(draw_bmp)

    def save_image(self):
        """save the drawing"""
        finished_image = self.statbmp.GetBitmap()
        #finished_image.SaveFile("mydrawing.png", wx.BITMAP_TYPE_PNG)
        finished_image.SaveFile("mydrawing.jpg", wx.BITMAP_TYPE_JPEG)


app = wx.App(0)
MyFrame(title='canvas draw and save').Show()
app.MainLoop()

# help(wx.PaintDC)

Dani AI

Generated

Nice, compact example from showing the common pattern: draw onto an off-screen bitmap with a MemoryDC, show it with a wx.StaticBitmap and save that bitmap to disk. A few practical updates and gotchas for anyone porting this old snippet to modern wxPython (Phoenix) / Python 3 or trying to make the save step more robust.

Prefer creating a bitmap with wx.Bitmap(width, height) rather than the legacy wx.EmptyBitmap (that wrapper is deprecated). When using wx.MemoryDC be sure to release the bitmap from the DC before reusing or saving it — either memdc.SelectObject(wx.NullBitmap) or delete the DC — otherwise the bitmap can be locked and SaveFile may fail. Also be aware wx.Bitmap.SaveFile returns False if the requested image format handler is not available; register handlers (or call the init helper on older builds) if needed, and choose PNG to preserve alpha (JPEG is lossy). (pythonhosted.org)

For interactive drawing use buffered DCs to avoid flicker (e.g. wx.BufferedPaintDC / wx.BufferedDC). If you need explicit RGBA bitmaps use wx.Bitmap.FromBufferRGBA / FromRGBA or wx.Image conversions and then SaveFile("out.png", wx.BITMAP_TYPE_PNG) to keep transparency. Small, explicit step to avoid the common trap:

memdc.SelectObject(wx.NullBitmap)   # release bitmap from DC
bmp.SaveFile("mydrawing.png", wx.BITMAP_TYPE_PNG)

These changes make the pattern from stable across modern wxPython releases. (docs.wxpython.org)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.