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

Project1

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

[已经解决] 【悬赏10V】双线性插值 求优化【更新2.1 @2011-11-28】

[复制链接]

Lv2.观梦者

(?????)

梦石
0
星屑
729
在线时间
1327 小时
注册时间
2011-7-18
帖子
3184

贵宾

跳转到指定楼层
1
发表于 2011-11-25 05:35:38 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式
本帖最后由 各种压力的猫君 于 2011-11-29 01:32 编辑

悬赏视情况可以随便追加,就这样。

好吧我还在搞双线性插值 lol
这次应该是真正的双线性插值了。




【更新记录】
 2011-11-28 2.1
 继续优化算法,提高效率(相同情况下对比2.0加快0.2秒),
 加权平均的边缘变成了另一种奇怪的样子 = = b 原因不明。
 2011-11-25 2.0
 大幅优化了算法,提高效率(对比初版(点我)同样是128*128放大3倍,加快1秒)

【测试工程】
  双线性插值缩放2.1.zip (282.07 KB, 下载次数: 36)

【脚本】
  1. #==============================================================================
  2. # ■ 双线性插值 2.1 by 各种压力的猫君
  3. #------------------------------------------------------------------------------
  4. #  双线性插值图像缩放算法
  5. #   仅供测试,当Bitmap尺寸较大时效率很差暂时不具实用性。
  6. #------------------------------------------------------------------------------
  7. #   使用方法:
  8. #   Bilinear.new(bitmap, x_rate, y_rate, type)
  9. #     bitmap :原Bitmap
  10. #     x_rate :横轴放大率
  11. #     y_rate :纵轴放大率
  12. #     type   :缩放参数(1:加权平均 2:算术平均)
  13. #
  14. #   缩放后的Bitmap会被输出到全局变量$new_bitmap。
  15. #   缩放结束后可以在全局变量$bilinear_time获取处理全程花费的时间(秒)
  16. #------------------------------------------------------------------------------
  17. #   更新记录:
  18. #   2.1 2011-11-28 优化效率
  19. #   2.0 2011-11-25 测试版(别问我1.0哪去了)
  20. #==============================================================================

  21. class Bilinear
  22.   #--------------------------------------------------------------------------
  23.   # ● 初始化对像
  24.   #--------------------------------------------------------------------------
  25.   def initialize(bitmap, x_rate, y_rate, type = 1)
  26.     # 获取原Bitmap及宽高信息
  27.     @old_bitmap = bitmap
  28.     @old_width  = @old_bitmap.width
  29.     @old_height = @old_bitmap.height
  30.     # 生成一个储存所有像素颜色的数组
  31.     @color_array = []
  32.     # 每行从左到右的顺序依次获取颜色并压入数组
  33.     for line in 1..@old_height
  34.       for row in 1..@old_width
  35.         color = @old_bitmap.get_pixel(row, line)
  36.         @color_array.push color
  37.       end
  38.     end
  39.     # 获取放大率
  40.     @x_rate = x_rate
  41.     @y_rate = y_rate
  42.     # 根据放大率计算新Bitmap尺寸
  43.     @new_width  = @x_rate * @old_width
  44.     @new_height = @y_rate * @old_height
  45.     # 生成Bitmap
  46.     @new_bitmap = Bitmap.new(@new_width, @new_height)
  47.     # 绘制Bitmap
  48.     draw(type)
  49.     # 返回Bitmap
  50.     $new_bitmap = @new_bitmap.clone
  51.     # 消除临时Bitmap
  52.     @new_bitmap.dispose
  53.   end
  54.   #--------------------------------------------------------------------------
  55.   # ● 绘制Bitmap
  56.   #--------------------------------------------------------------------------
  57.   def draw(type)
  58.     # 记录目前时间,用于统计算法用时
  59.     @time_begin = Time.now
  60.     # 一行一行绘制
  61.     for line in 1..@new_height
  62.       # 过程1:获取本行通用浮点y坐标
  63.       do_math_1(line)
  64.       for row in 1..@new_width
  65.         # 过程2:获取浮点x坐标
  66.         do_math_2(row)
  67.         # 过程3:获取颜色
  68.         do_math_3
  69.         # 过程4:计算颜色
  70.         do_math_4(type)
  71.         # 绘制颜色
  72.         draw_color(row, line)
  73.       end
  74.     end
  75.     # 计算算法用时
  76.     $bilinear_time = Time.now - @time_begin
  77.   end
  78.   #--------------------------------------------------------------------------
  79.   # ● 计算(过程1:获取浮点y坐标及y权)
  80.   #--------------------------------------------------------------------------
  81.   def do_math_1(y)
  82.     # 获取新坐标对应在原图上的浮点坐标
  83.     @y = 100 * y / @y_rate
  84.     # 计算y权
  85.     @ya = @y % 100
  86.     @yb = 100 - @ya
  87.     # 获取底数(floor)
  88.     @yf = @y /= 100
  89.   end
  90.   #--------------------------------------------------------------------------
  91.   # ● 计算(过程2:获取浮点x坐标及x权)
  92.   #--------------------------------------------------------------------------
  93.   def do_math_2(x)
  94.     # 获取新坐标对应在原图上的浮点坐标
  95.     @x = 100 * x / @x_rate
  96.     # 计算x权
  97.     @xa = @x % 100
  98.     @xb = 100 - @xa
  99.     # 获取底数(floor)
  100.     @xf = @x /= 100
  101.   end
  102.   #--------------------------------------------------------------------------
  103.   # ● 计算(过程3:获取颜色)
  104.   #--------------------------------------------------------------------------
  105.   def do_math_3
  106.     # 计算坐标颜色储存在数组中的序列
  107.     index11 = @xf + (@yf - 1) * @old_width - 1
  108.     if @ya == 0
  109.       index21 = index11
  110.     else
  111.       index21 = index11 + @old_width
  112.     end
  113.     if @xa == 0
  114.       index12 = index11
  115.       index22 = index21
  116.     else
  117.       index12 = index11 + 1
  118.       index22 = index21 + 1
  119.     end
  120.     # 从数组中获取颜色
  121.     @color11 = @color_array[index11]
  122.     @color21 = @color_array[index21]
  123.     @color12 = @color_array[index12]
  124.     @color22 = @color_array[index22]
  125.   end
  126.   #--------------------------------------------------------------------------
  127.   # ● 计算(过程4:计算颜色)
  128.   #--------------------------------------------------------------------------
  129.   def do_math_4(type)
  130.     # 分解颜色
  131.     @c11 = decompose_color(@color11)
  132.     @c21 = decompose_color(@color21)
  133.     @c12 = decompose_color(@color12)
  134.     @c22 = decompose_color(@color22)
  135.     if type == 1
  136.       # 加权
  137.       @c11 = weighted_average(@c11, @xa)
  138.       @c21 = weighted_average(@c21, @xa)
  139.       @c12 = weighted_average(@c12, @xb)
  140.       @c22 = weighted_average(@c22, @xb)
  141.       # 计算新颜色
  142.       @r = ((@c11[0] + @c12[0]) * @ya + (@c21[0] + @c22[0]) * @yb) / 10000
  143.       @g = ((@c11[1] + @c12[1]) * @ya + (@c21[1] + @c22[1]) * @yb) / 10000
  144.       @b = ((@c11[2] + @c12[2]) * @ya + (@c21[2] + @c22[2]) * @yb) / 10000
  145.       @a = ((@c11[3] + @c12[3]) * @ya + (@c21[3] + @c22[3]) * @yb) / 10000
  146.     elsif type == 2
  147.       # 计算新颜色
  148.       @r = (@c11[0] + @c12[0] + @c21[0] + @c22[0]) / 4
  149.       @g = (@c11[1] + @c12[1] + @c21[1] + @c22[1]) / 4
  150.       @b = (@c11[2] + @c12[2] + @c21[2] + @c22[2]) / 4
  151.       @a = (@c11[3] + @c12[3] + @c21[3] + @c22[3]) / 4
  152.     end
  153.   end
  154.   #--------------------------------------------------------------------------
  155.   # ○ 分解颜色
  156.   #--------------------------------------------------------------------------
  157.   def decompose_color(color)
  158.     r = color.red
  159.     g = color.green
  160.     b = color.blue
  161.     a = color.alpha
  162.     color_array = [r, g, b, a]
  163.     return color_array
  164.   end
  165.   #--------------------------------------------------------------------------
  166.   # ○ 加权运算
  167.   #--------------------------------------------------------------------------
  168.   def weighted_average(array, d)
  169.     new_array = []
  170.     array.each do |i|
  171.       new_array.push i * d
  172.     end
  173.     return new_array
  174.   end
  175.   #--------------------------------------------------------------------------
  176.   # ● 绘制颜色
  177.   #--------------------------------------------------------------------------
  178.   def draw_color(x, y)
  179.     color = Color.new(@r, @g, @b, @a)
  180.     @new_bitmap.set_pixel(x, y, color)
  181.   end
  182. end
复制代码
为什么不让我换行!!!
【历史版本】(以下链接均链接到我的6R空间日志)
 2.0版 大幅优化效率
 1.0版(某个脑残算法版本,刚发布就删除了,尸首已经找不到了)
 初版 最初的思路

【悬赏解决以下问题】
 ①效率再提高
 ②采用加权平均时图像边缘的锯齿
 ③调用方法能否改成类似@new_bitmap = Bilinear.new(@bitmap, 3, 3, 2) 这样

多多益善,就算效果不是非常好也有经验奖励,
VIP悬赏无上限追加{:nm_4:}(当然不能超过我财力范围 {:nm_7:} )

Lv1.梦旅人

梦石
0
星屑
50
在线时间
1281 小时
注册时间
2006-8-27
帖子
590
6
发表于 2011-11-28 22:23:21 | 只看该作者
本帖最后由 wbsy8241 于 2011-11-29 12:06 编辑

是你电脑 加权平均的3倍速 算数平均的1.8 倍速

画质好 并可缩小 可用小数
(你的用小数会报错,少用数组可提高速度,区域变量和实例变量(带不带@)速度一样)
RGSS的速度就这样了
  1. class Bilinear < Bitmap  #bitmap爸爸的意思
  2.   def initialize(bitmap, x_rate, y_rate)
  3.     old_width  = bitmap.width
  4.     old_height = bitmap.height
  5.     width  = (old_width * x_rate).round
  6.     height = (old_height * y_rate).round
  7.     new_width  = width + x_rate.ceil  #计算时多放大1些
  8.     new_height = height + y_rate.ceil #使四边上的颜色最接近原图四边
  9.     array = []
  10.     for y in 0...old_height
  11.       for x in 0...old_width
  12.         array.push(bitmap.get_pixel(x, y))
  13.       end
  14.     end
  15.     bitmap.dispose
  16.     color = Color.new(0, 0, 0, 0) #新生成比.set多用 6% 秒
  17.     super(width, height)          #生成Bitmap对象
  18.     for y in 0...height
  19.       t = y * old_height ; ty = t / new_height #省计算临时变量
  20.       ty1 = ty * old_width ; ty2 = ty1 + old_width #取得数组中y位
  21.       y2 = t % new_height * 100 / new_height #计算百分比位置
  22.       y1 = 100-y2
  23.       for x in 0...width
  24.         t = x * old_width; tx = t / new_width #省计算临时变量; 取得数组中x位
  25.         x2 = t % new_width * 100 / new_width #计算百分比位置
  26.         x1 = 100-x2
  27.         # 取得四点百分比; 取得四点颜色
  28.         b11 = x1*y1; c11 = array[ty1 + tx]
  29.         b21 = x2*y1; c21 = array[ty1 + tx+1]
  30.         b12 = x1*y2; c12 = array[ty2 + tx]
  31.         b22 = x2*y2; c22 = array[ty2 + tx+1]
  32.         # 根据四点百分比来调整颜色
  33.         red = (c11.red*b11   + c21.red*b21   + c12.red*b12   + c22.red*b22)   / 10000
  34.         green = (c11.green*b11 + c21.green*b21 + c12.green*b12 + c22.green*b22) / 10000
  35.         blue = (c11.blue*b11  + c21.blue*b21  + c12.blue*b12  + c22.blue*b22)  / 10000
  36.         alpha = (c11.alpha*b11 + c21.alpha*b21 + c12.alpha*b12 + c22.alpha*b22) / 10000
  37.         set_pixel(x, y, color.set(red, green, blue, alpha))
  38.       end
  39.     end
  40.   end
  41. end

  42. time = Time.new
  43. @a = Sprite.new
  44. @a.bitmap = Bilinear.new(Bitmap.new("TEST.png"),0.6,0.6)
  45. p Time.new - time
复制代码


wbsy8241于2011-11-29 12:09补充以下内容:
第20行 改了下变量
长宽相同的情况没测试出来问题

点评

OK懂了,范围是类似 0..(width - 1) 这样 -W- 非常感谢  发表于 2011-11-29 01:20
随便什么(好象)都是从0开始  发表于 2011-11-28 22:50
有个问题,为什么是从0开始的?bitmap的坐标第一个像素不应该是(1,1)么?还是说我理解错误?  发表于 2011-11-28 22:44
回复

使用道具 举报

Lv2.观梦者

(?????)

梦石
0
星屑
729
在线时间
1327 小时
注册时间
2011-7-18
帖子
3184

贵宾

5
 楼主| 发表于 2011-11-27 23:39:53 | 只看该作者
追加1V & 顶帖

又想到种优化方法……马上试试去

点评

benvisa的photozoomer用的算法几乎达到无损放大,不知道那算法效率如何  发表于 2011-12-31 08:13
回复

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

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

开拓者贵宾

4
发表于 2011-11-26 12:24:22 | 只看该作者
各种压力的猫君 发表于 2011-11-26 04:16
求具体思路 = = b
直接把Bitmap指定为父类用return @new_bitmap无效啊

父类是bitmap的话子类也算bitmap了,return什么啊,直接用bitmap的描绘方法。

点评

求改法 = = b  发表于 2011-11-27 02:51
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复

使用道具 举报

Lv2.观梦者

(?????)

梦石
0
星屑
729
在线时间
1327 小时
注册时间
2011-7-18
帖子
3184

贵宾

3
 楼主| 发表于 2011-11-26 04:16:24 | 只看该作者
fux2 发表于 2011-11-25 09:20
第三个问题把这玩意加个bitmap爸爸然后在自己身上画应该可以,前两个待我想想。 ...

求具体思路 = = b
直接把Bitmap指定为父类用return @new_bitmap无效啊
回复

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

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

开拓者贵宾

2
发表于 2011-11-25 09:20:59 | 只看该作者
第三个问题把这玩意加个bitmap爸爸然后在自己身上画应该可以,前两个待我想想。

评分

参与人数 1星屑 +24 收起 理由
各种压力的猫君 + 24 感谢参与 发糖

查看全部评分

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

使用道具 举报

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

本版积分规则

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

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

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

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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