Search code examples
pythonarraysnumpyppm

Is there any way to save two 2D numpy arrays as one plain ppm image?


I'm looking for a way to save (efficiently if possible) two 2D numpy arrays into one plain ppm image. I think the only difference between standard (raw) and plain ppm image is than the latter limits line length to 70 chars.

The only way I can think of is to save each array to separate colour channels. Say first array as Red, second as Green, and leave Blue at 0? Though not sure does it make sense...

Ideally the ppm file will by 'human readable' (not a data buffer). I know that scipy can save it as raw ppm (but not human readable)

Any ideas welcome


Solution

  • The plain PPM format is so simple that it would probably take you only a few minutes to write the code to create one. If you'd rather use an existing library, you can use imageio if you also install the freeimage backend. Then you can do something like the following.

    Suppose a and b are the two arrays.

    In [100]: a
    Out[100]: 
    array([[36, 19, 60, 73],
           [ 2, 27, 13, 22],
           [19, 50, 38, 18],
           [47, 69, 55, 52]], dtype=uint8)
    
    In [101]: b
    Out[101]: 
    array([[221, 252, 236, 225],
           [248, 254, 226, 248],
           [221, 232, 216, 208],
           [207, 243, 249, 231]], dtype=uint8)
    

    Create a 3-D array, and copy a and b into it.

    In [102]: data = np.zeros(a.shape + (3,), dtype=a.dtype)
    
    In [103]: data[:,:,0] = a
    
    In [104]: data[:,:,1] = b
    

    Use imageio.imwrite to create the PPM file. Use the format PPM-FI to use the freeimage backend, and set flags=1 to create a plain PPM file (i.e. ASCII, not raw).

    In [105]: import imageio
    
    In [106]: imageio.imwrite('data.ppm', data, format='PPM-FI', flags=1)
    

    Here's the file:

    In [107]: !cat data.ppm
    P3
    4 4
    255
     36 221   0  19 252   0  60 236   0  73 225   0   2 248   0 
     27 254   0  13 226   0  22 248   0  19 221   0  50 232   0 
     38 216   0  18 208   0  47 207   0  69 243   0  55 249   0 
     52 231   0