# Bitmap Export v5.4 for XP, VX and VXace by Zeus81 # Free for commercial use # Licence : [url]http://creativecommons.org/licenses/by/4.0/[/url] # Contact : [email protected] # How to Use : # - exporting bitmap : # bitmap.export(filename) # or bitmap.save(filename) # # - serialize bitmap : # open(filename, 'wb') {|file| Marshal.dump(bitmap, file)} # bitmap = open(filename, 'rb') {|file| Marshal.load(file)} # or # save_data(bitmap, filename) # bitmap = load_data(filename) # # - snapshot : # Graphics.export(filename) # or Graphics.save(filename) # or Graphics.snapshot(filename) # Here filename is optional, and will be replaced by datetime if omitted. $imported ||= {} $imported[:Zeus_Bitmap_Export] = __FILE__ def xp?() false end; alias vx? xp?; alias vxace? xp? RUBY_VERSION == '1.8.1' ? defined?(Hangup) ? def xp?() true end : def vx?() true end : def vxace?() true end class String alias getbyte [] alias setbyte []= alias bytesize size end unless vxace? class Font def marshal_dump() end def marshal_load(dump) end end class Bitmap RtlMoveMemory = Win32API.new('kernel32', 'RtlMoveMemory', 'ppi', 'i') def last_row_address return 0 if disposed? RtlMoveMemory.call(buf=[0].pack('L'), __id__*2+16, 4) RtlMoveMemory.call(buf, buf.unpack('L')[0]+8 , 4) RtlMoveMemory.call(buf, buf.unpack('L')[0]+16, 4) buf.unpack('L')[0] end def bytesize width * height * 4 end def get_data data = [].pack('x') * bytesize RtlMoveMemory.call(data, last_row_address, data.bytesize) data end def set_data(data) RtlMoveMemory.call(last_row_address, data, data.bytesize) end def get_data_ptr data = String.new RtlMoveMemory.call(data.__id__*2, [vxace? ? 0x6005 : 0x2007].pack('L'), 4) RtlMoveMemory.call(data.__id__*2+8, [bytesize,last_row_address].pack('L2'), 8) def data.free() RtlMoveMemory.call(__id__*2, String.new, 16) end return data unless block_given? yield data ensure data.free end def _dump(level) get_data_ptr do |data| dump = Marshal.dump([width, height, Zlib::Deflate.deflate(data, 9)]) dump.force_encoding('UTF-8') if vxace? dump end end def self._load(dump) width, height, data = *Marshal.load(dump) data.replace(Zlib::Inflate.inflate(data)) bitmap = new(width, height) bitmap.set_data(data) bitmap end def export(filename) case format=File.extname(filename) when '.bmp'; export_bmp(filename) when '.png'; export_png(filename) when '' ; export_png("#{filename}.png") else print("Export format '#{format}' not supported.") end end alias save export def export_bmp(filename) get_data_ptr do |data| File.open(filename, 'wb') do |file| file.write(['BM',data.bytesize+54,0,54,40,width,height, 1,32,0,data.bytesize,0,0,0,0].pack('a2L6S2L6')) file.write(data) end end end def export_png(filename) data, i = get_data, 0 if vxace? (0).step(data.bytesize-4, 4) do |i| byte2 = data.getbyte(i) data.setbyte(i, data.getbyte(i+2)) data.setbyte(i+2, byte2) end else (0).step(data.bytesize-4, 4) do |i| data[i,3] = data[i,3].reverse! end end deflate = Zlib::Deflate.new(9) null_char, w4 = [].pack('x'), width*4 (data.bytesize-w4).step(0, -w4) {|i| deflate << null_char << data[i,w4]} data.replace(deflate.finish) deflate.close dir = "Save/" File.open(dir + filename, 'wb') do |file| def file.write_chunk(chunk) write([chunk.bytesize-4].pack('N')) write(chunk) write([Zlib.crc32(chunk)].pack('N')) end file.write("\211PNG\r\n\32\n") file.write_chunk(['IHDR',width,height,8,6,0,0,0].pack('a4N2C5')) file.write_chunk(data.insert(0, 'IDAT')) file.write_chunk('IEND') end end end module Graphics if xp? FindWindow = Win32API.new('user32', 'FindWindow' , 'pp' , 'i') GetDC = Win32API.new('user32', 'GetDC' , 'i' , 'i') ReleaseDC = Win32API.new('user32', 'ReleaseDC' , 'ii' , 'i') BitBlt = Win32API.new('gdi32' , 'BitBlt' , 'iiiiiiiii', 'i') CreateCompatibleBitmap = Win32API.new('gdi32' , 'CreateCompatibleBitmap', 'iii' , 'i') CreateCompatibleDC = Win32API.new('gdi32' , 'CreateCompatibleDC' , 'i' , 'i') DeleteDC = Win32API.new('gdi32' , 'DeleteDC' , 'i' , 'i') DeleteObject = Win32API.new('gdi32' , 'DeleteObject' , 'i' , 'i') GetDIBits = Win32API.new('gdi32' , 'GetDIBits' , 'iiiiipi' , 'i') SelectObject = Win32API.new('gdi32' , 'SelectObject' , 'ii' , 'i') def self.snap_to_bitmap bitmap = Bitmap.new(width, height) info = [40,width,height,1,32,0,0,0,0,0,0].pack('LllSSLLllLL') hDC = GetDC.call(hwnd) bmp_hDC = CreateCompatibleDC.call(hDC) bmp_hBM = CreateCompatibleBitmap.call(hDC, width, height) bmp_obj = SelectObject.call(bmp_hDC, bmp_hBM) BitBlt.call(bmp_hDC, 0, 0, width, height, hDC, 0, 0, 0xCC0020) GetDIBits.call(bmp_hDC, bmp_hBM, 0, height, bitmap.last_row_address, info, 0) SelectObject.call(bmp_hDC, bmp_obj) DeleteObject.call(bmp_hBM) DeleteDC.call(bmp_hDC) ReleaseDC.call(hwnd, hDC) bitmap end end class << self def hwnd() @hwnd ||= FindWindow.call('RGSS Player', nil) end def width() 640 end unless method_defined?(:width) def height() 480 end unless method_defined?(:height) def export(filename=Time.now.strftime("snapshot %Y-%m-%d %Hh%Mm%Ss #{frame_count}")) bitmap = snap_to_bitmap bitmap.export(filename) bitmap.dispose end alias save export alias snapshot export end end