Extracting Pixel Data with ImageMagick

From Media Design: Networked & Lens-Based wiki
Jump to navigation Jump to search

Some examples of how to turn images into data which you can then manipulate.

Extracting pixel data into nested lists

This python script uses a system call to make use of command-line ImageMagick functionality. It extracts the co-ordinates and color of each pixel in an image, and stores them in nested lists.

The data is stored thus:
pixels[ [row1column1, row1column2, row1column3....] [row2column1, row2column2, row2column3...] [row3column1...] ]
^^ each sub-list corresponds to a row in the image grid; each key within the sub-list to the column number. The value is the pixel's RGB (colour) data. ^^

#!/usr/bin/python
#-*- coding:utf-8 -*-

import os, re

# Converts an image into nested lists of RGB values.
# stores rgb values and pixel co-ordinates thus, where the value of each list item is the RGB info; its key the column number, and its list the row number:
# pixels[ [row1column1, row1column2, row1column3....] [row2column1, row2column2, row2column3...] [row3column1...] ]

#--------- determine image dimensions-----------------------#	

image = "myImage.png"
sizeQuery = "identify -format '%w %h' " + image		# system command gets image dimensions with ImageMagick
size = os.popen(sizeQuery, 'r').read()			# captures output of system call
(width, height) = size.split()				# splits ImageMagick output into separate column & row no's
columns = int(width)
rows = int(height)
#print columns
#print rows

#--------- assign pixel details to lists  ------------------#		

pixels = []							# create empty list 'pixels'
def getcolors ():
    for row in range (0, rows):					# for each row in the image...		
    	pixels.append([])					# ...append a new sub-list within list 'pixels'
        for column in range (0, columns):			# for each column in the row...
            colorQuery = "convert " + image + " -format '%[pixel:p{" + str(column) + "," + str(row) + "}]' info:-"
            colorResult = os.popen(colorQuery, 'r').read()	# makes & captures output of system call
            color = re.sub("\n", "", colorResult)		# strips newline character from end of sys call result
            pixels[row].append(color)			# append color as a value to the 'row' sublist within 'pixels' - its is same as current column number
 
getcolors()

# test that colours & coordinates are assigned correctly:
print pixels [0][0]

# or:
# print pixels

Turning your image into html

This is an expanded version of the above script. After storing the pixel data, it uses it to print out an html table where each table cell corresponds to a single pixel from the image. Here, the color value is taken from the list and used as the background color for that table cell.

#!/usr/bin/python
#-*- coding:utf-8 -*-

import os, re

# stores rgb values and pixel co-ordinates in nested lists, thus:
# pixels[ [row1column1, row1column2, row1column3....] [row2column1, row2column2, row2column3...] [row3column1...] ]

#--------- determine image dimensions----------------------------------------#	

image = "20by10PixelsSection1.png"
sizeQuery = "identify -format '%w %h' " + image		# system command gets image dimensions with ImageMagick
size = os.popen(sizeQuery, 'r').read()			# captures output of system call
(width, height) = size.split()				# splits ImageMagick output into separate column & row no's
columns = int(width)
rows = int(height)
#print columns
#print rows

#--------- assign pixel details to lists  ------------------#		

pixels = []							# create empty list 'pixels'
def getcolors ():
    for row in range (0, rows):					# for each row in the image...		
    	pixels.append([])					# ...append a new sub-list within list 'pixels'
        for column in range (0, columns):			# for each column in the row...
            colorQuery = "convert " + image + " -format '%[pixel:p{" + str(column) + "," + str(row) + "}]' info:-"
            colorResult = os.popen(colorQuery, 'r').read()	# makes & captures output of system call
            color = re.sub("\n", "", colorResult)		# strips newline character from end of sys call result
            pixels[row].append(color)			# append color as a value to the 'row' sublist within 'pixels' - its is same as current column number
 
getcolors()

# print pixels

# test that colours & coordinates are assigned correctly:
#print pixels [1][1]
    
##--------- reproduce pixels as an html table ------------------#		

##--------- print html page opener ------------#
print """
<!DOCTYPE html>
<html>
  <head>
    <title>Forbidden Pixels: Trial #1</title>
    <style type="text/css">
      body {
        background-color: #333;
        color: #eee;
      }
     
      .pixel {
        width: 50px;
        height: 50px;
        float: left;
        border: 1px #000 solid;
        padding: none;
        margin: none;
      }
    </style>
  </head>
  
<body>
  <div id="header">
    <h1>Forbidden Pixels</h1>
    <p>A 20 x 10 pixel section of a censored photograph</p>
  </div>
  
  <div class="inner">"""

##--------- print table with a loop, using list values ------------#

print "<table>"
for row in range (0, rows):	
    print "<tr>"
    for column in range (0, columns):
        print """<td class="pixel" style="background-color:" """ + pixels[row][column] + """ "></td>"""       # pixels[row][column] prints the RGB value for the pixel at that coordinate
    print "</tr>"
print "</table>"

##--------- print closing html tags ------------#
print """
  </div>
</body>
</html>"""