(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 になります。

bmp2nc.rb

使い方

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オブジェクトに変換しているので、無駄が多い & 遅くなっているかと思います。
更新日時:2011/03/09 18:10:41
キーワード:[BMP] [NetCDF]
参照: