Favolas
Favolas

Reputation: 7243

Python loop for image and pil module

I'm using PIL and Image modes in Python. I want to create an image with this code:

imagesize = (12,12)
image = Image.new("RGB",imagesize,color=None)

I will use this function to put pixels on my image:

.putpixel(xy, color)

color is in a list of tuples. For exemple:

RGB = [((255, 255, 255),(207, 103, 36),(204, 93, 21),(204, 93, 21),(204, 93, 21), (.......some more RGB tuples.....)]

I need a loop that in .putpixel(xy, color):

color is incremented one step every time. For example RGB[0], next loop RGB[1] and so on. While this loop is being made the x and y is the more difficult to me. x goes from 1 to 12 (image size) while y is 0 and then, when x reaches imagesize it returns to 1 to 12 but y is now 1. The loop is ended when x and both reach to the end of image size.

Can anyone help me? I'm new in Python.

Regards,

Favolas

EDIT

P:S - Forgot to say that since this is for a school project I cant use any methods besides img.new, img.show and img.outpixel

Upvotes: 5

Views: 9519

Answers (4)

invert
invert

Reputation: 2076

If we have these two lists:

xy = [(1,2),(3,4),(5,6),(7,8)]
rgb = [(0,0,255), (0,255,0), (255,0,0), (255,255,0), (255,255,255)]

We can map the XY list to the RGB list into a dictionary:

d = dict(zip(xy,rgb))

Which looks like this:

>>> print(d)
{(1, 2): (0, 0, 255), (5, 6): (255, 0, 0), (3, 4): (0, 255, 0), (7, 8): (255, 255, 0)}

So we now have a dictionary, the key is the XY and the value is the corresponding RGB. Now we can map these key-value pairs using list comprehension:

[putpixel(x,col) for x,col in d.items()]

As a test, a mock putpixel() method that prints the inputs verify the results:

def putpixel(xy,col):
    print('%s set to %s' % (xy,col))

>>> result = [putpixel(x,col) for x,col in d.items()]
(1, 2) set to (0, 0, 255)
(5, 6) set to (255, 0, 0)
(3, 4) set to (0, 255, 0)
(7, 8) set to (255, 255, 0)

List comprehension usually returns a list of processed items, in this case we don't return a result from putpixel(), thus our result list would contain empties.

Upvotes: 1

khachik
khachik

Reputation: 28703

It depends on how you want to put RGB colors. For example:

for y in range(12):
  for x in range(12):
    img.putpixel(x, y, RGB[(x + 12*y)%len(RBG)]

will put 0 to N RBG colors in 0 to N pixels, 0 to N RGBs to 0+N, 2N pixels and so on. There are another options - choose the color randomly:

import random
...
for y in range(12):
  for x in range(12):
    img.putpixel(x, y, RBG[random.randint(0, len(RGB)-1)]

Optimization for both cases is left as an exercise.

Upvotes: 1

Spacedman
Spacedman

Reputation: 94162

If you have nested loops, i from 0 to 11 and j from 0 to 11, then to index incrementally into a one-dimensional vector you need to get X[j + i * 11].

>>> for i in range(5):
...   for j in range(5):
...      print j + i*5

will print 0 to 24.

See other answers for better ways to fill Images, and there are probably more pythonic ways of doing this too. But this is the generic answer!

Note this is for variables that start at ZERO, not ONE. For your 12x12 pixel image the valid xy range is from 0 to 11.

Upvotes: 1

Jim Brissom
Jim Brissom

Reputation: 32919

Ok, my comment from above should've really gone into an answer. I should catch some sleep. You can basically just put your pixel data into the image at once. The putdata method of a PIL.Image accepts a list of tuples that make up the pixels of the images. So:

img = PIL.Image.new("RGB", (12, 12))
img.show() # see a black image
pixels = [(255,0,0)]*(12*12)
img.putdata(pixels)
img.show() # see a red image

Upvotes: 2

Related Questions