5

バイナリ PBM/PGM/PPM ファイルを作成する方法を理解しようとしています。私が知っているように、各形式にはプレーンと生の 2 つのタイプがあります。たとえば、黒の 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.

何をする必要があるのか​​ わかりません。structまたはを使用する必要があるのではないかと思います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 など) を処理する必要があるため、適切な速度が必要です。ctypesしかし、問題は、ライブラリなしで純粋な Python を使用する必要があることです。バイナリ 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 に答える