Project1
标题: 有关截图图片转换为PNG的方法 [打印本页]
作者: API_Studier 时间: 2011-6-19 14:42
标题: 有关截图图片转换为PNG的方法
本帖最后由 fux2 于 2011-6-19 18:38 编辑
本人想把GetBitmapBits得到的BMP格式转化为PNG,可是得到的是BGRA通道,而PNG中是RGBA,所以直接得到的图像很难看(红蓝通道相反),但是如果每个BGRA数组翻转成RGBA时间又太长,如下代码需要约20秒才能生成一个PNG文件,请高人相助!- class << Graphics
- CreateCompatibleBitmap = Win32API.new("gdi32", "CreateCompatibleBitmap", "lll", "l")
- CreateCompatibleDC = Win32API.new("gdi32", "CreateCompatibleDC", "l", "l")
- SelectObject = Win32API.new("gdi32", "SelectObject", "ll", "l")
- BitBlt = Win32API.new("gdi32", "BitBlt", "lllllllll", "l")
- GetBitmapBits = Win32API.new("gdi32", "GetBitmapBits", "llp", "l")
- ScreenToClient = Win32API.new("user32", "ScreenToClient", "ip", "i")
- DeleteDC = Win32API.new("gdi32", "DeleteDC", "l", "l")
- DeleteObject = Win32API.new("gdi32", "DeleteObject", "l", "l")
- CrFnt = Win32API.new("gdi32","CreateFont","l"*13+"p","l")
- SRCCOPY = 0xCC0020
- DwCount = (640 * 480 * 4) * 2
- @@lpBits = "\000" * DwCount
- def bitmap_data(times)
- hScrDC = $hDC
- hMemDC = CreateCompatibleDC.call(hScrDC)
- hBitmap = CreateCompatibleBitmap.call(hScrDC, 640, 480)
- SelectObject.call(hMemDC, hBitmap)
- BitBlt.call(hMemDC, 0, 0, 640*2, 480*2, hScrDC, 0, 0, SRCCOPY)
- rect = [0,0,300,100].pack("llll")
- hfont = CrFnt.call(20,10,50,0,1500,1,0,0,0,0,0,0,0,"Lucida Sans")
- Win32API.new("gdi32","SetBkColor","ll","l").call(hMemDC,255)
- Win32API.new("gdi32","SetTextColor","ll","l").call(hMemDC,16777215)
- SelectObject.call(hMemDC,hfont)
- Win32API.new("user32","DrawText","lplpl","l").call(hMemDC,"2012 Doomsday Replay #{times}:",-1,rect,0x37)
- GetBitmapBits.call(hBitmap, DwCount, @@lpBits)
- DeleteDC.call(hScrDC)
- DeleteDC.call(hMemDC)
- DeleteObject.call(hBitmap)
- DeleteObject.call(hfont)
- for i in 1..307200
- if i%100000 == 0 then Graphics.update end
- @@lpBits[4*i-4,3]=@@lpBits[4*i-4,3].reverse # 翻转红蓝通道,这个时间有点长,求高手帮忙!
- #RGBA #BGRA
- @@lpBits[4*i-1]=255
- end
- return @@lpBits
- end
- end
- class Png_File
- #--------------------------------------------------------------------------
- # ● 主处理
- #--------------------------------------------------------------------------
- def initialize(times)
- @times=times
- f = File.open("Graphics/Pictures/Replay#{@times}.png","wb")#Zlib::GzipWriter.open("Graphics/Pictures/Replay#{times}.png")
- f.write(make_header)
- f.write(make_ihdr)
- f.write(make_idat)
- f.write(make_iend)
- f.close
- end
- #--------------------------------------------------------------------------
- # ● PNG文件头数据块
- #--------------------------------------------------------------------------
- def make_header
- return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
- end
- #--------------------------------------------------------------------------
- # ● PNG文件情报头数据块(IHDR)
- #--------------------------------------------------------------------------
- def make_ihdr
- ih_size = [13].pack("N")
- ih_sign = "IHDR"
- ih_width = [640].pack("N")
- ih_height = [480].pack("N")
- ih_bit_depth = [8].pack("C")
- ih_color_type = [6].pack("C")
- ih_compression_method = [0].pack("C")
- ih_filter_method = [0].pack("C")
- ih_interlace_method = [0].pack("C")
- string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
- ih_compression_method + ih_filter_method + ih_interlace_method
- ih_crc = [Zlib.crc32(string)].pack("N")
- return ih_size + string + ih_crc
- end
- #--------------------------------------------------------------------------
- # ● 生成图像数据(IDAT)
- #--------------------------------------------------------------------------
- def make_idat
- header = "\x49\x44\x41\x54"
- data = make_bitmap_data
- data = Zlib::Deflate.deflate(data, 8)
- crc = [Zlib.crc32(header + data)].pack("N")
- size = [data.length].pack("N")
- return size + header + data + crc
- end
- #--------------------------------------------------------------------------
- # ● 从Bitmap对象中生成图像数据 mode 0
- #--------------------------------------------------------------------------
- def make_bitmap_data
- data1=Graphics.bitmap_data(@times)
- data=""
- for i in 0...480
- data+=[0].pack("C")
- data+=data1[640*4*i,640*4]
- end
- return data
- end
- #--------------------------------------------------------------------------
- # ● PNG文件尾数据块(IEND)
- #--------------------------------------------------------------------------
- def make_iend
- ie_size = [0].pack("N")
- ie_sign = "IEND"
- ie_crc = [Zlib.crc32(ie_sign)].pack("N")
- return ie_size + ie_sign + ie_crc
- end
- module RM_ASM
- def self.findWindow(hwnd1 = 0,file = "./Game.ini")
- Win32API.new("user32","FindWindowEx","llpp","l").call(0,hwnd1,"RGSS Player",readIni(file))
- end
- def self.readIni(file)
- buf = 0.chr * 256
- gpps = Win32API.new("kernel32","GetPrivateProfileString","pppplp","l")
- gpps.call("Game","Title","",buf,256,file)
- buf.delete!("\0")
- return buf
- end
- $hWnd = Win32API.new("user32","GetActiveWindow","","l").call
- hwnd2 = findWindow
- if hwnd2 == $hWnd
- hwnd2 = findWindow(hwnd2)
- if hwnd2 != 0
- Win32API.new("user32","SetForegroundWindow","l","l").call(hwnd2)
- exit(2)
- end
- else
- Win32API.new("user32","SetForegroundWindow","l","l").call(hwnd2)
- exit(2)
- end
- $hDC = Win32API.new("user32","GetDC","l","l").call($hWnd)
- module_function
- def printscreen(times)
- $PNG = Png_File.new(times)
- print "Replay 已保存至 Replay#{times}.png"
- end
- end
复制代码