Draw with Pygame and Save Image – Live coding

Some live coding to draw on the screen. I’ve already made this once, but I wanted to make it simple because I have intention to add this feature to my latest project called pygpoint, a mix among pygame and powerpoint to show slides that are images like in powerpoint. In the last version of this program I added a blackboard where you can draw, but in another window. Now I want to add the feature so that you can also draw on the slides and have the chance to save also the image with the drawings on.
So this is the code to implement this. Next time I will add it to pygpoint.

The code

import pygame as pg

# pip install pygame==2.0.0.dev10

"""
With this program you can draw on the 
screen with pygame


pythonprogramming.altervista.org
"""

def init():
    global screen

    pg.init()
    screen = pg.display.set_mode((400, 400))
    mainloop()


drawing = False
last_pos = None
w = 1
color = (255, 0, 255)


def draw(event):
    global drawing, last_pos, w

    if event.type == pg.MOUSEMOTION:
        if (drawing):
            mouse_position = pg.mouse.get_pos()
            if last_pos is not None:
                pg.draw.line(screen, color, last_pos, mouse_position, w)
            last_pos = mouse_position
    elif event.type == pg.MOUSEBUTTONUP:
        mouse_position = (0, 0)
        drawing = False
        last_pos = None
    elif event.type == pg.MOUSEBUTTONDOWN:
        drawing = True


def mainloop():
    global screen

    loop = 1
    while loop:
        # checks every user interaction in this list
        for event in pg.event.get():
            if event.type == pg.QUIT:
                loop = 0
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_s:
                    pg.image.save(screen, "image.png")
            draw(event)
        pg.display.flip()
    pg.quit()


init()

The live coding video of drawing on the screen with pygame

This project on repl.it

How to clear the screen

drawnsave2.py
=============
changes:
c to clear the screen:
I simply paint the screen in black when hit c key
screen.fill((0, 0, 0))

The code in the while loop in the mainloop function

            if event.type == pg.KEYDOWN:
                if event.key == pg.K_s:
                    pg.image.save(screen, "image.png")
                if event.key == pg.K_c:
                    screen.fill((0, 0, 0))

Save multiple images

With the following changes you can save different images with different names, progressively ordinated.

import pygame as pg

# pip install pygame==2.0.0.dev10

"""
With this program you can draw on the 
screen with pygame


pythonprogramming.altervista.org

drawnsave2.py
=============
    changes:
        c to clear the screen:
        I simply paint the screen in black when hit c key
            screen.fill((0, 0, 0))

"""

def init():
    global screen

    pg.init()
    screen = pg.display.set_mode((400, 400))
    mainloop()


drawing = False
last_pos = None
w = 1
color = (255, 0, 255)


def draw(event):
    global drawing, last_pos, w

    if event.type == pg.MOUSEMOTION:
        if (drawing):
            mouse_position = pg.mouse.get_pos()
            if last_pos is not None:
                pg.draw.line(screen, color, last_pos, mouse_position, w)
            last_pos = mouse_position
    elif event.type == pg.MOUSEBUTTONUP:
        mouse_position = (0, 0)
        drawing = False
        last_pos = None
    elif event.type == pg.MOUSEBUTTONDOWN:
        drawing = True


def mainloop():
    global screen

    loop = 1
    imagecount = 0
    while loop:
        # checks every user interaction in this list
        for event in pg.event.get():
            if event.type == pg.QUIT:
                loop = 0
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_s:
                    if imagecount < 10:
                        imagecount = "0" + str(imagecount)
                    pg.image.save(screen, "image{}.png".format(imagecount))
                    imagecount = int(imagecount)
                    imagecount +=1
                if event.key == pg.K_c:
                    screen.fill((0, 0, 0))
            draw(event)
        pg.display.flip()
    pg.quit()


init()

Lets see the images with imageslider

With this code you can opend another python file (I made this some times ago) to watch the files you created).

                if event.key == pg.K_i:
                    os.startfile("imageslider.py")

imageslider.py

This is the code of the program to watch the images

import tkinter as tk
import glob
from PIL import Image, ImageTk
import os

def insertfiles():
    "loads the list of files in the directory"
    for filename in glob.glob("*.png"):
        lst.insert(tk.END, filename)


def delete_item(event):
    "Deletes a file in the list: called by lst.bind('<Control-d>', delete_item)"
    n = lst.curselection()
    os.remove(lst.get(n))
    lst.delete(n)


def get_window_size():
    "Returns the width and height of the screen to set images and canvas alike it: called by root.bind <Configure>"
    root_w = root.winfo_width()
    if root.winfo_width() > 200 and root.winfo_height() >30:
        w = root.winfo_width() - 200
        h = root.winfo_height() - 30
    else:
        w = 200
        h = 30
    return w, h


def showimg(event):
    "takes the selected image to show it, called by root.bind <Configure> and lst.bind <<ListboxSelect>>"
    n = lst.curselection()
    filename = lst.get(n)
    im = Image.open(filename)
    im = im.resize((get_window_size()), Image.ANTIALIAS)
    img = ImageTk.PhotoImage(im)
    w, h = img.width(), img.height()
    canvas.image = img
    canvas.config(width=w, height=h)
    canvas.create_image(0, 0, image=img, anchor=tk.NW)
    root.bind("<Configure>", lambda x: showimg(x))



root = tk.Tk()

root.geometry("800x600+300+50")
lst = tk.Listbox(root, width=20)
lst.pack(side="left", fill=tk.BOTH, expand=0)
lst.bind("<<ListboxSelect>>", showimg)
lst.bind("<Control-d>", delete_item)
insertfiles()
canvas = tk.Canvas(root)
canvas.pack()

root.mainloop()

Now you will see something like this

Let’s use it as an animator and the imageslider inside the main file

Now we can create gif pressing g and we can see the images in the image slider without the external file, because we put that code into a class insider the main file. Here is the code:

import pygame as pg
import os
import glob
from PIL import Image
import tkinter as tk
from PIL import Image, ImageTk


# pip install pygame==2.0.0.dev10

"""
With this program you can draw on the 
screen with pygame


pythonprogramming.altervista.org

drawnsave2.py
=============
    changes:
        c to clear the screen:
        I simply paint the screen in black when hit c key
            screen.fill((0, 0, 0))
        You can save all images with different progressive names
        You can see the images with imageslider pressing i
drawnsave4.py
        added g to make gif from saved files
        now i opens imageslider from inside the progam drawnsave.py without external programs

"""

def init():
    global screen

    pg.init()
    screen = pg.display.set_mode((400, 400))
    mainloop()


drawing = False
last_pos = None
w = 1
color = (255, 0, 255)


def draw(event):
    global drawing, last_pos, w

    if event.type == pg.MOUSEMOTION:
        if (drawing):
            mouse_position = pg.mouse.get_pos()
            if last_pos is not None:
                pg.draw.line(screen, color, last_pos, mouse_position, w)
            last_pos = mouse_position
    elif event.type == pg.MOUSEBUTTONUP:
        mouse_position = (0, 0)
        drawing = False
        last_pos = None
    elif event.type == pg.MOUSEBUTTONDOWN:
        drawing = True


def mainloop():
    global screen

    loop = 1
    imagecount = 0
    while loop:
        # checks every user interaction in this list
        for event in pg.event.get():
            if event.type == pg.QUIT:
                loop = 0
            if event.type == pg.KEYDOWN:
                if event.key == pg.K_s:
                    if imagecount < 10:
                        imagecount = "0" + str(imagecount)
                    pg.image.save(screen, "image{}.png".format(imagecount))
                    imagecount = int(imagecount)
                    imagecount +=1
                if event.key == pg.K_c:
                    screen.fill((0, 0, 0))
                if event.key == pg.K_i:
                    ImgSlide()
                elif event.key == pg.K_g:
                    frames = []
                    imgs = glob.glob("*.png")
                    for i in imgs:
                        new_frame = Image.open(i)
                        frames.append(new_frame)

                    # Save into a GIF file that loops forever
                    frames[0].save('animated.gif', format='GIF',
                                   append_images=frames[1:],
                                   save_all=True,
                                   duration=300, loop=0)
                    os.startfile("animated.gif")
            draw(event)
        pg.display.flip()
    pg.quit()


class ImgSlide():

    def __init__(self):
        self.root = tk.Tk()

        self.root.geometry("800x600+300+50")
        self.lst = tk.Listbox(self.root, width=20)
        self.lst.pack(side="left", fill=tk.BOTH, expand=0)
        self.lst.bind("<<ListboxSelect>>", self.showimg)
        self.lst.bind("<Control-d>", self.delete_item)
        self.canvas = tk.Canvas(self.root)
        self.canvas.pack()
        self.insertfiles()

        self.root.mainloop()


    def insertfiles(self):
        "loads the list of files in the directory"
        for filename in glob.glob("*.png"):
            self.lst.insert(tk.END, filename)


    def delete_item(self, event):
        "Deletes a file in the list: called by self.lst.bind('<Control-d>', delete_item)"
        n = self.lst.curselection()
        os.remove(lst.get(n))
        lst.delete(n)


    def get_window_size(self):
        "Returns the width and height of the screen to set images and self.canvas alike it: called by self.root.bind <Configure>"
        self.root_w = self.root.winfo_width()
        if self.root.winfo_width() > 200 and self.root.winfo_height() >30:
            w = self.root.winfo_width() - 200
            h = self.root.winfo_height() - 30
        else:
            w = 200
            h = 30
        return w, h


    def showimg(self, event):
        "takes the selected image to show it, called by self.root.bind <Configure> and lst.bind <<ListboxSelect>>"
        n = self.lst.curselection()
        filename = self.lst.get(n)
        im = Image.open(filename)
        im = im.resize((self.get_window_size()), Image.ANTIALIAS)
        img = ImageTk.PhotoImage(im)
        w, h = img.width(), img.height()
        self.canvas.image = img
        self.canvas.config(width=w, height=h)
        self.canvas.create_image(0, 0, image=img, anchor=tk.NW)
        self.root.bind("<Configure>", lambda x: self.showimg(x))



init()

 


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.