5

我试图了解如何创建二进制 PBM/PGM/PPM 文件。据我所知,每种格式有两种类型:普通格式和原始格式。例如,黑色 PBM 5x5 的结构如下所示:

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

如您所见,它很简单:白色为 0,黑色为 1。但是,PBM 有原始版本,如下所示:

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

我该怎么做?PBM 格式说明 说:

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.

我不明白我需要做什么;我怀疑我可能需要使用structor array.array,但我不确定。我需要你的帮助; 你能用 Python 举例说明如何创建这样的文件吗?

>>> 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'

我需要良好的速度,因为我需要处理更大的图像(例如 2000x5000)。但问题是我需要使用纯 Python,没有ctypes和库。请你帮我,并举一个小例子如何创建二进制 PBM 文件?

如果您能告诉我有关二进制 PGM 和 PPM 处理的信息,那将更加令人惊奇。

谢谢!

4

1 回答 1

6

我敢肯定这里有很大的改进空间(在效率方面),但这是否正常工作?

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))

编辑

至于阅读,这似乎有效:

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's 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)

这些文件格式需要是方形的吗?这似乎不太可能。我很可能在维度部分混淆了行/列。随意检查;-)。

于 2012-09-11T18:16:04.067 回答