(Application) BMPをNetCDFに変換
作成者:山本 博基
概要
BMP画像データをNetCDFデータに変換します。
8/24/32 bit, Windows, OS/2フォーマットに対応し、これらは自動で判別されます。
生成されるNetCDFファイルの、軸の名前 [単位名] は x [pixels], y [pixels]、 変数名は8 bit の場合は I [none] (long name は Intensity) 、 24/32 bit の場合は R [none], G [none], B [none], 及び I [none] (R + G + B)になります。
型は全て Int になります。
使い方
BMPフォーマットのファイル hoge.bmp を与えて実行すると、 hoge.nc が生成されます。
$ ./bmp2nc.rb hoge.bmp
ソースコード
bmp2nc.rb
#!/usr/bin/env ruby # # 機能: # 8/24/32 bit のBMPフォーマットの画像データを読み込んで、NetCDF ファイルを生成する。 # Windows, OS/2 のフォーマットに対応。 # 8/24/32 bit の判別, Windows, OS/2の判別は自動で行われる。 # # 使用法: # ruby bmp2nc.rb hoge.bmp # と実行すると hoge.nc が生成される。 # 軸の名前[単位名]は x [pixels], y [pixels] # 変数名は8 bit の場合は I [none] (long name は Intensity) # 24/32 bit の場合は R [none], G[none], B[none], 及び I [none] (R + G + B)である。 # # 参考URL: http://www.kk.iij4u.or.jp/~kondo/bmp/ require "numru/gphys" include NumRu # 入力ファイルを開く infp = File.open(ARGV[0],"r") #情報ヘッダ取得 filehead = infp.read(14).unpack("SLSSL") #データオフセット値 offset = filehead[4] #Windows, OS/2 のフォーマット判別 flaghead = infp.read(4).unpack("L") #OS/2 のフォーマットの場合 if flaghead[0] == 12 then infohead = infp.read(36).unpack("ssSS") width = infohead[0].abs height = infohead[1].abs #Windowsフォーマットの場合 elsif flaghead[0] == 40 then infohead = infp.read(36).unpack("llSSLLllLL") width = infohead[0].abs height = infohead[1].abs else p "This file may not be .bmp format" exit end # make x axis xdata = NArray[0..width-1] xary = VArray.new(xdata, {"long_name"=>"x", "units"=>"pixels"}, "x") xaxis = Axis.new xaxis.pos = xary # make y axis ydata = NArray[0..height-1] yary = VArray.new(ydata, {"long_name"=>"y", "units"=>"pixels"}, "y") yaxis = Axis.new yaxis.pos = yary #8bit bmpの場合 if infohead[3] == 8 then array = Array.new infp.pos = offset height.times{ warray = infp.read(width).unpack("C*") array << warray } na = NArray.to_na(array) va = VArray.new(na, {"long_name"=>"Intensity", "units"=>"none"},"I") grid = Grid.new(xaxis, yaxis) gphys = GPhys.new(grid, va) p gphys #書き出し outfile = NetCDF.create(ARGV[0].sub(".bmp", ".nc")) GPhys::NetCDF_IO.write( outfile, gphys) outfile.close #24bit bmpの場合 elsif infohead[3] ==24 then arrayR = Array.new arrayG = Array.new arrayB = Array.new infp.pos = offset height.times{ warrayR = Array.new warrayG = Array.new warrayB = Array.new width.times{ carray = infp.read(3).unpack("C*") warrayB << carray[0] warrayG << carray[1] warrayR << carray[2] } arrayR << warrayR arrayG << warrayG arrayB << warrayB } naR = NArray.to_na(arrayR) naG = NArray.to_na(arrayG) naB = NArray.to_na(arrayB) grid = Grid.new(xaxis, yaxis) vaR = VArray.new(naR, {"long_name"=>"R", "units"=>"none"},"R") gphysR = GPhys.new(grid, vaR) vaG = VArray.new(naG, {"long_name"=>"G", "units"=>"none"},"G") gphysG = GPhys.new(grid, vaG) vaB = VArray.new(naB, {"long_name"=>"B", "units"=>"none"},"B") gphysB = GPhys.new(grid, vaB) va = VArray.new(naR + naG + naB, {"long_name"=>"R+G+B", "units"=>"none"},"I") gphys = GPhys.new(grid, va) p gphys #書き出し outfile = NetCDF.create(ARGV[0].sub(".bmp", ".nc")) GPhys::NetCDF_IO.write( outfile, gphysR) GPhys::NetCDF_IO.write( outfile, gphysG) GPhys::NetCDF_IO.write( outfile, gphysB) GPhys::NetCDF_IO.write( outfile, gphys) outfile.close #32bit bmpの場合 elsif infohead[3] ==32 then arrayR = Array.new arrayG = Array.new arrayB = Array.new infp.pos = offset height.times{ warrayR = Array.new warrayG = Array.new warrayB = Array.new width.times{ carray = infp.read(4).unpack("C*") warrayB << carray[0] warrayG << carray[1] warrayR << carray[2] } arrayR << warrayR arrayG << warrayG arrayB << warrayB } naR = NArray.to_na(arrayR) naG = NArray.to_na(arrayG) naB = NArray.to_na(arrayB) grid = Grid.new(xaxis, yaxis) vaR = VArray.new(naR, {"long_name"=>"R", "units"=>"none"},"R") gphysR = GPhys.new(grid, vaR) vaG = VArray.new(naG, {"long_name"=>"G", "units"=>"none"},"G") gphysG = GPhys.new(grid, vaG) vaB = VArray.new(naB, {"long_name"=>"B", "units"=>"none"},"B") gphysB = GPhys.new(grid, vaB) va = VArray.new(naR + naG + naB, {"long_name"=>"R+G+B", "units"=>"none"},"I") gphys = GPhys.new(grid, va) p gphys #書き出し outfile = NetCDF.create(ARGV[0].sub(".bmp", ".nc")) GPhys::NetCDF_IO.write( outfile, gphysR) GPhys::NetCDF_IO.write( outfile, gphysG) GPhys::NetCDF_IO.write( outfile, gphysB) GPhys::NetCDF_IO.write( outfile, gphys) outfile.close end infp.close
補足
- BMPからデータを取り出す際に一度 Array オブジェクトで取り出してから、NArrayオブジェクトに変換しているので、無駄が多い & 遅くなっているかと思います。
キーワード:[BMP] [NetCDF]
参照: