1

I am trying to learn about image processing in Rasbian on the Pi3. For my first little project I decided to read a JPG file from disk, and then paint it to the screen, one pixel at a time. I cannot find much help on this, probably because there are not too many good reasons to do this. But, this is what I want to do. Here is the bit of code I tried. The fill in draw.point should be the color for the original file - that is problem 1 - how to get that value. The second problem is newimage.show() does not show anything.

I am just looking for a little direction here - not necessarily a total solution. I not even sure if PIL is the best option. Thanks for any help.

from PIL import Image,ImageDraw

im = Image.open("test.jpg")

print(im.format, im.size, im.mode)
im.show()  #does nothing

xsize, ysize = im.size

print(xsize)
print(ysize)


# set up an output image
newim = Image.new("RGB", (xsize,ysize))
draw = ImageDraw.Draw(newim)                  

for pixelx in range (0,xsize):
   for pixely in range (0,ysize):
       #ImageDraw.draw.point((pixelx,pixely), fill=None)
       draw.point((pixelx,pixely),fill=255)  #fill should be actual color
       newim.show() #does nothing
2

Sadly, the PIL.show() function won't work as you expect it to do. As far as I know, if you work in graphical mode with X, then a new image viewer would be opened to display each image. If you work in console mode, it won't do anything.

In order to display something on screen, you will need to use some display manager. On raspberry, this could be i.e. SDL, openGL, dispmanx, OpenMax ...

As you work in python, i suggest you to use pygame, a library that run SDL1.2 through python, allowing your program to run under X, console mode, windows, OS2 ..

It's quite powerful and not so complicated, as you can see in this piece of code:

import pygame
from pygame.locals import *

#load SDL, then open a SDL window
pygame.init()
screen = pygame.display.set_mode((640, 480))

#Now load your image as a displayable surface.
im = pygame.image.load("test.jpg").convert()
xsize=im.get_width()
ysize=im.get_height()

for pixelx in range (0,xsize):
   for pixely in range (0,ysize):
       #read and write color to screen
       color=im.get_at((pixelx,pixely))
       screen.set_at((pixelx,pixely),color)

       #Refresh only the part of the screen that have been updated
       pygame.display.update((pixelx,pixely,pixelx+1,pixely+1))

Surface.get_at() or or Surface.set_at() functions may be a bit slow, in this case you can use Surface.get_buffer() as described here : https://www.pygame.org/docs/ref/surface.html

Welcome in the graphical programmation world :)

Edit : you will need to run this code with sudo, and may also need to hit Ctrl-C in order to complete pygame initialisation (see : https://stackoverflow.com/questions/17035699/pygame-requires-keyboard-interrupt-to-init-display)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.