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

Project1

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

[通用发布] Bitmap 类储存为 .bmp 档案(高速= =)

[复制链接]

Lv3.寻梦者

弓箭手?剑兰

梦石
0
星屑
4864
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
跳转到指定楼层
1
发表于 2011-5-28 17:43:55 | 只看该作者 回帖奖励 |正序浏览 |阅读模式

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

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

x
本帖最后由 一箭烂YiJL 于 2011-5-28 17:45 编辑

0.序
这是将Bitmap 类(挺)高速的保存为bmp档案。因为之前想用柳之一的《Bitmap高速Marshal》和保存png结合,
但其实是上下倒置,而且png格式每行都要插进"0",获取每点的颜色值比起用数组"搞定"上下倒置和插"0"要快!
今天我研究了一下bmp档案,bmp格式是上下倒置,而且不用插"0",所以将拿到的数据直接写入bmp的颜色值数据流中。
然而这样比png的每点扫要快得多,VX的屏幕载图储存bmp,fps不会降!

1.脚本
脚本如下(XP/VX),柳之一的《Bitmap高速Marshal》已经不是那个样了(而且不能Marshal= =):

  1. #==============================================================================
  2. # ■ BmpWriter             by 一箭烂YiJL (获取颜色值部分 by 柳之一)
  3. #------------------------------------------------------------------------------
  4. #  使用手册:
  5. #
  6. #     BmpWriter.write(bitmap, [name[, path]])
  7. #       bitmap    : 位图
  8. #       name      : 保存文件名
  9. #       path      : 保存路径
  10. #
  11. #     自动创建路径!
  12. #==============================================================================

  13. module BmpWriter
  14.   #--------------------------------------------------------------------------
  15.   # ● 传送到内存的API函数
  16.   #--------------------------------------------------------------------------
  17.   RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  18.   #--------------------------------------------------------------------------
  19.   # ● 制作bmp档案
  20.   #--------------------------------------------------------------------------
  21.   def self.write(bitmap, name = "Bitmap.bmp", path = "Pictures/")
  22.     ## 先要工作
  23.     Dir.mkdir(path) unless FileTest.directory?(path)
  24.     length = bitmap.width * bitmap.height
  25.     file = File.open(path + name, "wb")
  26.    
  27.     ## BitmapFileHeader
  28.     size = 54 + length * 4
  29.     chunk = "BM" + [size, 0, 54].pack("L*")
  30.     file.write(chunk)
  31.    
  32.     ## BitmapInfoHeader
  33.     chunk = [40, bitmap.width, bitmap.height, 1, 32, 0, 0, 0xEC4, 0xEC4, 256, 0].pack("L3S2L*")
  34.     file.write(chunk)
  35.    
  36.     ## Byte
  37.     data = "rgba" * bitmap.width * bitmap.height
  38.     RtlMoveMemory_pi.call(data, bitmap.address, data.length)
  39.     chunk = data
  40.     file.write(chunk)
  41.    
  42.     file.close
  43.   end
  44. end

  45. class Bitmap
  46.   #--------------------------------------------------------------------------
  47.   # ● 传送到内存的API函数
  48.   #--------------------------------------------------------------------------
  49.   RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  50.   #--------------------------------------------------------------------------
  51.   # ● Bitmap地址
  52.   #--------------------------------------------------------------------------
  53. # [[[bitmap.object_id * 2 + 16] + 8] + 16] == 数据的开头
  54.   def address
  55.     buffer, ad = "rgba", object_id * 2 + 16
  56.     RtlMoveMemory_pi.call(buffer, ad, 4)
  57.     ad = buffer.unpack("L")[0] + 8
  58.     RtlMoveMemory_pi.call(buffer, ad, 4)
  59.     ad = buffer.unpack("L")[0] + 16
  60.     RtlMoveMemory_pi.call(buffer, ad, 4)
  61.     return buffer.unpack("L")[0]
  62.   end
  63. end
复制代码

2.范例
只有VX的: BmpWriter(VX).zip (280.85 KB, 下载次数: 248)
在任何场景按F8就可以载图,保存在 Pictures/Bitmap.bmp
没有XP的是因为XP还要找XP的Graphics.snap_to_bitmap,如果真的很想要的话就回帖伸手吧~

评分

参与人数 1星屑 +1000 收起 理由
夕阳武士 + 1000 前途无量啊你~

查看全部评分

Lv1.梦旅人

梦石
0
星屑
51
在线时间
6 小时
注册时间
2010-10-24
帖子
5
21
发表于 2011-6-19 14:35:07 | 只看该作者
本人还是得纠个错,这样得到的事实上是BGRA四个通道 ,而并非RGBA(真不知道Bitmap中怎么什么东西都是倒过来的)……
本人现在正在研究PNG格式,想将体积大的BMP转为小巧又相对简单的PNG格式(不像JPG那么烦),可惜通过将每一个BGRA数组都转化为RGBA的时间实在太长,不知有否高人相助!
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
20
发表于 2011-6-5 00:18:01 | 只看该作者
一箭烂YiJL 发表于  
果然是我误会了 orz ,但是这两个域为什么叫压缩方式呢?

JPG 和 PNG 都是压缩格式,在这个域指定 JPG 或者 PNG 就告诉了打印机,接下来的数据不是 BMP,而是 JPG 或 PNG。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv3.寻梦者

弓箭手?剑兰

梦石
0
星屑
4864
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
19
 楼主| 发表于 2011-6-4 15:17:02 | 只看该作者
苏小脉 发表于 2011-6-3 10:52
这两个域是用在打印机硬件加速时的。

http://msdn.microsoft.com/en-us/library/dd145023(VS.85).aspx

果然是我误会了 orz ,但是这两个域为什么叫压缩方式呢?
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
18
发表于 2011-6-3 10:52:58 | 只看该作者
一箭烂YiJL 发表于 2011-6-2 21:40
应该是我误会了吧~
MSDN 指出 BitmapInfoHeader 的第六个域(压缩方式)可以为 BI_PNG ,描述的译文:

这两个域是用在打印机硬件加速时的。

http://msdn.microsoft.com/en-us/library/dd145023(VS.85).aspx

可以把 PNG 或 JPEG 和头一起直接传给硬件支持 JPEG 和 PNG 的打印机,硬件渲染。

These compression values are only valid for SetDIBitsToDevice and StretchDIBits when the hdc parameter specifies a printer device.

翻译成汉文:
这些压缩值仅对指定了 hDC 参数为打印机设备的 SetDIBitsToDevice 和 StretchDIBits 有效。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv3.寻梦者

弓箭手?剑兰

梦石
0
星屑
4864
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
17
 楼主| 发表于 2011-6-2 21:40:33 | 只看该作者
苏小脉 发表于 2011-6-1 08:16
微软哪里说的?我查阅的材料都只提到了 RLE,霍夫曼都仅仅是存在于 OS/2 的 BMP 标准中。 ...

应该是我误会了吧~
MSDN 指出 BitmapInfoHeader 的第六个域(压缩方式)可以为 BI_PNG ,描述的译文:
表示这是一幅 PNG 图像。

于是我就用了 PNG 的压缩方式,可能是我误会其中的意思吧~
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
16
发表于 2011-6-1 08:16:03 | 只看该作者
一箭烂YiJL 发表于  
于是我想说...算了...其实我那句也应该是错的...

微软哪里说的?我查阅的材料都只提到了 RLE,霍夫曼都仅仅是存在于 OS/2 的 BMP 标准中。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv3.寻梦者

弓箭手?剑兰

梦石
0
星屑
4864
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
15
 楼主| 发表于 2011-5-31 20:14:32 | 只看该作者
苏小脉 发表于 2011-5-31 20:00
那这是什么意思呢?
那这是什么意思呢?

于是我想说...算了...其实我那句也应该是错的...

PNG 是另一种格式,标准自然不同。

微软那里说 BMP 可以用 PNG 的压缩法,PNG 的压缩法就是 DEFLATE ( / Gzip)....
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
14
发表于 2011-5-31 20:00:25 | 只看该作者
一箭烂YiJL 发表于  
我有语法问题,应该是Bitmap 的那些结构体用指针指来指去。
可能的其中一个原因是 Bitmap#get_pixel、set_pixel、blur......
就可以引用位图的("同一个")颜色值数据作修改、读取......

那这是什么意思呢?

我用的是 Zlib 的 DEFLATE (LZ77 + 霍夫曼) 算法,这样能够在 png 里解读。(研究 PNG 的时候发现 Zlib 还有 CRC 校验的算法)

PNG 是另一种格式,标准自然不同。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv3.寻梦者

弓箭手?剑兰

梦石
0
星屑
4864
在线时间
833 小时
注册时间
2010-11-17
帖子
1140
13
 楼主| 发表于 2011-5-31 16:51:18 | 只看该作者
苏小脉 发表于 2011-5-31 08:34
什么 Bitmap 指针?
什么 Bitmap 指针?

我有语法问题,应该是Bitmap 的那些结构体用指针指来指去。

又不是想用什么方法压缩就用什么方法压缩

我用的是 Zlib 的 DEFLATE (LZ77 + 霍夫曼) 算法,这样能够在 png 里解读。(研究 PNG 的时候发现 Zlib 还有 CRC 校验的算法)
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-5-11 20:47

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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