Python (バイナリファイル入出力)

バイナリファイル入出力

バイナリファイル入出力に使用するメソッドは以下の通りです。

open(ファイル名, モード)
ファイル名のファイルをモードにしたがって開いて、ファイル記述子を返します。
'r'
読み込み専用
'w'
書き込み専用
'a'
ファイルの末尾に追加
'r+'
更新(読み取りと書き込み)
'w+'
ファイルを空にして、そのファイルを読み書き用に開く
'a+'
ファイルを読み書き用に開いて、ファイルの末尾に追加
'b'
ファイルをバイナリモードで開く (他のオプションと一緒に使用)
read()
ファイルのデータをすべて読み込みます。
返り値は、文字列です。
read(n)
ファイルのデータをnバイト分読み込みます。
write(s)
文字列またはリスト s をファイルに書き込みます。
close()
ファイルを閉じます。

ファイル入出力の例 (バイナリファイル)

読み込んだバイナリの画像データを、半分の明るさにして出力するスクリプトです。

  1. 以下のスクリプトを、darken.py というファイル名で保存します。
    #!env python
    import sys
    import struct
    
    infile = open(sys.argv[1], 'r')
    outfile = open(sys.argv[2], 'w')
    
    for i in range(3):
        d = infile.readline()
        outfile.write(d)
    
    data = infile.read()
    odata = ''
    for i in range(len(data)/3):
        r = ord(data[3*i])/2
        g = ord(data[3*i+1])/2
        b = ord(data[3*i+2])/2
        odata += struct.pack('BBB', r, g, b)
    
    outfile.write(odata)
    
    infile.close()
    outfile.close()
    
    
  2. サンプルの画像をバイナリのppmファイルで用意します。
    [tmp1.ppm]
    サンプル画像(tmp1.ppm)
  3. 以下のように実行します。
    # python darken.py tmp1.ppm tmp2.ppm
    [tmp2.ppm]
    サンプル画像(tmp2.ppm)

スクリプト解説

import struct
packメソッドを使用するために、structモジュールをインポートします。
for i in range(3):
画像ファイルのヘッダ部分を入出力するためにループします。
ここでは、入力•出力の画像ファイルは同じ大きさ•色数なので、そのままデータを入出力します。
d = infile.readline()
ヘッダ部分を1行読み込みます。
outfile.write(d)
読み込んだヘッダをそのまま出力します。
data = infile.read()
画像ファイルの色データを読み込みます。
data に代入されるデータは、文字列として読み込まれています。
odata = ''
出力データを入れてゆく変数を用意します。
for i in range(len(data)/3):
ループの回数は、読み込んだデータの長さを3で除算したものになります。
r = ord(data[3*i])/2
g = ord(data[3*i+1])/2
b = ord(data[3*i+2])/2
文字データdata[3*i], data[3*i+1], data[3*i+2]をord()によって数値に変換してRGBの計算を行います。
odata += struct.pack('BBB', r, g, b)
三つの数値 r, g, b を1バイトずつのデータに並べて、 odata に追加します。
outfile.write(odata)
出力ファイルにデータを書き込みます。

RGBデータのループ

RGBのデータをループによって計算するには、以下の方法もあります。

for rgb in zip(data[0::3], data[1::3], data[2::3]):
    r = ord(rgb[0])/2
    g = ord(rgb[1])/2
    b = ord(rgb[2])/2
for rgb in zip(data[0::3], data[1::3], data[2::3]):
入力データから、RGBのデータを一つずつ取り出して、 リスト rgb に代入しながらループします。
rgb には、色データが文字になって並んでいます。
[赤の数値を表す文字, 緑の数値を表す文字, 青の数値を表す文字]
例えば、R が 97、G が 100、B が 120 という値だとすると、 97 は'a'、100 は 'd'、120 は 'x'という文字を表す数値なので、 rgb には以下のようにデータが代入されています。 ['a', 'd', 'x']
r = ord(rgb[0])/2
g = ord(rgb[1])/2
b = ord(rgb[2])/2
文字データrgb[0], rgb[1], rgb[2]をord()によって数値に変換して計算を行います。

PPM ファイルフォーマット

バイナリデータのPPM画像ファイルは、 文字列3行分のヘッダと、それ以下のバイナリ画像データによって作られています。

1行目
マジックナンバーを表す文字列'P6'
2行目
横•縦の解像度
例えば、横640ピクセル、縦480ピクセルならば '640 480' という文字列になります。
3行目
色数の最大値
例えば、各色データが1バイトで表される場合は'255'になります。
4行目
色データがバイナリで並ぶ
色数の最大値が255ならば、1バイトずつRGBの3バイトデータが必要な個数だけ並びます。

練習問題

  1. 読み込んだ2つのバイナリの画像データを、マスク画像によって合成して出力するスクリプト composite.py を作成してみましょう。
    1. サンプルの画像をバイナリのppmファイルで用意します。
      (下の画像 tmp3.ppm)
      [tmp3.ppm]
      (上の画像 tmp4.ppm)
      [tmp4.ppm]
      (マスク画像 mask1.ppm)
      [mask1.ppm]
    2. 以下のように実行すると、tmp5.ppm の画像になります。
      # python composite.py tmp3.ppm tmp4.ppm mask1.ppm tmp5.ppm
      [tmp5.ppm]

参考


Prev
index | home
abetmhr@gmail.com