Create binary PBM / PGM / PPM

I am trying to understand how to create PBM / PGM / PPM binaries. As I know, for each format there are two types: simple and raw. For example, the structure of the black PBM 5x5 is as follows:

P1 # This is a comment 5 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 

So, as you can see, this is simple: white - 0, black - 1. However, PBM has the original version, which looks like this:

 'P4\n# This is a comment\n5 5\n\xf8\xf8\xf8\xf8\xf8' 

How can i do this? PBM format description says:

A raster of Height rows, in order from top to bottom. Each row is Width bits, packed 8 to a byte, with don't care bits to fill out the last byte in the row. Each bit represents a pixel: 1 is black, 0 is white. The order of the pixels is left to right. The order of their storage within each file byte is most significant bit to least significant bit. The order of the file bytes is from the beginning of the file toward the end of the file. A row of an image is horizontal. A column is vertical. The pixels in the image are square and contiguous.

I do not understand what I need to do; I suspect that I may need to use struct or array.array , but I'm not sure. I need your help; Could you give an example in Python, how to create such a file?

 >>> size = (5, 5) >>> array = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] >>> create_pbm(size, array) 'P4\n5 5\n\xf8\xf8\xf8\xf8\xf8' 

I need a good speed because I need to process much larger images (e.g. 2000x5000). But the problem is that I need to use pure Python, without ctypes and libraries. Could you please help me and give a small example of creating PBM binaries?

It will be even more surprising if you tell me about binary processing of PGM and PPM.

Thanks!

+4
source share
1 answer

I am sure there are many opportunities for improvement (in terms of efficiency), but does this work correctly?

 import struct def create_pbm(size,lst): out = ['P4\n'+' '.join(map(str,size))+'\n'] #header for j in xrange(0,len(lst),size[1]): #single row of data row = lst[j:j+size[1]] #padded string which can be turned into a number with `int` s = ''.join(map(str,row))+'0000000' #Turn the string into a number and pack it (into unsigned int) using struct. vals = [struct.pack('B',int(s[i*8:(i+1)*8],2)) for i in xrange(size[0]//8+1) ] out.append(''.join(vals)) return ''.join(out) a = [1]*25 #flat black image. print repr(create_pbm((5,5),a)) 

EDIT

As for reading, this seems to work:

 def read_pbm(fname): with open(fname) as f: data = [x for x in f if not x.startswith('#')] #remove comments p_whatever = data.pop(0) #P4 ... don't know if that important... dimensions = map(int,data.pop(0).split()) arr = [] col_number = 0 for c in data.pop(0): integer = struct.unpack('B',c)[0] col_number += 8 bits = map(int,bin(integer)[2:]) arr.extend(bits[:min(8,dimensions[0]-col_number)]) if(col_number > dimensions[0]): col_number = 0 return (dimensions, arr) 

Should these file formats be square? which seems unlikely. It is possible that I got rows / columns mixed in part sizes. Feel free to check it out; -).

+5
source

Source: https://habr.com/ru/post/1433628/


All Articles