Here I wrote a function to save image/matrix into PPM format. I tried to simplify the saving process by using the matlab function ‘dlmwrite’ such that I only need to write the header for this PPM format. However, before streaming the image data, different channels of the input image must be interleaved. I experimented two ways to do this. Both work just fine, and the use of matlab function ‘cat’ (or ‘permute’) make the implementation very simple.
function write_ppm(im, fname, xval) [height, width, c] = size(im); assert(c == 3); fid = fopen( fname, 'w' ); %% write headers fprintf( fid, 'P3\n' ); fprintf( fid, '%d %d\n', width, height); fprintf( fid, '%d \n', xval); %maximum values fclose( fid ); %% interleave image channels before streaming c1 = im(:, :, 1)'; c2 = im(:, :, 2)'; c3 = im(:, :, 3)'; im1 = cat(2, c1(:), c2(:), c3(:)); %% data streaming, could be slow if the image is large dlmwrite(fname, int32(im1), '-append', 'delimiter', '\n')
The implementation in Python is even simpler. ‘f.write()’ is capable of writing the entire image in one function call with the help of ‘\n’.join().
def write_ppm(fname, im, xval): height, width, nc = im.shape assert nc == 3 f = open(fname, 'w') f.write('P3\n') f.write(str(width)+' '+str(height)+'\n') f.write(str(xval)+'\n') # interleave image channels before streaming c1 = np.reshape(im[:, :, 0], (width*height, 1)) c2 = np.reshape(im[:, :, 1], (width*height, 1)) c3 = np.reshape(im[:, :, 2], (width*height, 1)) im1 = np.hstack([c1, c2, c3]) im2 = im1.reshape(width*height*3) f.write('\n'.join(im2.astype('str'))) f.write('\n') f.close()
You could also use imagemagick to convert other image formats into ppm. By default, convert will save the results into binary format.
>> convert input.jpg output.ppm (for binary)
or
>> convert input.jpg -compress none output.ppm (for ASCII)
Remember that if your input data range is in between 8bit and 16 bit, for example, you specify 14 bit in your ppm header, after Imagemagick convert, the results will be saved in 16bit format and MSB aligned.