read and write '.bmp' file

class Bitmap
	FILE_HEADER = "S<L<S<S<L<"
	INFO_HEADER = "L<l<l<S<S<L<L<l<l<L<L<"
	BM = 'B'.ord+('M'.ord<<8)
	CCC = "CCC".freeze
	attr_reader :width
	attr_reader :height
	attr_reader :blob
	def initialize width, height, blob="\0"*(width*height*3)
		@width = width
		@height = height
		@blob = blob
	end
	def self.load filename
		open filename,"rb" do |file|
			header = file.read(14).unpack FILE_HEADER
			raise unless header[0]==BM
			raise unless header[1]==file.size
			raise unless header.last==54
			dib = file.read(40).unpack INFO_HEADER
			raise unless dib[4]==24
			width, height = dib[1,2]
			raise unless height>0
			blob = "\0"*(width*height*3)
			(height-1).downto 0 do |y|
				0.upto(width-1) do |x|
					b, g, r = file.read(3).unpack CCC
					blob[(y*width+x)*3,3] = [r,g,b].pack CCC
				end
				file.read(width%4)
			end
			self.new width, height, blob
		end
	end
	def save filename
		raise unless @blob.size==@width*@height*3
		size = (24*@width+31).div(32)*4*@height
		header = [BM, size+54, 0, 0, 54]
		dib = [40, @width, @height, 1, 24, 0, size, 3780, 3780, 0, 0]
		open filename,"wb" do |file|
			file.write header.pack FILE_HEADER
			file.write dib.pack INFO_HEADER
			(@height-1).downto 0 do |y|
				0.upto(@width-1) do |x|
					r, g, b = @blob[(y*@width+x)*3,3].unpack CCC
					file.write [b, g, r].pack CCC
				end
				file.write "\0"*(@width%4)
			end			
		end
		nil
	end
	def [] x,y
		@blob[(y*@width+x)*3,3].unpack CCC
	end
	def []= x,y,rgb
		@blob[(y*@width+x)*3,3] = rgb.pack CCC
	end
end

def Bitmap::run_test
	b = Bitmap.load "test.bmp"
	b2 = Bitmap.new(b.width*2,b.height*2)
	for y in 0...b.height
		for x in 0...b.width
			rgb = b[x,y]
			b2[x*2,y*2] = rgb
			b2[x*2,y*2+1] = [0,0,255]
			b2[x*2+1,y*2] = rgb
			b2[x*2+1,y*2+1] = [128,0,0]
		end
	end
	b2.save "test2.bmp"
	puts 'ok'
end

Bitmap::run_test if __FILE__ == $0


Only 24-bit bmp file is supported here。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值