设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 3221|回复: 6
打印 上一主题 下一主题

[已经过期] 有关截图图片转换为PNG的方法

 关闭 [复制链接]

Lv1.梦旅人

梦石
0
星屑
51
在线时间
6 小时
注册时间
2010-10-24
帖子
5
跳转到指定楼层
1
发表于 2011-6-19 14:42:59 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 fux2 于 2011-6-19 18:38 编辑

本人想把GetBitmapBits得到的BMP格式转化为PNG,可是得到的是BGRA通道,而PNG中是RGBA,所以直接得到的图像很难看(红蓝通道相反),但是如果每个BGRA数组翻转成RGBA时间又太长,如下代码需要约20秒才能生成一个PNG文件,请高人相助!
  1. class << Graphics
  2.   CreateCompatibleBitmap = Win32API.new("gdi32", "CreateCompatibleBitmap", "lll", "l")
  3.   CreateCompatibleDC = Win32API.new("gdi32", "CreateCompatibleDC", "l", "l")
  4.   SelectObject = Win32API.new("gdi32", "SelectObject", "ll", "l")
  5.   BitBlt = Win32API.new("gdi32", "BitBlt", "lllllllll", "l")
  6.   GetBitmapBits = Win32API.new("gdi32", "GetBitmapBits", "llp", "l")
  7.   ScreenToClient = Win32API.new("user32", "ScreenToClient", "ip", "i")
  8.   DeleteDC = Win32API.new("gdi32", "DeleteDC", "l", "l")
  9.   DeleteObject = Win32API.new("gdi32", "DeleteObject", "l", "l")
  10.   CrFnt = Win32API.new("gdi32","CreateFont","l"*13+"p","l")
  11.   SRCCOPY = 0xCC0020
  12.   DwCount = (640 * 480 * 4) * 2
  13.   @@lpBits = "\000" * DwCount
  14.   def bitmap_data(times)
  15.     hScrDC = $hDC
  16.     hMemDC = CreateCompatibleDC.call(hScrDC)
  17.     hBitmap = CreateCompatibleBitmap.call(hScrDC, 640, 480)
  18.     SelectObject.call(hMemDC, hBitmap)
  19.     BitBlt.call(hMemDC, 0, 0, 640*2, 480*2, hScrDC, 0, 0, SRCCOPY)
  20.     rect = [0,0,300,100].pack("llll")

  21.     hfont = CrFnt.call(20,10,50,0,1500,1,0,0,0,0,0,0,0,"Lucida Sans")

  22.     Win32API.new("gdi32","SetBkColor","ll","l").call(hMemDC,255)
  23.     Win32API.new("gdi32","SetTextColor","ll","l").call(hMemDC,16777215)
  24.     SelectObject.call(hMemDC,hfont)
  25.     Win32API.new("user32","DrawText","lplpl","l").call(hMemDC,"2012 Doomsday Replay #{times}:",-1,rect,0x37)

  26.     GetBitmapBits.call(hBitmap, DwCount, @@lpBits)
  27.     DeleteDC.call(hScrDC)
  28.     DeleteDC.call(hMemDC)
  29.     DeleteObject.call(hBitmap)
  30.     DeleteObject.call(hfont)
  31.     for i in 1..307200
  32.       if i%100000 == 0 then Graphics.update end
  33.       @@lpBits[4*i-4,3]=@@lpBits[4*i-4,3].reverse # 翻转红蓝通道,这个时间有点长,求高手帮忙!
  34.                 #RGBA           #BGRA
  35.       @@lpBits[4*i-1]=255
  36.     end
  37.     return @@lpBits
  38.   end
  39. end

  40. class Png_File
  41.   #--------------------------------------------------------------------------
  42.   # ● 主处理
  43.   #--------------------------------------------------------------------------
  44.   def initialize(times)
  45.     @times=times
  46.     f = File.open("Graphics/Pictures/Replay#{@times}.png","wb")#Zlib::GzipWriter.open("Graphics/Pictures/Replay#{times}.png")
  47.     f.write(make_header)
  48.     f.write(make_ihdr)
  49.     f.write(make_idat)
  50.     f.write(make_iend)
  51.     f.close
  52.   end
  53.   #--------------------------------------------------------------------------
  54.   # ● PNG文件头数据块
  55.   #--------------------------------------------------------------------------
  56.   def make_header
  57.     return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
  58.   end
  59.   #--------------------------------------------------------------------------
  60.   # ● PNG文件情报头数据块(IHDR)
  61.   #--------------------------------------------------------------------------
  62.   def make_ihdr
  63.     ih_size = [13].pack("N")
  64.     ih_sign = "IHDR"
  65.     ih_width = [640].pack("N")
  66.     ih_height = [480].pack("N")
  67.     ih_bit_depth = [8].pack("C")
  68.     ih_color_type = [6].pack("C")
  69.     ih_compression_method = [0].pack("C")
  70.     ih_filter_method = [0].pack("C")
  71.     ih_interlace_method = [0].pack("C")
  72.     string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
  73.              ih_compression_method + ih_filter_method + ih_interlace_method
  74.     ih_crc = [Zlib.crc32(string)].pack("N")
  75.     return ih_size + string + ih_crc
  76.   end
  77.   #--------------------------------------------------------------------------
  78.   # ● 生成图像数据(IDAT)
  79.   #--------------------------------------------------------------------------
  80.   def make_idat
  81.     header = "\x49\x44\x41\x54"
  82.     data = make_bitmap_data
  83.     data = Zlib::Deflate.deflate(data, 8)
  84.     crc = [Zlib.crc32(header + data)].pack("N")
  85.     size = [data.length].pack("N")
  86.     return size + header + data + crc
  87.   end
  88.   #--------------------------------------------------------------------------
  89.   # ● 从Bitmap对象中生成图像数据 mode 0
  90.   #--------------------------------------------------------------------------
  91.   def make_bitmap_data
  92.     data1=Graphics.bitmap_data(@times)
  93.     data=""
  94.     for i in 0...480
  95.       data+=[0].pack("C")
  96.       data+=data1[640*4*i,640*4]
  97.     end
  98.     return data
  99.   end
  100.   #--------------------------------------------------------------------------
  101.   # ● PNG文件尾数据块(IEND)
  102.   #--------------------------------------------------------------------------
  103.   def make_iend
  104.     ie_size = [0].pack("N")
  105.     ie_sign = "IEND"
  106.     ie_crc = [Zlib.crc32(ie_sign)].pack("N")
  107.     return ie_size + ie_sign + ie_crc
  108.   end
  109. module RM_ASM
  110.   def self.findWindow(hwnd1 = 0,file = "./Game.ini")
  111.     Win32API.new("user32","FindWindowEx","llpp","l").call(0,hwnd1,"RGSS Player",readIni(file))
  112.   end
  113.   def self.readIni(file)
  114.     buf = 0.chr * 256
  115.     gpps = Win32API.new("kernel32","GetPrivateProfileString","pppplp","l")
  116.     gpps.call("Game","Title","",buf,256,file)
  117.     buf.delete!("\0")
  118.     return buf
  119.   end
  120.   $hWnd = Win32API.new("user32","GetActiveWindow","","l").call
  121.   hwnd2 = findWindow
  122.   if hwnd2 == $hWnd
  123.     hwnd2 = findWindow(hwnd2)
  124.     if hwnd2 != 0
  125.       Win32API.new("user32","SetForegroundWindow","l","l").call(hwnd2)
  126.       exit(2)
  127.     end
  128.   else
  129.     Win32API.new("user32","SetForegroundWindow","l","l").call(hwnd2)
  130.     exit(2)
  131.   end
  132.   $hDC  = Win32API.new("user32","GetDC","l","l").call($hWnd)
  133.   module_function
  134.   def printscreen(times)
  135.     $PNG = Png_File.new(times)
  136.     print "Replay 已保存至 Replay#{times}.png"
  137.   end
  138. end
复制代码
dsu_plus_rewardpost_czw

Lv1.梦旅人

梦石
0
星屑
51
在线时间
6 小时
注册时间
2010-10-24
帖子
5
2
 楼主| 发表于 2011-6-20 18:40:51 | 显示全部楼层
本帖最后由 API_Studier 于 2011-6-20 18:42 编辑

总共要处理307200(640*480)个点,看这一句:if i%100000 == 0 then Graphics.update end
每100000个点会更新一下。不过感谢你的回复(汗……轮回者的这篇没搜到)

点评

图像处理会越来越慢,你可以试看连续处理几十张,应该会马上脚本备份。 具体做法最好是先固定一整个位置的bitmap在内存处理,速度较快没有10s问题  发表于 2011-6-21 12:14
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
51
在线时间
6 小时
注册时间
2010-10-24
帖子
5
3
 楼主| 发表于 2011-7-2 09:05:31 | 显示全部楼层
本帖最后由 API_Studier 于 2011-7-2 16:38 编辑

谢谢苏小脉的回答!(最近有些忙,未能及时查看回复,见谅)


API_Studier于2011-7-2 16:31补充以下内容:
刚刚试了下,整个速度快了约15秒,十分感谢!


API_Studier于2011-7-2 16:35补充以下内容:
  1. module RM_ASM
  2.   def self.findWindow(hwnd1 = 0,file = "./Game.ini")
  3.     Win32API.new("user32","FindWindowEx","llpp","l").call(0,hwnd1,"RGSS Player",readIni(file))
  4.   end
  5.   def self.readIni(file)
  6.     buf = 0.chr * 256
  7.     gpps = Win32API.new("kernel32","GetPrivateProfileString","pppplp","l")
  8.     gpps.call("Game","Title","",buf,256,file)
  9.     buf.delete!("\0")
  10.     return buf
  11.   end
  12.   Win32API.new("kernel32","CopyFile","ppl","l").call("Movie.exe","Save/Movie-Copy.exe",0) # 备份Movie.exe
  13.   $hWnd = Win32API.new("user32","GetActiveWindow","","l").call
  14.   hwnd2 = findWindow
  15.   if hwnd2 == $hWnd
  16.     hwnd2 = findWindow(hwnd2)
  17.     if hwnd2 != 0
  18.       Win32API.new("user32","SetForegroundWindow","l","l").call(hwnd2)
  19.       exit(2)
  20.     end
  21.   else
  22.     Win32API.new("user32","SetForegroundWindow","l","l").call(hwnd2)
  23.     exit(2)
  24.   end
  25.   $hDC  = Win32API.new("user32","GetDC","l","l").call($hWnd)
  26.   module_function
  27.   def printscreen(times)
  28.     Png_File.new(times)
  29.     print "Replay 已保存至 Replay#{times}.png"
  30.   end
  31. end

  32. unless FileTest.exist?('Data/UR.rxdata')
  33.   file = Zlib::GzipWriter.open('Data/UR.rxdata',9)
  34.   @string = 'Unknowrank_is_false'
  35.   Marshal.dump(@string,file)
  36.   file.close
  37. end

  38. print "本游戏有关影片为《2012世界末日》,与最近播出的《2012》无关系,不清楚的请补好功课!"


  39. module Graphics
  40.   DwCount = (640 * 480 * 4) * 2
  41.   @@lpBits = "\000" * DwCount
  42.   class << self
  43.     CreateCompatibleBitmap = Win32API.new("gdi32", "CreateCompatibleBitmap", "lll", "l")
  44.     CreateCompatibleDC = Win32API.new("gdi32", "CreateCompatibleDC", "l", "l")
  45.     SelectObject = Win32API.new("gdi32", "SelectObject", "ll", "l")
  46.     BitBlt = Win32API.new("gdi32", "BitBlt", "lllllllll", "l")
  47.     GetBitmapBits = Win32API.new("gdi32", "GetBitmapBits", "llp", "l")
  48.     ScreenToClient = Win32API.new("user32", "ScreenToClient", "ip", "i")
  49.     DeleteDC = Win32API.new("gdi32", "DeleteDC", "l", "l")
  50.     DeleteObject = Win32API.new("gdi32", "DeleteObject", "l", "l")
  51.     CrFnt = Win32API.new("gdi32","CreateFont","l"*13+"p","l")
  52.     SRCCOPY = 0xCC0020
  53.     def bitmap_data(times)
  54.       hScrDC = $hDC
  55.       hMemDC = CreateCompatibleDC.call(hScrDC)
  56.       hBitmap = CreateCompatibleBitmap.call(hScrDC, 640, 480)
  57.       SelectObject.call(hMemDC, hBitmap)
  58.       BitBlt.call(hMemDC, 0, 0, 640*2, 480*2, hScrDC, 0, 0, SRCCOPY)
  59.       rect = [0,0,300,100].pack("llll")

  60.       hfont = CrFnt.call(20,10,50,0,1500,1,0,0,0,0,0,0,0,"Lucida Sans")

  61.       Win32API.new("gdi32","SetBkColor","ll","l").call(hMemDC,255)
  62.       Win32API.new("gdi32","SetTextColor","ll","l").call(hMemDC,16777215)
  63.       SelectObject.call(hMemDC,hfont)
  64.       Win32API.new("user32","DrawText","lplpl","l").call(hMemDC,"2012 Doomsday Replay #{times}:",-1,rect,0x37)

  65.       GetBitmapBits.call(hBitmap, DwCount, @@lpBits)
  66.       DeleteDC.call(hScrDC)
  67.       DeleteDC.call(hMemDC)
  68.       DeleteObject.call(hBitmap)
  69.       DeleteObject.call(hfont)
  70.       for i in 1..307200
  71.         a = i * 4
  72.         b = a + 2
  73.         tmp = @@lpBits[a]
  74.         @@lpBits[a] = @@lpBits[b]
  75.         @@lpBits[b] = tmp
  76.         @@lpBits[b + 1] = 255
  77.       end
  78.       return @@lpBits
  79.     end
  80.   end
  81. end

  82. class Png_File
  83.   #--------------------------------------------------------------------------
  84.   # ● 主处理
  85.   #--------------------------------------------------------------------------
  86.   def initialize(times)
  87.     @times=times
  88.     f = File.open("Graphics/Pictures/Replay#{@times}.png","wb")#Zlib::GzipWriter.open("Graphics/Pictures/Replay#{times}.png")
  89.     f.write(make_header)
  90.     f.write(make_ihdr)
  91.     f.write(make_idat)
  92.     f.write(make_iend)
  93.     f.close
  94.   end
  95.   #--------------------------------------------------------------------------
  96.   # ● PNG文件头数据块
  97.   #--------------------------------------------------------------------------
  98.   def make_header
  99.     return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
  100.   end
  101.   #--------------------------------------------------------------------------
  102.   # ● PNG文件情报头数据块(IHDR)
  103.   #--------------------------------------------------------------------------
  104.   def make_ihdr
  105.     ih_size = [13].pack("N")
  106.     ih_sign = "IHDR"
  107.     ih_width = [640].pack("N")
  108.     ih_height = [480].pack("N")
  109.     ih_bit_depth = [8].pack("C")
  110.     ih_color_type = [6].pack("C")
  111.     ih_compression_method = [0].pack("C")
  112.     ih_filter_method = [0].pack("C")
  113.     ih_interlace_method = [0].pack("C")
  114.     string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
  115.              ih_compression_method + ih_filter_method + ih_interlace_method
  116.     ih_crc = [Zlib.crc32(string)].pack("N")
  117.     return ih_size + string + ih_crc
  118.   end
  119.   #--------------------------------------------------------------------------
  120.   # ● 生成图像数据(IDAT)
  121.   #--------------------------------------------------------------------------
  122.   def make_idat
  123.     header = "\x49\x44\x41\x54"
  124.     data = make_bitmap_data
  125.     data = Zlib::Deflate.deflate(data, 8)
  126.     crc = [Zlib.crc32(header + data)].pack("N")
  127.     size = [data.length].pack("N")
  128.     return size + header + data + crc
  129.   end
  130.   #--------------------------------------------------------------------------
  131.   # ● 从Bitmap对象中生成图像数据 mode 0
  132.   #--------------------------------------------------------------------------
  133.   def make_bitmap_data
  134.     data1=Graphics.bitmap_data(@times)
  135.     data=""
  136.     for i in 0...480
  137.       data+=[0].pack("C")
  138.       data+=data1[640*4*i,640*4]
  139.     end
  140.     return data
  141.   end
  142.   #--------------------------------------------------------------------------
  143.   # ● PNG文件尾数据块(IEND)
  144.   #--------------------------------------------------------------------------
  145.   def make_iend
  146.     ie_size = [0].pack("N")
  147.     ie_sign = "IEND"
  148.     ie_crc = [Zlib.crc32(ie_sign)].pack("N")
  149.     return ie_size + ie_sign + ie_crc
  150.   end
  151. end

  152. module RM_ASM
  153.   $hWnd = Win32API.new("user32","GetActiveWindow","","l").call
  154.   $hDC  = Win32API.new("user32","GetDC","l","l").call($hWnd)
  155.   module_function
  156.   def printscreen(times)
  157.     Png_File.new(times)
  158.     print "Replay 已保存至 Replay#{times}.png"
  159.   end
  160. end
复制代码
使用时可以:RM_ASM.printscreen(times),保存为png格式,从此再也无需动态链接库了!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-5-3 06:46

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表