If I open an image with
open("image.jpg"), how can I get the RGB values of a pixel assuming I have the coordinates of the pixel?
Then, how can I do the reverse of this? Starting with a blank graphic, ‘write’ a pixel with a certain RGB value?
I would prefer if I didn’t have to download any additional libraries.
Image manipulation is a complex topic, and it’s best if you do use a library. I can recommend gdmodule which provides easy access to many different image formats from within Python.
It’s probably best to use the Python Image Library to do this which I’m afraid is a separate download.
The easiest way to do what you want is via the load() method on the Image object which returns a pixel access object which you can manipulate like an array:
from PIL import Image im = Image.open('dead_parrot.jpg') # Can be many different formats. pix = im.load() print im.size # Get the width and hight of the image for iterating over print pix[x,y] # Get the RGBA Value of the a pixel of an image pix[x,y] = value # Set the RGBA Value of the image (tuple) im.save('alive_parrot.png') # Save the modified pixels as .png
Alternatively, look at ImageDraw which gives a much richer API for creating images.
There’s a really good article on wiki.wxpython.org entitled Working With Images. The article mentions the possiblity of using wxWidgets (wxImage), PIL or PythonMagick. Personally, I’ve used PIL and wxWidgets and both make image manipulation fairly easy.
PyPNG – lightweight PNG decoder/encoder
Although the question hints at JPG, I hope my answer will be useful to some people.
Here’s how to read and write PNG pixels using PyPNG module:
import png, array point = (2, 10) # coordinates of pixel to be painted red reader = png.Reader(filename='image.png') w, h, pixels, metadata = reader.read_flat() pixel_byte_width = 4 if metadata['alpha'] else 3 pixel_position = point + point * w new_pixel_value = (255, 0, 0, 0) if metadata['alpha'] else (255, 0, 0) pixels[ pixel_position * pixel_byte_width : (pixel_position + 1) * pixel_byte_width] = array.array('B', new_pixel_value) output = open('image-with-red-dot.png', 'wb') writer = png.Writer(w, h, **metadata) writer.write_array(output, pixels) output.close()
PyPNG is a single pure Python module less than 4000 lines long, including tests and comments.
PIL is a more comprehensive imaging library, but it’s also significantly heavier.
You can use pygame‘s surfarray module. This module has a 3d pixel array returning method called pixels3d(surface). I’ve shown usage below:
from pygame import surfarray, image, display import pygame import numpy #important to import pygame.init() image = image.load("myimagefile.jpg") #surface to render resolution = (image.get_width(),image.get_height()) screen = display.set_mode(resolution) #create space for display screen.blit(image, (0,0)) #superpose image on screen display.flip() surfarray.use_arraytype("numpy") #important! screenpix = surfarray.pixels3d(image) #pixels in 3d array: #[x][y][rgb] for y in range(resolution): for x in range(resolution): for color in range(3): screenpix[x][y][color] += 128 #reverting colors screen.blit(surfarray.make_surface(screenpix), (0,0)) #superpose on screen display.flip() #update display while 1: print finished
I hope been helpful. Last word: screen is locked for lifetime of screenpix.
As Dave Webb said:
Here is my working code snippet printing the pixel colours from an
import os, sys import Image im = Image.open("image.jpg") x = 3 y = 4 pix = im.load() print pix[x,y]
install PIL using the command “sudo apt-get install python-imaging” and run the following program. It will print RGB values of the image. If the image is large redirect the output to a file using ‘>’ later open the file to see RGB values
import PIL import Image FILENAME='fn.gif' #image can be in gif jpeg or png format im=Image.open(FILENAME).convert('RGB') pix=im.load() w=im.size h=im.size for i in range(w): for j in range(h): print pix[i,j]
You could use the Tkinter module, which is the standard Python interface to the Tk GUI toolkit and you don’t need extra download. See https://docs.python.org/2/library/tkinter.html.
(For Python 3, Tkinter is renamed to tkinter)
Here is how to set RGB values:
#from http://tkinter.unpythonic.net/wiki/PhotoImage from Tkinter import * root = Tk() def pixel(image, pos, color): """Place pixel at pos=(x,y) on image, with color=(r,g,b).""" r,g,b = color x,y = pos image.put("#%02x%02x%02x" % (r,g,b), (y, x)) photo = PhotoImage(width=32, height=32) pixel(photo, (16,16), (255,0,0)) # One lone pixel in the middle... label = Label(root, image=photo) label.grid() root.mainloop()
And get RGB:
#from http://www.kosbie.net/cmu/spring-14/15-112/handouts/steganographyEncoder.py def getRGB(image, x, y): value = image.get(x, y) return tuple(map(int, value.split(" ")))
Using Pillow (which works with Python 3.X as well as Python 2.7+), you can do the following:
from PIL import Image im = Image.open('image.jpg', 'r') width, height = im.size pixel_values = list(im.getdata())
Now you have all pixel values. If it is RGB or another mode can be read by
im.mode. Then you can get pixel
(x, y) by:
Alternatively, you can use Numpy and reshape the array:
>>> pixel_values = numpy.array(pixel_values).reshape((width, height, 3)) >>> x, y = 0, 1 >>> pixel_values[x][y] [ 18 18 12]
A complete, simple to use solution is
# Third party modules import numpy from PIL import Image def get_image(image_path): """Get a numpy array of an image so that one can access values[x][y].""" image = Image.open(image_path, "r") width, height = image.size pixel_values = list(image.getdata()) if image.mode == "RGB": channels = 3 elif image.mode == "L": channels = 1 else: print("Unknown mode: %s" % image.mode) return None pixel_values = numpy.array(pixel_values).reshape((width, height, channels)) return pixel_values image = get_image("gradient.png") print(image) print(image.shape)
You might be uncertain about the order of width / height / channel. For this reason I’ve created this gradient:
The image has a width of 100px and a height of 26px. It has a color gradient going from
#ffaa00 (yellow) to
#ffffff (white). The output is:
[[255 172 5] [255 172 5] [255 172 5] [255 171 5] [255 172 5] [255 172 5] [255 171 5] [255 171 5] [255 171 5] [255 172 5] [255 172 5] [255 171 5] [255 171 5] [255 172 5] [255 172 5] [255 172 5] [255 171 5] [255 172 5] [255 172 5] [255 171 5] [255 171 5] [255 172 4] [255 172 5] [255 171 5] [255 171 5] [255 172 5]] (100, 26, 3)
Things to note:
image, hence the first row, has 26 triples of the same color
photo = Image.open('IN.jpg') #your image photo = photo.convert('RGB') width = photo.size #define W and H height = photo.size for y in range(0, height): #each pixel has coordinates row = "" for x in range(0, width): RGB = photo.getpixel((x,y)) R,G,B = RGB #now you can use the RGB value
import matplotlib.pyplot as plt import matplotlib.image as mpimg img=mpimg.imread('Cricket_ACT_official_logo.png') imgplot = plt.imshow(img)
If you are looking to have three digits in the form of an RGB colour code, the following code should do just that.
i = Image.open(path) pixels = i.load() # this is not a list, nor is it list()'able width, height = i.size all_pixels =  for x in range(width): for y in range(height): cpixel = pixels[x, y] all_pixels.append(cpixel)
This may work for you.
Using a library called Pillow, you can make this into a function, for ease of use later in your program, and if you have to use it multiple times.
The function simply takes in the path of an image and the coordinates of the pixel you want to "grab." It opens the image, converts it to an RGB color space, and returns the R, G, and B of the requested pixel.
from PIL import Image def rgb_of_pixel(img_path, x, y): im = Image.open(img_path).convert('RGB') r, g, b = im.getpixel((x, y)) a = (r, g, b) return a
*Note: I was not the original author of this code; it was left without an explanation. As it is fairly easy to explain, I am simply providing said explanation, just in case someone down the line does not understand it.