FMF読込クラス
もう少し変態的な書き方に修正。
#!/usr/bin/env python # -*- coding: utf-8 -*- import struct class Layer2D: """ 2次元レイヤー """ def __init__(self, width, height, data): """ コンストラクタ @param width 幅 @param height 高さ @param data データ """ self.width = width self.height = height self.data = data def get(self, x, y): """ 座標を指定して値を取得 @param x, y 座標 @return 値 """ if 0 <= x < self.width: if 0 <= y < self.height: return self.data[y*self.width + x] return None def __str__(self): strData = " " for i, data in enumerate(self.data): strData += "%r,"%data if (i+1) % self.width == 0: strData += "\n " return "(Width,Height)=(%d,%d)\n%s"%( self.width, self.height, strData) class FMFLoader: """ FMFファイル読込クラス """ # データのbit数に対応するバイナリコード変換関数テーブル CONVERT_BIN_FUNC_TBL = { 8: lambda cnt, b: struct.unpack("%dB"%cnt, b), 16: lambda cnt, b: struct.unpack("%dH"%cnt, b), } def __init__(self, filepath, layer2d=Layer2D): """ コンストラクタ @param filepath FMFファイルパス @param layer レイヤーとして使用するクラス(Layer2Dの派生クラス) """ self.filepath = filepath self.file = open(filepath, "rb") # ヘッダ self._readHeader() # データ( レイヤーリスト) self.layerList = map(self._createLayer, [layer2d]*self.layerCount) def _readHeader(self): """ ヘッダ読込[20byte] """ b = self.file.read(4) assert b == "FMF_", "FileformatError: Expected 'FMF'file. (file:'%s')"%self.filepath self.identifier = b # ファイル識別子 [4byte] b = self.file.read(16) (self.dataSize, # ヘッダを除いたサイズ [4byte] self.width, # マップの幅 [4byte] self.height, # マップの高さ [4byte] self.chipWidth, # チップの幅 [1byte] self.chipHeight, # チップの高さ [1byte] self.layerCount, # レイヤー数 [1byte] self.bitCount # データのbit数(8/16) [1byte] ) = struct.unpack("3L4B", b) def _createLayer(self, layer2d): """ レイヤーの生成 """ return apply(layer2d, (self.width, self.height, self._createLayerData(self.width*self.height))) def _createLayerData(self, size): """ レイヤーデータを生成 @param size レイヤーデータのサイズ """ return self.CONVERT_BIN_FUNC_TBL[self.bitCount]( size, self.file.read(size*self.bitCount/8)) def getLayer(self, index): """ レイヤーオブジェクト取得 @parma index レイヤー番号 """ if 0 <= index < self.layerCount: return self.layerList[index] return None def toStringHeader(self): """ ヘッダを文字列に変換 """ return "%s%s%s%s%s%s%s%s"%( " Identifier :%s\n"%self.identifier, " Size(except Header):%i\n"%self.dataSize, " Width :%i\n"%self.width, " Height :%i\n"%self.height, " ChipWidth :%i\n"%self.chipWidth, " ChipHeight :%i\n"%self.chipHeight, " LayerCount :%i\n"%self.layerCount, " BitCount :%i\n"%self.bitCount, ) def toStringData(self): """ データを文字列に変換 """ result = " " for idx, layer in enumerate(self.layerList): result += "[Layer:%d]\n "%idx for i, data in enumerate(layer.data): result += "%r,"%data if (i+1) % layer.width == 0: result += "\n " return result def __str__(self): return "Header ... \n%s\nData ... \n%s"%( self.toStringHeader(), self.toStringData()) def main(): fmf = FMFLoader("area.fmf") print fmf if __name__ == "__main__": main()