Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to open/create images in Python without using external modules

I have a python script which opens an image file (.png or .ppm) using OpenCV, then loads all the RGB values into a multidimensional Python array (or list), performs some pixel by pixel calculations solely on the Python array (OpenCV is not used at all for this stage), then uses the newly created array (containing new RGB values) to write a new image file (.png here) using OpenCV again. Numpy is not used at all in this script. The program works fine.

The question is how to do this without using any external libraries, regardless whether they are for image processing or not (e.g. OpenCV, Numpy, Scipy, Pillow etc.). To summarize, I need to use bare bones Python's internal modules to: 1. open image and read the RGB values and 2. write a new image from pre-calculated RGB values. I will use Pypy instead of CPython for this purpose, to speed things up. Note: I use Windows 10, if that matters.

like image 632
NP1 Avatar asked Feb 17 '26 04:02

NP1


2 Answers

You can write a PPM file like this without OpenCV or numpy or anything that hates you :-

import array
width,height = 800,600

PPMheader = 'P6\n' +str(width) + ' ' +str(height) + '\n255\n'

# Create and fill a red PPM image
image = array.array('B', [255, 0, 0] * width * height)

# Save as PPM image
with open('result.ppm', 'wb') as f:
   f.write(bytearray(PPMheader, 'ascii'))
   image.tofile(f)

enter image description here


I wrote a really simplistic PPM reader too - it only reads 24-bit P6 PPM files matching the ones written above. I guess it could be fleshed out to handle comments, 16-bit data and greyscale data, but it's a start:

#!/usr/local/bin/python3
import array

def ppmread(filename):
    with open(filename, 'rb') as f:
        # Read first line - expecting "P6"
        line = f.readline().decode('latin-1')
        if not line.startswith('P6'):
           print("ERROR: Expected PPM file to start with P6")
           return False

        # Read second line - expecting "width height"
        line = f.readline().decode('latin-1')
        dims = line.split()
        width,height=int(dims[0]),int(dims[1])

        # Read third line - expecting "255"
        line = f.readline().decode('latin-1')
        if not line.startswith('255'):
           print("ERROR: Expected 8-bit PPM with MAXVAL=255")
           return False

        image= f.read(width*height*3)

ppmread('test.ppm')

Convert PPM to PNG or JPEG with ImageMagick in Terminal:

convert result.ppm -auto-level image.png

Or:

convert result.ppm -resize 1024x768 image.jpg

Likewise, convert JPEG to PPM with ImageMagick in Terminal:

convert image.jpg -depth 8 image.ppm
like image 103
Mark Setchell Avatar answered Feb 18 '26 18:02

Mark Setchell


Working with bare-bones .ppm files is trivial: you have three lines of text (P6, "width height", 255), and then you have the 3*width*height bytes of RGB. As long as you don't need more complicated variants of the .ppm format, you can write a loader and a saver in 5 lines of code each.

like image 32
Armin Rigo Avatar answered Feb 18 '26 18:02

Armin Rigo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!