Project1

标题: 保存Bitmap为PNG文件(快速+无DLL) [打印本页]

作者: dant    时间: 2012-3-4 13:06
标题: 保存Bitmap为PNG文件(快速+无DLL)
本帖最后由 dant 于 2012-3-4 13:40 编辑

虽然没有用DLL,但是BGRA->RGBA的处理还是用了一种很龌龊的方法
RUBY 代码复制
  1. #encoding:utf-8
  2. #==============================================================================
  3. # ■ Bitmap
  4. #------------------------------------------------------------------------------
  5. #  位图的类。所谓位图即表示图像其本身。
  6. #==============================================================================
  7.  
  8. class Bitmap
  9.   #--------------------------------------------------------------------------
  10.   # ● 传送到内存的API函数
  11.   #--------------------------------------------------------------------------
  12.   RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  13.   #--------------------------------------------------------------------------
  14.   # ● Bitmap地址
  15.   #--------------------------------------------------------------------------
  16.   # [[[bitmap.object_id * 2 + 16] + 8] + 16] == 数据的开头
  17.   def address
  18.     buffer, ad = "rgba", object_id * 2 + 16
  19.     RtlMoveMemory_pi.call(buffer, ad, 4)
  20.     ad = buffer.unpack("L")[0] + 8
  21.     RtlMoveMemory_pi.call(buffer, ad, 4)
  22.     ad = buffer.unpack("L")[0] + 16
  23.     RtlMoveMemory_pi.call(buffer, ad, 4)
  24.     return buffer.unpack("L")[0]
  25.   end
  26.  
  27.   module Bitmap2PNG
  28.     module_function
  29.     Malloc = Win32API.new('msvcrt.dll','malloc','i','i')
  30.     Memcpy_pi = Win32API.new('kernel32.dll','RtlMoveMemory','pii','v')
  31.     Memcpy_ii = Win32API.new('kernel32.dll','RtlMoveMemory','iii','v')
  32.     Memcpy_ip = Win32API.new('kernel32.dll','RtlMoveMemory','ipi','v')
  33.     Free = Win32API.new('msvcrt.dll','free','i','v')
  34.     Callsub = Win32API.new('user32.dll','CallWindowProcW','iiiii','i')
  35.     #--------------------------------------------------------------------------
  36.     # ● 主处理
  37.     #--------------------------------------------------------------------------
  38.     def make_png(bitmap_Fx)
  39.       @bitmap_Fx = bitmap_Fx
  40.       return make_header + make_ihdr + make_idat + make_iend
  41.     end
  42.     #--------------------------------------------------------------------------
  43.     # ● PNG文件头数据块
  44.     #--------------------------------------------------------------------------
  45.     def make_header
  46.       return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
  47.     end
  48.     #--------------------------------------------------------------------------
  49.     # ● PNG文件情报头数据块(IHDR)
  50.     #--------------------------------------------------------------------------
  51.     def make_ihdr
  52.       ih_size = [13].pack("N")
  53.       ih_sign = "IHDR"
  54.       ih_width = [@bitmap_Fx.width].pack("N")
  55.       ih_height = [@bitmap_Fx.height].pack("N")
  56.       ih_bit_depth = [8].pack("C")
  57.       ih_color_type = [6].pack("C")
  58.       ih_compression_method = [0].pack("C")
  59.       ih_filter_method = [0].pack("C")
  60.       ih_interlace_method = [0].pack("C")
  61.       string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
  62.       ih_compression_method + ih_filter_method + ih_interlace_method
  63.       ih_crc = [Zlib.crc32(string)].pack("N")
  64.       return ih_size + string + ih_crc
  65.     end
  66.     #--------------------------------------------------------------------------
  67.     # ● 生成图像数据(IDAT)
  68.     #--------------------------------------------------------------------------
  69.     def make_idat
  70.       header = "IDAT"
  71.       data = make_bitmap_data_dant
  72.       data = Zlib::Deflate.deflate(data)
  73.       crc = [Zlib.crc32(header + data)].pack("N")
  74.       size = [data.length].pack("N")
  75.       return size + header + data + crc
  76.     end
  77.     #--------------------------------------------------------------------------
  78.     # ● 从Bitmap对象的原始数据生成PNG图像数据
  79.     #--------------------------------------------------------------------------
  80.     def make_bitmap_data_dant
  81.       len = @bitmap_Fx.width * @bitmap_Fx.height * 4
  82.       pBuf = Malloc.call(len)
  83.       bitmap=@bitmap_Fx#.reverse
  84.       addr=bitmap.address
  85.       Memcpy_ii.call(pBuf,addr,len)
  86.       Callsub.call(@pCode,pBuf,bitmap.width*bitmap.height,0,0)
  87.       len2=len+bitmap.height
  88.       len3=bitmap.width*4
  89.       pBuf2 = Malloc.call(len2+512)
  90.       pos=pBuf2
  91.       pos2=pBuf+len-len3
  92.       Memcpy_ip.call(pos,0.chr,1)
  93.       pos+=1
  94.       for i in 0...bitmap.height
  95.         Memcpy_ii.call(pos,pos2,len3)
  96.         pos+=len3
  97.         pos2-=len3
  98.         Memcpy_ip.call(pos,0.chr,1)
  99.         pos+=1
  100.       end
  101.       buf="\0"*len2
  102.       Memcpy_pi.call(buf,pBuf2,len2)
  103.       Free.call(pBuf)
  104.       Free.call(pBuf2)
  105. #~       bitmap.dispose
  106.       return buf
  107.     end
  108.     #--------------------------------------------------------------------------
  109.     # ● PNG文件尾数据块(IEND)
  110.     #--------------------------------------------------------------------------
  111.     def make_iend
  112.       return [0x00,0x00,0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82].pack("C*")
  113.       #ie_size = [0].pack("N")
  114.       #ie_sign = "IEND"
  115.       #ie_crc = [Zlib.crc32(ie_sign)].pack("N")
  116.       #return ie_size + ie_sign + ie_crc
  117.     end
  118.  
  119.     def init
  120.       @pCode=Malloc.call(512)
  121. =begin
  122.       qwe proc src,pixels,un,used
  123.       mov eax,src
  124.       xor ecx,ecx
  125.       .while ecx < pixels
  126.       mov edx,[eax] ;AARRGGBB|BB GG RR AA
  127.       bswap edx ;BBGGRRAA|AA RR GG BB
  128.       ror edx,8 ;AABBGGRR|RR GG BB AA
  129.       mov [eax],edx
  130.       inc ecx
  131.       add eax,4
  132.       .endw
  133.       ret
  134.       qwe endp
  135. =end
  136.       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*')
  137.       Memcpy_ip.call(@pCode,code,code.length)
  138.  
  139.     end
  140.  
  141.     def close
  142.       Free.call(@pCode)
  143.     end
  144.  
  145.   end #Bitmap2PNG
  146.  
  147.   def save_png(filename)
  148.     File.open(filename,"wb"){|f|f.write(Bitmap2PNG.make_png(self))}
  149.   end
  150.  
  151. end #Bitmap
  152.  
  153.  
  154. Bitmap::Bitmap2PNG.init
  155. END {Bitmap::Bitmap2PNG.close}

范例工程(VX)
savePNG.zip(250 KB, 下载次数: undefined, 售价: 4294967295 经验, 备用地址1, 备用地址2)


作者: 逸豫    时间: 2012-3-4 13:26
竟然用Dropbox……害得咱还要开VPN……
而且这奇葩的伪装……
作者: iisnow    时间: 2012-3-4 13:29
本帖最后由 iisnow 于 2012-3-4 13:30 编辑

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

然后LZ能不能推荐一下PNG相关的API的一些资料啊
作者: orzfly    时间: 2012-3-4 13:46
惊险触手 这奇葩的附件伪装= =b
下次用Dropbox建议你建立一个专门的文件夹来放这些东西……
不要图方便免得以后不能整理。

作者: 晴兰    时间: 2012-3-6 21:56
提示: 作者被禁止或删除 内容自动屏蔽
作者: dant    时间: 2012-3-7 13:41
晴兰 发表于 2012-3-6 21:56
惊现触手
其实可以直接取code的地址 不需要RtlMoveMemory再复制一遍的 而且malloc用Win32API是有问题的  ...

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

作者: 雷欧亦炫    时间: 2013-12-17 18:49
怎么个龌龊法?(纯属新手,问下怎么做到的)




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1