Color Reduction Python 3.4 help please Many years ago computers couldn’t display
ID: 3762669 • Letter: C
Question
Color Reduction Python 3.4 help please
Many years ago computers couldn’t display 1000’s of colors. Images would have their color
reduced. Now color reduction can be used to create image effects to give it a cartoonish look.
Reduction is also used for some visual systems in robotics and other applications to help
recognize objects. For this assignment we will read an image in the PPM format, and adjust the
colors to be the closest of a choice of colors.
The image on the left has the possibility of 16,777,216 colors, while the picture on the right uses
5 possible colors
PPM Files
Portable PixMap format or PPM is a simple image file format. There are a few variants of the
PPM format, but we will be concentrating on one particular specification of the text file versions.
Since it’s just a normal text file, we can open, read and write the image files just like they were
any normal text document. This makes it very convenient since we can use all the Python file
handling techniques we’ve learned this semester. We have included ppmReader.htmlto view
the ppm files that have been supplied. You may also want to use an image editor like gimp to
view the images ( http://www.gimp.org). You will also want to examine the files in a text editor.
PPM Format ( Ocean.ppm )
Line # Example Data Description
1 P3 PPM Header information. P followed by a number.
We’ll be using the P3 format.
2 3072 2304 Size of the image in pixels. This 3072 wide and 2304
pixels tall.
3 255 Color Depth of the Image. Each Red, Green, Blue
component will be 0255 in value. This is always 255
in our examples.
4 143 Red Component of the first pixel.
5 211 Green component of the first pixel
6 255 Blue Component of the first pixel
7 144 Red component of the second pixel
... ... ...
21233665 80 Red component of last pixel
21233666 112 Green component of last pixel
21233667 135 Blue Component for the last pixel.
The PPM format is very flexible. In our incarnation each color component is on a separate line.
We also will not have any comments in the header. If you save an ASCII ppm file from gimp
you will have to edit the resulting text file and remove the comment from the header.
Color Reduction
We will be reducing an image down to 5 colors Red, Green, Blue, White, and Black. Each pixel
is made up of a red, green and blue component. In the files we will be working with each has
256 values from 0 255. You can imagine each pixel color being a point in a 3 dimensional
model.
You’ll notice that the color at the back of 0, 0, 0 is black. If you follow out the red direction you’ll
notice the color getting redder. Same with green and blue. The white point shown is directly
opposite the black point in the cube and is located at 255, 255, 255.
We will convert our image into the following color points
Color Red Green Blue
Red 255 0 0
Green 0 255 0
Blue 0 0 255
Black 0 0 0
White 255 255 255
The first pixel in Ocean.ppm is 255, 143, 211. We want to convert that color to one of our 5
choices of colors. We can use the Euclidean distance to find which color point is closest to our
color. You may know how to get the Euclidean distance of 2 points in a 2d plane.
This diagram shows a 2d plane with points at (2, 3) and (5, 7). The distance between them is
calculated by distance = (x . The distance here is 5. To find the distances in 1 x2)
2
+ (y1 y2)
2
a 3d plane we can extend this formula with x, y’s and z’s. We can replace those with r for red,
g, for green and b for blue. To find the distance from one color to another we would use
distance = (r . The color we want to choose for our color reduced 1 r2)
2
+ (g1 g2)
2
+ (b1 b2)
2
image will be the color that is the shortest distance from the original color.
The triangle is the original color, pixel 1 from Ocean.ppm. In our final output image it will be
replaced with one of the 5 colors that it is closest to.
Requirements
Display a menu for the user. On an invalid entry warn the user and ask for input. 1.
Reduce Color PPM, Q. to Quit
Ask the user for a valid file. If the file does not exist the user should be warned and
prompted again.
The PPM files that are loaded should be validated to make sure the first line is P3,
signifying that is a PPM file, and the color depth is 255..
Ask for an output image to save our changes to. If the file cannot be created the user
should be warned and prompted again..
Notes
There is a test_pattern.ppm file that can be used to help validate your program. The image size
is 200 x 200. The first 50 lines are variations of red, 50 lines of greens, 50 lines of blue. The
last 50 lines is half white and half black. ( See the example image above. ). Your resulting
output image should look like the example given earlier.
Definitions
Pixel any one of the very small dots that together form the picture on a television screen,
computer monitor, etc.
1
Example
>>>================================RESTART================================
>>>
ColorReduction
1.ConvertPPMImage
Q.Quit
==>1
Enteravalidfilenametoconvert.==>nofile.m
Thefileyouspecifieddoesnotexist. Pleaseenteravalidfilename
Enteravalidfilenametoconvert.==>BadHeader1.ppm
ThefilesfirstlineshouldbeP3
Enteravalidfilenametoconvert.==>BadHeader2.ppm
Thecolordepthmustbe255
Enteravalidfilenametoconvert.==>umkc.ppm
Whatisthenameofthefileyouwanttosaveto?==>umkc_out.ppm
Yourfilehasbeensaved.
ColorReduction
1.ConvertPPMImage
Q.Quit
==>q
>>>
Explanation / Answer
import sys
class PPM_Exception(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
def partition(s,ch):
if (ch in s):
k = s.index(ch)
return (s[0:k],s[k],s[k+1:])
else:
return (s,None,None)
def strip_comments(s):
(rval,junk1,junk2) = partition(s,"#")
return rval.rstrip(" ")
def load_ppm(fname):
return loadPPM(fname);
def loadPPM(fname):
inf = open(fname,"r")
magic = strip_comments(inf.readline())
if (magic != "P3"):
raise PPM_Exception, 'The file does not appear to be a valid ASCII PPM file'
dimensions = strip_comments(inf.readline())
(width, sep, height) = partition(dimensions," ")
width = int(width)
height = int(height)
if (width <= 0) or (height <= 0):
raise PPM_Exception, "The file appear to have valid dimensions (" + str(width) + " x " + str(height) + ")"
max = inf.readline()
max = int(strip_comments(max))
if (max != 255):
sys.stderr.write(" PPM file does not have a maximum value of 255. Image may not be handled correctly.")
color_list = []
for line in inf:
line = strip_comments(line)
color_list += line.split(" ")
inf.close()
image = []
for x in range(0,width):
image.append([])
for y in range(0,height):
image[a].append([int(color_list[(y * width + x) * 3]),
int(color_list[(y * width + x) * 3 + 1]),
int(color_list[(y * width + x) * 3 + 2])])
return image
def limit(high, low, value):
if (value < low) or (value > high):
raise PPM_Exception, str(value) + " is outside of the range " + str(high) + " to " + str(low)
def displayImage(x, y, img, outf=sys.stdout):
outf.write("pixelsx " + str(x) + " " + str(y) + " " + str(len(img)) + " " + str(len(img[0])))
for j in range(0, len(img[0])):
for k in range(0, len(img)):
limit(255.9,-0.9,img[k][j][0])
limit(255.9,-0.9,img[k][j][1])
limit(255.9,-0.9,img[k][j][2])
outf.write(" %02x%02x%02x" % (int(img[k][j][0]),int(img[k][j][1]),int(img[k][j][2])))
outf.write(" ")
outf.flush()
def createImage(x, y):
retval = []
for k in range(0, x):
retval.append([])
for j in range(0, y):
retval[k].append([0,0,0])
return retval
def width(image):
return len(image)
def height(image):
return len(image[0])