查看: 8956|回复: 6

[通用发布] 保存Bitmap为PNG文件(快速+无DLL)

[复制链接]
梦石
0
星屑
60
在线时间
156 小时
注册时间
2011-12-13
回帖
127
发表于 2012-3-4 13:06:46 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 dant 于 2012-3-4 13:40 编辑

虽然没有用DLL,但是BGRA->RGBA的处理还是用了一种很龌龊的方法
[pre lang="ruby" line="1"]#encoding:utf-8
#==============================================================================
# ■ Bitmap
#------------------------------------------------------------------------------
#  位图的类。所谓位图即表示图像其本身。
#==============================================================================

class Bitmap
  #--------------------------------------------------------------------------
  # ● 传送到内存的API函数
  #--------------------------------------------------------------------------
  RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  #--------------------------------------------------------------------------
  # ● Bitmap地址
  #--------------------------------------------------------------------------
  # [[[bitmap.object_id * 2 + 16] + 8] + 16] == 数据的开头
  def address
    buffer, ad = "rgba", object_id * 2 + 16
    RtlMoveMemory_pi.call(buffer, ad, 4)
    ad = buffer.unpack("L")[0] + 8
    RtlMoveMemory_pi.call(buffer, ad, 4)
    ad = buffer.unpack("L")[0] + 16
    RtlMoveMemory_pi.call(buffer, ad, 4)
    return buffer.unpack("L")[0]
  end
  
  module Bitmap2PNG
    module_function
    Malloc = Win32API.new('msvcrt.dll','malloc','i','i')
    Memcpy_pi = Win32API.new('kernel32.dll','RtlMoveMemory','pii','v')
    Memcpy_ii = Win32API.new('kernel32.dll','RtlMoveMemory','iii','v')
    Memcpy_ip = Win32API.new('kernel32.dll','RtlMoveMemory','ipi','v')
    Free = Win32API.new('msvcrt.dll','free','i','v')
    Callsub = Win32API.new('user32.dll','CallWindowProcW','iiiii','i')
    #--------------------------------------------------------------------------
    # ● 主处理
    #--------------------------------------------------------------------------
    def make_png(bitmap_Fx)
      @bitmap_Fx = bitmap_Fx
      return make_header + make_ihdr + make_idat + make_iend
    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 = [@bitmap_Fx.width].pack("N")
      ih_height = [@bitmap_Fx.height].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 = "IDAT"
      data = make_bitmap_data_dant
      data = Zlib::Deflate.deflate(data)
      crc = [Zlib.crc32(header + data)].pack("N")
      size = [data.length].pack("N")
      return size + header + data + crc
    end
    #--------------------------------------------------------------------------
    # ● 从Bitmap对象的原始数据生成PNG图像数据
    #--------------------------------------------------------------------------
    def make_bitmap_data_dant
      len = @bitmap_Fx.width * @bitmap_Fx.height * 4
      pBuf = Malloc.call(len)
      bitmap=@bitmap_Fx#.reverse
      addr=bitmap.address
      Memcpy_ii.call(pBuf,addr,len)
      Callsub.call(@pCode,pBuf,bitmap.width*bitmap.height,0,0)
      len2=len+bitmap.height
      len3=bitmap.width*4
      pBuf2 = Malloc.call(len2+512)
      pos=pBuf2
      pos2=pBuf+len-len3
      Memcpy_ip.call(pos,0.chr,1)
      pos+=1
      for i in 0...bitmap.height
        Memcpy_ii.call(pos,pos2,len3)
        pos+=len3
        pos2-=len3
        Memcpy_ip.call(pos,0.chr,1)
        pos+=1
      end
      buf="\0"*len2
      Memcpy_pi.call(buf,pBuf2,len2)
      Free.call(pBuf)
      Free.call(pBuf2)
#~       bitmap.dispose
      return buf
    end
    #--------------------------------------------------------------------------
    # ● PNG文件尾数据块(IEND)
    #--------------------------------------------------------------------------
    def make_iend
      return [0x00,0x00,0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82].pack("C*")
      #ie_size = [0].pack("N")
      #ie_sign = "IEND"
      #ie_crc = [Zlib.crc32(ie_sign)].pack("N")
      #return ie_size + ie_sign + ie_crc
    end
   
    def init
      @pCode=Malloc.call(512)
=begin
      qwe proc src,pixels,un,used
      mov eax,src
      xor ecx,ecx
      .while ecx < pixels
      mov edx,[eax] ;AARRGGBB|BB GG RR AA
      bswap edx ;BBGGRRAA|AA RR GG BB
      ror edx,8 ;AABBGGRR|RR GG BB AA
      mov [eax],edx
      inc ecx
      add eax,4
      .endw
      ret
      qwe endp
=end
      code = [0x55,0x8B,0xEC,0x8B,0x45,0x8,0x33,0xC9,0xEB,0xD,0x8B,0x10,0xF,0xCA,0xC1,0xCA,0x8,0x89,0x10,0x41,0x83,0xC0,0x4,0x3B,0x4D,0xC,0x72,0xEE,0xC9,0xC2,0x10,0x0].pack('C*')
      Memcpy_ip.call(@pCode,code,code.length)
      
    end
   
    def close
      Free.call(@pCode)
    end
   
  end #Bitmap2PNG
  
  def save_png(filename)
    File.open(filename,"wb"){|f|f.write(Bitmap2PNG.make_png(self))}
  end
  
end #Bitmap


Bitmap::Bitmap2PNG.init
END {Bitmap::Bitmap2PNG.close}
[/pre]
范例工程(VX)
savePNG.zip(250 KB, 下载次数: undefined, 售价: 4294967295 经验, 备用地址1, 备用地址2)

评分

参与人数 3星屑 +1632 收起 理由
taroxd + 240 果然龌龊~
fux2 + 1332 触手
iisnow + 60 LZ厉害,并且非常感谢

查看全部评分

宛若

梦石
0
星屑
1888
在线时间
529 小时
注册时间
2007-8-19
回帖
1466

极短24参与开拓者

发表于 2012-3-4 13:26:09 | 显示全部楼层
竟然用Dropbox……害得咱还要开VPN……
而且这奇葩的伪装……

点评

我这里用https://dl-web..............可以的 奇葩的天朝局域网  发表于 2012-3-4 13:48
[url=http://rpg.blue/thread-219730-1-1.html]http://unhero.sinaapp.com/wi.php[/url]
[color=Red]如你所见这是个死坑,没错这就是打我的脸用的[/color]
回复

使用道具 举报

梦石
0
星屑
513
在线时间
1479 小时
注册时间
2011-9-17
回帖
1266

开拓者贵宾

发表于 2012-3-4 13:29:20 | 显示全部楼层
本帖最后由 iisnow 于 2012-3-4 13:30 编辑

过来学习~~
顺便吐槽下,为什么附件下载不了;

然后LZ能不能推荐一下PNG相关的API的一些资料啊

点评

关于PNG的资料 http://www.w3.org/TR/PNG/ ms这里也有一些 http://www.libpng.org/pub/png/libpng.html  发表于 2012-3-4 13:44
加了两个地址  发表于 2012-3-4 13:41
我帖子中要有是不HX的空白,请Ctrl + A
回复

使用道具 举报

Fuzzy Ginkgo

梦石
0
星屑
61105
在线时间
1933 小时
注册时间
2010-6-26
回帖
1535

烫烫烫开拓者

发表于 2012-3-4 13:46:13 | 显示全部楼层
惊险触手 这奇葩的附件伪装= =b
下次用Dropbox建议你建立一个专门的文件夹来放这些东西……
不要图方便免得以后不能整理。
我的言论只代表我个人的观点,不代表雇主及/或任何第三方的立场。
Opinions expressed are solely my own and do not express the views or opinions of my employer and/or any third parties.
捐赠 | GitHub
回复

使用道具 举报

头像被屏蔽
梦石
0
星屑
653
在线时间
3774 小时
注册时间
2011-2-26
回帖
1577

开拓者

发表于 2012-3-6 21:56:32 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
签名被屏蔽
回复

使用道具 举报

梦石
0
星屑
60
在线时间
156 小时
注册时间
2011-12-13
回帖
127
 楼主| 发表于 2012-3-7 13:41:50 | 显示全部楼层
晴兰 发表于 2012-3-6 21:56
惊现触手
其实可以直接取code的地址 不需要RtlMoveMemory再复制一遍的 而且malloc用Win32API是有问题的  ...

直接执行String里的代码有时会出错,原因不明
malloc改成VirtualAlloc应该就没问题了

点评

???  发表于 2012-3-8 18:23
其实新人俺还有一个问题  发表于 2012-3-7 14:27
回复

使用道具 举报

梦石
0
星屑
50
在线时间
66 小时
注册时间
2013-9-4
回帖
91
发表于 2013-12-17 18:49:51 | 显示全部楼层
怎么个龌龊法?(纯属新手,问下怎么做到的)
本人以后只点评!不回复!更不发主题!
(每次发资源都被扣分,还扣那么多!)
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部