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

Project1

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

[通用发布] Bilinear_Zoom 1.0 双线性插值缩放

[复制链接]

Lv2.观梦者

(?????)

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

贵宾

跳转到指定楼层
1
发表于 2011-12-31 15:23:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 各种压力的猫君 于 2012-2-1 20:15 编辑

高效率的DLL请见板凳,配合使用的脚本请见地面(6R你就不能老老实实给我用楼层号么233)


本脚本意在拓展思路,效率较差基本不具实用性。

(原图分辨率使用PS降低至1200*900,测试缩放倍数横纵均为0.3)

0 pass:RM默认算法(最邻近插值)

1 pass:双线性插值

2 pass:重复两次双线性插值

4 pass:重复四次双线性插值

下面是脚本:
  1. #==============================================================================
  2. # ■ Bilinear_Zoom 1.0
  3. #------------------------------------------------------------------------------
  4. #  双线性插值图像缩放算法
  5. #     by:各种压力的猫君  鸣谢:wbsy8241
  6. #------------------------------------------------------------------------------
  7. #   使用方法:
  8. #     Bilinear_Zoom.new(bitmap, x_rate, y_rate, pass, type)
  9. #       - bitmap   待缩放Bitmap
  10. #       - x_rate   横轴放大率(支持小数)
  11. #       - y_rate   纵轴放大率(支持小数)
  12. #       - pass = 0 采用RM默认算法(测试用)
  13. #              = 1 处理1次(默认)
  14. #              = 2 处理2次(质量提升,用时翻倍)
  15. #              = 4 处理4次(质量再提升,用时再翻倍)
  16. #       - type = 1 计算Red、Green、Blue、Alpha(默认,有透明度)
  17. #              = 0 计算Red、Green、Blue,Alpha = 255(速度较快,无透明度)
  18. #------------------------------------------------------------------------------
  19. #   脚本说明:
  20. #     本脚本意在拓展思路,效率较差基本不具实用性。
  21. #     所需时间和缩放后图片大小成正比,在RMXP上使用时可能存在“10s备份”问题。
  22. #     全局变量 $bilinear_time 记录处理用时 $bilinear_pass 记录所用pass。
  23. #------------------------------------------------------------------------------
  24. #   更新记录:
  25. #     1.0 2011-12-31 初版
  26. #==============================================================================

  27. class Bilinear_Zoom < Bitmap
  28.   #--------------------------------------------------------------------------
  29.   # ● 初始化对像
  30.   #--------------------------------------------------------------------------
  31.   def initialize(bitmap, x_rate, y_rate, pass = 1, type = 1)
  32.     # 记录目前时间,用于统计算法用时
  33.     @time_begin = Time.now
  34.     # 记录全局变量(测试用)
  35.     $bilinear_pass = pass
  36.     # 读入参数
  37.     @pass = pass
  38.     @type = type
  39.     @bitmap = bitmap
  40.     # 若pass0采用RM默认算法
  41.     if @pass == 0
  42.       # 获取放大率
  43.       @x_rate = x_rate
  44.       @y_rate = y_rate
  45.       # 获取原Bitmap及宽高信息
  46.       @old_width  = @bitmap.width
  47.       @old_height = @bitmap.height
  48.       # 根据放大率计算新Bitmap尺寸
  49.       @new_width  = (@old_width  * @x_rate).ceil
  50.       @new_height = (@old_height * @y_rate).ceil
  51.       # 生成Bitmap
  52.       super(@new_width, @new_height)
  53.       # 缩放
  54.       stretch_blt(self.rect, @bitmap, @bitmap.rect)
  55.     else # 双线性插值
  56.       case @pass
  57.       when 1
  58.         # 获取放大率
  59.         @x_rate = x_rate
  60.         @y_rate = y_rate
  61.       when 2
  62.         # 计算每pass放大率
  63.         @x_rate = Math.sqrt(x_rate)
  64.         @y_rate = Math.sqrt(y_rate)
  65.       when 4
  66.         # 计算每pass放大率
  67.         @x_rate = Math.sqrt(Math.sqrt(x_rate))
  68.         @y_rate = Math.sqrt(Math.sqrt(y_rate))
  69.       end
  70.       # 绘制Bitmap
  71.       loop do
  72.         break if @pass == 0
  73.         # 获取原Bitmap及宽高信息
  74.         @old_width  = @bitmap.width
  75.         @old_height = @bitmap.height
  76.         # 根据放大率计算新Bitmap尺寸
  77.         @new_width  = (@old_width  * @x_rate).ceil
  78.         @new_height = (@old_height * @y_rate).ceil
  79.         # 生成Bitmap
  80.         super(@new_width, @new_height)
  81.         # 缩放处理
  82.         draw(@bitmap)
  83.         # 循环(多pass)
  84.         @pass -= 1
  85.         @bitmap = self.clone
  86.       end
  87.     end
  88.     # 记录全局变量(测试用)
  89.     $bilinear_time = Time.now - @time_begin
  90.   end
  91.   #--------------------------------------------------------------------------
  92.   # ● 绘制Bitmap
  93.   #--------------------------------------------------------------------------
  94.   def draw(bitmap)
  95.     # 计算用宽高
  96.     @math_width  = @new_width  + @x_rate.ceil
  97.     @math_height = @new_height + @y_rate.ceil
  98.     # 生成一个储存所有像素颜色的Table(3维数组)
  99.     @color_table = Table.new(@old_width, @old_height, 4)
  100.     # 每行从左到右的顺序依次获取颜色并压入Table
  101.     for line in 0..(@old_height - 1)
  102.       for row in 0..(@old_width - 1)
  103.         @temp_color = bitmap.get_pixel(row, line)
  104.         @color_table[row, line, 0] = @temp_color.alpha unless @type == 0
  105.         @color_table[row, line, 1] = @temp_color.red
  106.         @color_table[row, line, 2] = @temp_color.green
  107.         @color_table[row, line, 3] = @temp_color.blue
  108.       end
  109.     end
  110.     # 一行一行绘制
  111.     for line in 0..(@new_height - 1)
  112.       # 过程1:获取本行通用浮点y坐标
  113.       do_math_1(line)
  114.       for row in 0..(@new_width - 1)
  115.         # 过程2:获取浮点x坐标
  116.         do_math_2(row)
  117.         # 过程3:获取颜色
  118.         do_math_3
  119.         # 过程4:计算颜色
  120.         do_math_4
  121.         # 后处理(预留模块)
  122.         post_treatment
  123.         # 绘制颜色
  124.         draw_color(row, line)
  125.       end
  126.     end
  127.   end
  128.   #--------------------------------------------------------------------------
  129.   # ● 计算(过程1:获取y坐标及y权)
  130.   #--------------------------------------------------------------------------
  131.   def do_math_1(y)
  132.     # 获取坐标
  133.     temp = y * @old_height
  134.     @ty1 = temp / @math_height
  135.     @ty2 = @ty1 + 1
  136.     # 获取权
  137.     @py2 = temp % @math_height * 100 / @math_height
  138.     @py1 = 100 - @py2
  139.   end
  140.   #--------------------------------------------------------------------------
  141.   # ● 计算(过程2:获取x坐标及x权)
  142.   #--------------------------------------------------------------------------
  143.   def do_math_2(x)
  144.     # 获取坐标
  145.     temp = x * @old_width
  146.     @tx1 = temp / @math_width
  147.     @tx2 = @tx1 + 1
  148.     # 获取权
  149.     @px2 = temp % @math_width * 100 / @math_width
  150.     @px1 = 100 - @px2
  151.   end
  152.   #--------------------------------------------------------------------------
  153.   # ● 计算(过程3:获取颜色)
  154.   #--------------------------------------------------------------------------
  155.   def do_math_3
  156.     # 获取四点颜色对应的权
  157.     @p11 = @px1 * @py1
  158.     @p21 = @px2 * @py1
  159.     @p12 = @px1 * @py2
  160.     @p22 = @px2 * @py2
  161.     # 从Table中获取颜色
  162.     unless @type == 0
  163.       @c11_a = @color_table[@tx1, @ty1, 0]
  164.       @c21_a = @color_table[@tx2, @ty1, 0]
  165.       @c12_a = @color_table[@tx1, @ty2, 0]
  166.       @c22_a = @color_table[@tx2, @ty2, 0]
  167.     end
  168.     @c11_r = @color_table[@tx1, @ty1, 1]
  169.     @c21_r = @color_table[@tx2, @ty1, 1]
  170.     @c12_r = @color_table[@tx1, @ty2, 1]
  171.     @c22_r = @color_table[@tx2, @ty2, 1]
  172.     @c11_g = @color_table[@tx1, @ty1, 2]
  173.     @c21_g = @color_table[@tx2, @ty1, 2]
  174.     @c12_g = @color_table[@tx1, @ty2, 2]
  175.     @c22_g = @color_table[@tx2, @ty2, 2]
  176.     @c11_b = @color_table[@tx1, @ty1, 3]
  177.     @c21_b = @color_table[@tx2, @ty1, 3]
  178.     @c12_b = @color_table[@tx1, @ty2, 3]
  179.     @c22_b = @color_table[@tx2, @ty2, 3]
  180.   end
  181.   #--------------------------------------------------------------------------
  182.   # ● 计算(过程4:计算颜色)
  183.   #--------------------------------------------------------------------------
  184.   def do_math_4
  185.     @a = (@c11_a * @p11 + @c21_a * @p21 + @c12_a * @p12 + @c22_a * @p22) / 10000 unless @type == 0
  186.     @r = (@c11_r * @p11 + @c21_r * @p21 + @c12_r * @p12 + @c22_r * @p22) / 10000
  187.     @g = (@c11_g * @p11 + @c21_g * @p21 + @c12_g * @p12 + @c22_g * @p22) / 10000
  188.     @b = (@c11_b * @p11 + @c21_b * @p21 + @c12_b * @p12 + @c22_b * @p22) / 10000
  189.   end
  190.   #--------------------------------------------------------------------------
  191.   # ● 后处理(预留模块)
  192.   #--------------------------------------------------------------------------
  193.   def post_treatment
  194.     unless @type == 0
  195.       @color = @temp_color.set(@r, @g, @b, @a)
  196.     else
  197.       @color = @temp_color.set(@r, @g, @b)
  198.     end
  199.     # 预留
  200.   end
  201.   #--------------------------------------------------------------------------
  202.   # ● 绘制颜色
  203.   #--------------------------------------------------------------------------
  204.   def draw_color(x, y)
  205.     set_pixel(x, y, @color)
  206.   end
  207. end
复制代码
天知道这效率差的要死的玩意有啥用 ╮(╯_╰)╭



用8pass的话(也就是再开一次平方)显然会更平滑,
但是因为双线性插值的特性会产生不可避免的模糊。
orz君帮忙搬到C++了……效率可谓质变……

(原图 4021×6050 缩放倍数 0.125)
RGSS3采用1pass耗时近1分钟,
C++采用4pass耗时刚过半秒……

评分

参与人数 2星屑 +460 收起 理由
退屈£无聊 + 400
orzfly + 60

查看全部评分

Lv2.观梦者

傻♂逼

梦石
0
星屑
369
在线时间
1605 小时
注册时间
2007-3-13
帖子
6562

烫烫烫开拓者

2
发表于 2012-1-1 17:46:43 | 只看该作者
本帖最后由 yangff 于 2012-1-1 17:51 编辑

用卷积插值吧。。
=T=
ps:用MMX或者GPU优化其实很明显的额。。

点评

= = b 咱可没有菲菲姐那么触啊  发表于 2012-1-1 18:51
哎呀,蛋疼什么的最有爱了
回复 支持 反对

使用道具 举报

Lv6.析梦学徒

Fuzzy Ginkgo
Taciturn Knight

梦石
0
星屑
60705
在线时间
1933 小时
注册时间
2010-6-26
帖子
1605

烫烫烫开拓者

3
发表于 2012-1-3 03:08:43 | 只看该作者
本帖最后由 fux2 于 2014-2-19 16:00 编辑

我来丢一个附件
NekoExt.dll & NekoExt.rb
自行拆解吧
我洗洗睡了
NekoExt.7z (7.07 KB, 下载次数: 5)
vc90写的 下次让我换个编译器吧 这个需要msvcr90.dll

@各种压力的猫君 , release配置里面编译器参数需要加上/Gz /TC 就是__stdcall和编译为C代码

评分

参与人数 1星屑 +200 收起 理由
各种压力的猫君 + 200 认可答案

查看全部评分

我的言论只代表我个人的观点,不代表雇主及/或任何第三方的立场。
Opinions expressed are solely my own and do not express the views or opinions of my employer and/or any third parties.
捐赠 | GitHub
回复 支持 反对

使用道具 举报

Lv2.观梦者

(?????)

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

贵宾

4
 楼主| 发表于 2012-2-1 20:00:05 | 只看该作者
  1. #==============================================================================
  2. # ■ Bilinear_Zoom_Lib 1.0
  3. #------------------------------------------------------------------------------
  4. #  双线性插值图像缩放算法
  5. #     by:各种压力的猫君  鸣谢:wbsy8241、orzfly
  6. #------------------------------------------------------------------------------
  7. #   使用方法:
  8. #     Bilinear_Zoom.new(bitmap, x_rate, y_rate, pass, type)
  9. #       - bitmap   待缩放Bitmap
  10. #       - x_rate   横轴放大率(支持小数)
  11. #       - y_rate   纵轴放大率(支持小数)
  12. #       - pass = 0 采用RM默认算法(测试用)
  13. #              = 1 处理1次(默认)
  14. #              = 2 处理2次(质量提升,用时翻倍)
  15. #              = 4 处理4次(质量再提升,用时再翻倍)
  16. #       - type = 1 计算Red、Green、Blue、Alpha(默认,有透明度)
  17. #              = 0 计算Red、Green、Blue,Alpha = 255(速度较快,无透明度)
  18. #------------------------------------------------------------------------------
  19. #   脚本说明:
  20. #     Bilinear_Zoom 1.0 的DLL版,需要 NekoExt.DLL 的支持。
  21. #------------------------------------------------------------------------------
  22. #   更新记录:
  23. #     1.0 2012-02-01 初次发布,不支持type参数(摆设一个)
  24. #==============================================================================

  25. class Bitmap
  26.   RtlMoveMemory_pi = Win32API.new('kernel32', 'RtlMoveMemory', 'pii', 'i')
  27.   RtlMoveMemory_ip = Win32API.new('kernel32', 'RtlMoveMemory', 'ipi', 'i')
  28.   def address
  29.     buffer, ad = "rgba", object_id * 2 + 16
  30.     RtlMoveMemory_pi.call(buffer, ad, 4)
  31.     ad = buffer.unpack("L")[0] + 8
  32.     RtlMoveMemory_pi.call(buffer, ad, 4)
  33.     ad = buffer.unpack("L")[0] + 16
  34.     RtlMoveMemory_pi.call(buffer, ad, 4)
  35.     return buffer.unpack("L")[0]
  36.   end
  37.   BilinearZoom_iiiiiiii = Win32API.new('NekoExt', 'BilinearZoom', 'iiiiiiii', 'i')
  38.   def biliner_zoom(x_rate, y_rate, pass = 1, type = 1)
  39.     result = 0
  40.       case pass
  41.       when 1
  42.         # 获取放大率
  43.         @x_rate = x_rate
  44.         @y_rate = y_rate
  45.       when 2
  46.         # 计算每pass放大率
  47.         @x_rate = Math.sqrt(x_rate)
  48.         @y_rate = Math.sqrt(y_rate)
  49.       when 4
  50.         # 计算每pass放大率
  51.         @x_rate = Math.sqrt(Math.sqrt(x_rate))
  52.         @y_rate = Math.sqrt(Math.sqrt(y_rate))
  53.       when 8
  54.         # 计算每pass放大率
  55.         @x_rate = Math.sqrt(Math.sqrt(Math.sqrt(x_rate)))
  56.         p @x_rate
  57.         @y_rate = Math.sqrt(Math.sqrt(Math.sqrt(y_rate)))
  58.       end
  59.       # 绘制Bitmap
  60.       loop do
  61.         break if pass == 0
  62.         result = Bitmap.new(
  63.         (self.width  * @x_rate).ceil,
  64.         (self.height * @y_rate).ceil
  65.         )
  66.         BilinearZoom_iiiiiiii.call(
  67.           address,
  68.           result.address,
  69.           width,
  70.           height,
  71.           result.width,
  72.           result.height,
  73.           result.width + @x_rate.ceil,
  74.           result.height + @y_rate.ceil
  75.         )
  76.         # 循环(多pass)
  77.         pass -= 1
  78.       end
  79.     return result
  80.   end
  81. end
复制代码
配合orz君的DLL使用 - - 才想起来没发
回复 支持 反对

使用道具 举报

Lv1.梦旅人

66RPG我的

梦石
0
星屑
163
在线时间
491 小时
注册时间
2012-1-16
帖子
1993
5
发表于 2012-2-1 21:14:39 | 只看该作者
没有理解这个脚本干嘛的,是测试游戏的打开用时吗。请问如果对方没有安装VC可以运行吗?

点评

收缩位图。  发表于 2012-2-2 17:06
帐号并非本人使用!
帐号并非本人使用!
帐号并非本人使用!
帐号并非本人使用!
帐号并非本人使用!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-5-10 11:51

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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