user937868
user937868

Reputation:

Image to ASCII in python using a PPM file. PIL not allowed

Needing a little help/direction with a project. Our task is to take in a .ppm file (the one we are required to test with is found here: http://beastie.cs.ua.edu/cs250/projects/asciiart/tux.ppm) and reprint it out on the screen using ascii characters. We are required to convert the pixels to greyscale. This is really where I am stuck. Cannot figure out how to read in every three elements (because every three is a pixel in PPM files), convert them to greyscale and move on. Again PIL is not allowed. Any help or links on what to read up on would be awesome!

Upvotes: 1

Views: 3717

Answers (2)

Diego Navarro
Diego Navarro

Reputation: 9704

Reading the ppm file you can do this:

# Open the PPM file and process the 3 first lines
f = open("tux.ppm")
color = f.readline().splitlines()
size_x, size_y = f.readline().split()
max = f.readline().splitlines()

You really don't need to know about the 3 first lines of the file. You only must know that you are working with a RGB image, which means you have 3 values (0-255) for each pixel.

To convert the image to grayscale you have two options: you can either generate another PPM file (with 3 values per pixel) or you can generate a PGM file which has the same format as the PPM but the first line is P2 instead of P3 and you will have only one value per pixel (that's the cool way).

To convert a RGB color value (r,g,b) in one grayscale intensity value you can apply this formula (better than simply apply the average):

0.21*r + 0.71*g + 0.07*b

Generate the grayscale image with one value per pixel (if you want it in 3-values you only have to repeat 3 times it for r,g,b):

# Getting the image data (if you have read the 3 first lines...)
data = f.read().split()

# Generate a new array of pixels with grayscale values (1 per pixel)
gray_data = [0.21*data[i] + 0.71*data[i+1] + 0.07*data[i+2] for i in range(0,len(data),3)]

Upvotes: 1

Blender
Blender

Reputation: 298156

The PPM isn't hard to parse.

The header:

P3
50 50
255
  • P3 means that the image is an ASCII pixmap (color).
  • 50 50 is the width and height.
  • 255 is the max color value.

The body:

254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 
254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 254 254 252 
254 254 252 254 254 252 254 254 252 253 255 250 239 244 237 251 255 248 
234 236 231 255 255 251 252 251 249 255 254 251 253 248 242 255 255 244 
...

Just remove all newlines:

body.replace('\n', ' ')

And parse it in triplets (not too elegant):

raw = body.split(' ')

for i in range(0, len(raw), 3):
  red = raw[i]
  green = raw[i + 1]
  blue = raw[i + 2]

Upvotes: 3

Related Questions