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

Project1

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

[原创发布] Bitmap模糊绘制blur_blt

[复制链接]

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

跳转到指定楼层
1
发表于 2022-3-12 20:27:30 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 guoxiaomi 于 2022-3-13 00:23 编辑

不知道有没有人写过?相当于把一张bitmap,模糊的绘制到目标bitmap上,虽然用了高斯分布的公式,但不是高斯模糊,只是糊了点

下图是sigma=2.0时的模糊,也可以下载范例尝试: 20220312-blur.zip (201.29 KB, 下载次数: 24) ,按左右键调整模糊程度,确认键退出


RUBY 代码复制
  1. class Bitmap
  2.   def blur_blt(src_bitmap, sigma = 1.0)
  3.     blt(0, 0, src_bitmap, src_bitmap.rect)
  4.     return if sigma < 0.01
  5.     d = 4
  6.     sum = 0.0
  7.     for dx in -d..d
  8.       for dy in -d..d
  9.         sum += Math.exp(-0.5 * (dx * dx + dy * dy) / (sigma * sigma))
  10.       end
  11.     end
  12.  
  13.     for dx in -d..d
  14.       for dy in -d..d
  15.         alpha = Math.exp(-0.5 * (dx * dx + dy * dy) / (sigma * sigma)) * 255.0 / sum
  16.         next if alpha < 1
  17.         blt(dx, dy, src_bitmap, src_bitmap.rect, alpha)
  18.       end
  19.     end
  20.   end
  21. end

下面是测试代码:
RUBY 代码复制
  1. b = RPG::Cache.battleback("001-grassland01")
  2. s = Sprite.new
  3. s.bitmap = b.clone
  4.  
  5. hint = Sprite.new
  6. hint.y = 440
  7. hint.bitmap = Bitmap.new(640, 32)
  8.  
  9. refresh = Proc.new { |sigma|
  10.   s.bitmap.clear
  11.   s.bitmap.blur_blt(b, sigma)
  12.   hint.bitmap.clear
  13.   hint.bitmap.draw_text(0, 0, 640, 32, "sigma = %.2f" % sigma, 1)
  14. }
  15.  
  16. sigma = 1.0
  17. refresh.call(sigma)
  18.  
  19. loop do
  20.   Graphics.update
  21.   Input.update
  22.   exit if Input.trigger?(Input::C)
  23.  
  24.   if Input.press?(Input::RIGHT)
  25.     sigma += 0.05
  26.     refresh.call(sigma)
  27.   elsif Input.press?(Input::LEFT) && sigma > 0
  28.     sigma -= 0.05
  29.     refresh.call(sigma)
  30.   end
  31. end
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *

Lv4.逐梦者

梦石
0
星屑
6483
在线时间
119 小时
注册时间
2020-1-8
帖子
234
2
发表于 2022-3-12 23:25:52 | 只看该作者
我打开是  No such file to load -- main.rb……

RUBY 代码复制
  1. $: << "."
  2. load "main.rb"


以前好奇高斯模糊,见过类似的计算公式来计算kernel,但我基本没看懂……
效果和效率都不错,就是和PS的高斯模糊看起来有点不一样……

点评

嗯,得对照测试一下高斯模糊的效果,我改一下标题2333  发表于 2022-3-13 00:00
我用就没问题呀,大不了就把上面两段代码复制进去……  发表于 2022-3-12 23:59
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

3
 楼主| 发表于 2022-3-13 00:20:24 | 只看该作者
本帖最后由 guoxiaomi 于 2022-3-13 01:48 编辑
RPGzh500223 发表于 2022-3-12 23:25
我打开是  No such file to load -- main.rb……

$:


模糊就是将一个点像素变为某个分布。比如说,把这个点的颜色分配到周围几个点上,本来位置占0.5,上下左右各0.125,只要加起来是1就行。符合高斯分布的分配方式就是高斯模糊。操作起来就更简单了,直接将图片平移,然后按照分配比例计算透明度,叠加起来即可。我这段代码就是x: -4~4, y: -4~4总共81张图叠出来的。

我一开始按照高斯分布的公式写的,叠起来却非常的暗,所以我在叠之前先把原图绘制了一遍。可能RMXP的Bitmap叠加不是直接用的加法,或者有数值精度的问题,得再研究研究。

===
我怀疑我的权重算错了,真实权重应该是下面这个(论坛发不了公式):

计算结果

点评

↓↓↓↓高斯函数的积分要烂熟于心~  发表于 2022-3-13 14:43
blt我直接实现的加法,没有用混合模式,公式是d+s*alpha。不过确实如黄鸡所说我可以看看MV  发表于 2022-3-13 11:52
虽说有81次循环,但是实际有效(alpha>1)的21次……  发表于 2022-3-13 11:11
图像卷积我还是知道的,我不明白的是高斯的数学公式(超我范围太多)。Bitmap#blt本来就不是颜色叠加,颜色混合更合适,你自己写的那个RMXP不是也有吗  发表于 2022-3-13 11:02
看来你高数学的相当好啊  发表于 2022-3-13 08:19

评分

参与人数 1+1 收起 理由
runapp + 1 我很赞同

查看全部评分

熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 1 反对 0

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
42387
在线时间
7601 小时
注册时间
2009-7-6
帖子
13506

开拓者贵宾

4
发表于 2022-3-13 09:11:24 | 只看该作者
遇事不决抄MV……

点评

想问下精灵缩放可以二次立方缩放吗?  发表于 2022-3-13 18:38

评分

参与人数 1+1 收起 理由
guoxiaomi + 1 我很赞同

查看全部评分

RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
6483
在线时间
119 小时
注册时间
2020-1-8
帖子
234
5
发表于 2022-3-13 11:08:57 | 只看该作者
本帖最后由 RPGzh500223 于 2022-3-13 11:32 编辑
  1. class Bitmap
  2.   def blur_blt2(src_bitmap, sigma = 1.0)
  3.     self.blt(0, 0, src_bitmap, src_bitmap.rect)
  4.     return if sigma < 0.01
  5.     d, sum, sigma_ratio = 4, 0.0, -0.5 / (sigma * sigma)
  6.    
  7.     1.upto(d) do |dx|
  8.       mul = dx * dx
  9.       sum += Math.exp(mul * sigma_ratio) * 4
  10.       1.upto(d) do |dy|
  11.         sum += Math.exp((mul + dy * dy) * sigma_ratio) * 4
  12.       end
  13.     end
  14.     sum += 1
  15.         
  16.     var = 255.0 / sum
  17.     d_max = (Math.log(1 / var) / sigma_ratio).ceil
  18.    
  19.     1.upto(d) do |dx|
  20.       1.upto(d) do |dy|
  21.         distance = dx * dx + dy * dy
  22.         next if distance > d_max
  23.         alpha = Math.exp(distance * sigma_ratio) * var
  24.         self.blt( dx,  dy, src_bitmap, src_bitmap.rect, alpha)
  25.         self.blt( dx, -dy, src_bitmap, src_bitmap.rect, alpha)
  26.         self.blt(-dx,  dy, src_bitmap, src_bitmap.rect, alpha)
  27.         self.blt(-dx, -dy, src_bitmap, src_bitmap.rect, alpha)
  28.       end
  29.     end
  30.   end
  31. end
复制代码


分享的关于写脚本的小心得(无关于如何计算,其实如何算才是核心……)
  for...in...在ruby里好像是效率最低的循环
  多重赋值比多次赋值快
  能合并的计算常量就先合并
  尽可能减少循环次数,例如对称一次就基本少一半循环
  其实Math里不少计算是很费效率的,尽可能避免

------------------------------------------------------------------------------------------
模糊效果,我一般就用SSE的pavgb写的均值模糊,高斯模糊的话就调GDI+实现

点评

for..in...不是效率最低的,这个我测过,其实取决于in后面你怎么写(但怎么写它也不会是效率最低的循环方式),其他的没问题  发表于 2022-3-14 07:02
想问下精灵缩放可以二次立方缩放吗?  发表于 2022-3-13 13:05
那这里改用均值模糊的公式是不是更快点  发表于 2022-3-13 11:54
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
36427
在线时间
10796 小时
注册时间
2009-3-15
帖子
4814
6
发表于 2022-3-13 11:50:06 | 只看该作者
想问下精灵缩放可以二次立方缩放吗?

点评

这个你得问能重写rm的人了,比如楼上的楼上 个人理解,精灵是把self.bitmap作为源数据在渲染的时候进行缩放旋转什么 我都不知道现有的缩放是什么...  发表于 2022-3-13 13:34
估计在rm的框架下有点难,问问楼上?  发表于 2022-3-13 12:04
缩放我不清楚,主要是我突然意识到了模糊就是平移+叠加,所以水一贴  发表于 2022-3-13 11:57
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
39016
在线时间
5717 小时
注册时间
2006-11-10
帖子
6619
7
发表于 2022-3-13 16:23:18 | 只看该作者
R叔移植的半生烛光DLL就有模糊计算,  不过,不拆DLL看不到怎么写的

话说, 扭曲应该也可以这样做吧?  把扩散的计算换成正弦曲线重叠?
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

8
 楼主| 发表于 2022-3-13 18:20:27 | 只看该作者
本帖最后由 guoxiaomi 于 2022-3-14 00:26 编辑
灯笼菜刀王 发表于 2022-3-13 16:23
R叔移植的半生烛光DLL就有模糊计算,  不过,不拆DLL看不到怎么写的

话说, 扭曲应该也可以这样做吧?  把扩散 ...


我觉得扭曲可能只能一行行的处理了,但是也许有算法只需要处理一个周期,因为每隔固定的周期,画面平移的模式就相同了。

===
想了下,可以把原来的图片拆成N份,每份做不同的平移,这样就能做出动态的扭曲效果了,这样也只需要一次逐行复制,并且在播放动画的时候是没有绘制的,纯粹操作sprite

点评

和我以前想过的方法一样, 但是, 我无法搞定边缘羽化和合成问题, sprite的加法不行,所以,应该还是需要绘制  发表于 2022-3-17 10:43
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-21 17:19

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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