查看: 4051|回复: 31

[原创发布] BitmapEnhance 2.0

[复制链接]
梦石
0
星屑
13562
在线时间
2753 小时
注册时间
2014-10-4
回帖
705

R考场第七期纪念奖

发表于 2019-5-13 13:12:39 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 SixRC 于 2019-5-20 12:22 编辑

BitmapEnhance2.0 发布
缺乏编辑能力 更新了就直接写最前面了
这次更新 对函数没做改动
变的是效率
现在用了VS编译(VS真香) 然后整理了一下OpenCV模块 添加了多线程等支持(主要是TBB) 删掉了些没用的 用tbb改写了Mosaic
本来想用GPU 但是CUDA适用性不广 OPENCL 用了还不如不用 因为运算量其实不大 时间反而浪费在内存拷贝上 用GPU没体现意义 多线程的意义远远大于GPU了
现在的效率是之前的几倍吧 效率的提升看CPU核心数 至少翻一番
依旧是静态库 所以不用担心运行库的问题
因为文件有6M了 所以是外链
biten2.0

基于 OpenCV 4.1.0
给 Bitmap 类加了一些图像处理功能
顺便结合了上次做的东西  怎样才能更改地图部分色调,部分不更改?
然后就可以很方便的更改显示的画面 像是任意尺寸放大 加滤镜什么的
[fold=实现和闲话]
开始我其实是想像黄鸡一样搞个放大游戏画面的东西出来
然后就开始搜现成的图像处理库
搜了一大堆 大部分得用 c++ 这玩意我不会啊 有个基于 c 的 但是是 GPL 那用了不是整个游戏要开源了..
好吧我就先看了下 c++ 大概翻了下教程 能写就行
现在我"会" c++ 了 那来吧 选库吧 随便选!那就 OpenCV 吧!
用得用最新的(毕竟看了那么多更新的效率提升的记录 心动) 下了官方的 bin 发现没有32位
没有就没有 我自己编译
然后就一堆操作 各种踩坑 编译了几遍终于好了
(这里我要说!我是 msys2 编译的 cmake 神坑 命令行里直接卡住)
(然而桌面版的 cmake 没有相关的环境变量调用不到msys2的东西)
(最后在msys2里打开了cmakegui终于好了 虽然解决思路简单 但 主要是没人跟我一样 都是vs编译的)
自己编译还是有大大好处的 可以调整用到的支持 比方取消 dx11 增加兼容性 (?我觉得) 比方静态链接就只需要链接用到的库减少成品文件大小
然后的过程在现在看来还比较平淡的 写这个函数的接口 写那个 写那个那个 (其实各种改bug)
感觉跟重复劳动一样 因为都是调用 opencv 我也没啥思考 就看文档 抄抄抄
不过还是挺好玩的 学习 opencv 的同时学习 c++
[/fold]
下面是新增的方法
作用对象是整个位图
对目前位图的处理需要一个输出位图 可以自己指定 默认输出到自身 传入非位图自动调整为self (这样写参数可以偷懒)
对了 假如图像处理的参数传的值不对 程序会炸 比方需要奇数传了偶数 根据官方文档好好传参
[fold=biten_resize]
调用形式有两个 一是传入宽高 二是传入输出 插值算法为可选参
bitmap.biten_resize(1280, 720, [interpolation])
这个会新建一张位图作为输出
bitmap.biten_resize(output, [interpolation])
这个根据 output 的尺寸进行缩放然后输出到他
因为放大的话新数据原位图本身放不下 所以不要传自己作为输出
可选算法
[pre lang="c"]    /** nearest neighbor interpolation */
    INTER_NEAREST        = 0,
    /** bilinear interpolation */
    INTER_LINEAR         = 1,
    /** bicubic interpolation */
    INTER_CUBIC          = 2,
    /** resampling using pixel area relation. It may be a preferred method for image decimation, as
    it gives moire'-free results. But when the image is zoomed, it is similar to the INTER_NEAREST
    method. */
    INTER_AREA           = 3,
    /** Lanczos interpolation over 8x8 neighborhood */
    INTER_LANCZOS4       = 4,
    /** Bit exact bilinear interpolation */
    INTER_LINEAR_EXACT = 5,[/pre]
whereas to enlarge an image, it will generally look best with c::INTER_CUBIC (slow) or INTER_LINEAR (faster but still looks OK).

[/fold]
[fold=biten_blur]
输入模糊核的宽高 默认 3
bitmap.biten_blur([width, [height, [out]]])
10, 3 的效果
1.png
[/fold]
[fold=biten_dilate]
biten_dilate(ksizew = 3, ksizeh = 3, out = self, shape = 0, iterations = 1)
核的宽高
shape:
[pre lang="c"]enum MorphShapes {
    MORPH_RECT    = 0, //!< a rectangular structuring element:  \f[E_{ij}=1\f]
    MORPH_CROSS   = 1, //!< a cross-shaped structuring element:
                       //!< \f[E_{ij} =  \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\f]
    MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed
                      //!< into the rectangle Rect(0, 0, esize.width, 0.esize.height)
};[/pre]
iterations 迭代次数
3, 3 的效果 迭代一次
dilate.png
[/fold]
[fold=biten_erode]
biten_erode(ksizew = 3, ksizeh = 3, out = self, shape = 0, iterations = 1)
3, 3 的效果 迭代一次
erode.png
[/fold]
不想写解释了 因为我也不是那么懂参数的意义 去看 opencv 文档吧 右上角查询
OpenCV 4.1.0 文档
要不百度下 关键词 opencv 函数名 比方 opencv GaussianBlur 肯定一大堆解释加范例 比我说的好多了
[fold=biten_GaussianBlur]
biten_GaussianBlur(ksizew = 3, ksizeh = 3, out = self, sigmaX = 0.0, sigmaY = 0.0)
size 必须是正奇数 不然就炸给你看
9, 3
gb.png
[/fold]
[fold=biten_medianBlur]
biten_medianBlur(ksize = 3, out = self)
ksize 必须是大于 1 的奇数
9
mb.png
size大了效率低 因为  核大了运算多了
但这个函数 核大了尤其慢
[/fold]
[fold=biten_morphologyEx]
biten_morphologyEx(op, ksizew = 3, ksizeh = 3, out = self, shape = 0, iterations = 1)
op是操作方式
[pre lang="c"]//! type of morphological operation
enum MorphTypes{
    MORPH_ERODE    = 0, //!< see #erode
    MORPH_DILATE   = 1, //!< see #dilate
    MORPH_OPEN     = 2, //!< an opening operation
                        //!< \f[\texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} ))\f]
    MORPH_CLOSE    = 3, //!< a closing operation
                        //!< \f[\texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} ))\f]
    MORPH_GRADIENT = 4, //!< a morphological gradient
                        //!< \f[\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )\f]
    MORPH_TOPHAT   = 5, //!< "top hat"
                        //!< \f[\texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} )\f]
    MORPH_BLACKHAT = 6, //!< "black hat"
                        //!< \f[\texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src}\f]
    MORPH_HITMISS  = 7  //!< "hit or miss"
                        //!<   .- Only supported for CV_8UC1 binary images. A tutorial can be found in the documentation
};[/pre]
7 是不支持的 因为输入是 CV_8UC4  
传 7 ========================== 炸
这个 没图 这个主要应该不是拿来加滤镜的.. 也不是说不可以
[/fold]
[fold=biten_Scharr]
biten_Scharr(dx, dy, out = self, scale = 1.0, delta = 0.0)
dx dy 可以是 1,0 0,1 1,1
[/fold]
[fold=biten_Canny]
biten_Canny(threshold1, threshold2, out = self, apertureSize = 3, l2gradient = 0)
biten_Canny(80,160,0,3,1)
ca.png
用于边缘检测
[/fold]
[fold=Mosaic]
biten_Mosaic(sizew = 2, sizeh = 2, out = self)
2, 2
m'm批注 2019-05-13 124118.png
这是我写的 所以..别查参数的意思了 字面意思
[/fold]
[fold=filter2D]
biten_filter2D(kw, kd, kernel, out = self, delta = 0.0)
biten_filter2D2(kw, kd, kernel, out = self, delta = 0.0)
上面那个接收整型的卷积核
下面接受双精度浮点数的卷积核
下面是使用范例
[pre lang="ruby"]kernel=[-1,0,0,
        0,0,0,
        0,0,1].pack("l*") # "d*" if double
bitmap.biten_filter2D(3,3,kernel,0,80)[/pre]
fd.png
这个传入自定义卷积核实现各种效果
[/fold]
下面是整个画面滤镜的实现
[fold]
[pre lang="ruby"]module Graphics
  module_function
  # max 2560 *  1920
  CCBBSS_SRC_WIDTH = 640
  CCBBSS_SRC_HEIGHT = 480
  CCBBSS_DET_WIDTH = 1280
  CCBBSS_DET_HEIGHT = 960
  CCBBSS_SRC_BITMAP = Bitmap.new(CCBBSS_SRC_WIDTH, CCBBSS_SRC_HEIGHT)
  CCBBSS_DET_BITMAP = Bitmap.new(CCBBSS_DET_WIDTH, CCBBSS_DET_HEIGHT)
  CCBBSS_DLL = Win32API.new('kernel32','GetModuleHandleA','p','l').call('RGSS103J')
  CCBBSS_WPMLP = Win32API.new('kernel32','WriteProcessMemory','llpll','l')
  CCBBSS_WPMPL = Win32API.new('kernel32','WriteProcessMemory','lplll','l')
  temp = "\0"*4
  CCBBSS_WPMPL.call(-1, temp, CCBBSS_DLL + 0x12B6C4, 4, 0)
  CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x134, 4, 0)
  CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0xB4, 4, 0)
  CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x10, 4, 0)
  CCBBSS_BITMAP = temp.unpack("l")[0]
  CCBBSS_WPMPL.call(-1, temp, CCBBSS_DLL + 0x12B6C4, 4, 0)
  CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x144, 4, 0)
  CCBBSS_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x10, 4, 0)
  CCBBSS_FREEZE_BITMAP = temp.unpack("l")[0]
  CCBBSS_RUBY_CODE = "Graphics.ccbbss_update"
  CCBBSS_CODE = [0x8B, 0x54,0x24, 0x10,
                 0x60, 0x68, CCBBSS_RUBY_CODE,
                 0xB8, CCBBSS_DLL + 0x31D70,
                 0xFF, 0xD0,
                 0x83, 0xC4, 0x04, 0x61,
                 0x68, 0xCC0020,
                 0x6A, 0x00, 0x6A, 0x00, 0x57,
                 0xBF, CCBBSS_DLL + 0x884CD,
                 0xFF, 0xE7].pack("C6pClC7lC6lC2")
  cc = [0xBA, CCBBSS_CODE, 0xFF, 0xE2].pack("CpC2")
  CC_T = Win32API.new("user32","MessageBoxA","lppl","v")
  CCBBSS_WPMLP.call(-1, CCBBSS_DLL + 0x884C3, cc, 7, 0)
  CCBBSS_MAKE_BITMAP = Win32API.new("bitmap_enhance/biten","_Z11make_bitmapPvS_ii","llll","v")
  CCBBSS_SET_BITMAP = Win32API.new("bitmap_enhance/biten","_Z10set_bitmapPvS_ii","llll","v")
  CCBBSS_COPY_BITMAP = Win32API.new("bitmap_enhance/biten","_Z11copy_bitmapPvS_ii","llll","v")
  # prevent transition bug
  class << self
    alias transition_ccbbss transition
    def transition(*args)
      CCBBSS_SET_BITMAP.call(CCBBSS_FREEZE_BITMAP, CCBBSS_SRC_BITMAP.biten_addr, CCBBSS_SRC_WIDTH, CCBBSS_SRC_HEIGHT)
      Graphics.transition_ccbbss(*args)
    end
  end
  def ccbbss_update
    CCBBSS_MAKE_BITMAP.call(CCBBSS_BITMAP, CCBBSS_SRC_BITMAP.biten_addr, CCBBSS_SRC_WIDTH, CCBBSS_SRC_HEIGHT)
    dest = ccbbss_process(CCBBSS_SRC_BITMAP)
    CCBBSS_SET_BITMAP.call(CCBBSS_BITMAP, dest.biten_addr, dest.width, dest.height)
  end
  # customize here
  def ccbbss_process(src)
    kernel=[-1,0,0,
            0,0,0,
            0,0,1].pack("l*")
    CCBBSS_SRC_BITMAP.biten_filter2D(3,3,kernel,0,80)
    CCBBSS_SRC_BITMAP.biten_resize(CCBBSS_DET_BITMAP)
    return CCBBSS_DET_BITMAP
  end
end[/pre]
这是个扩大画面的例子
没什么好解释的?
[/fold]
没了
要用得有脚本基础
有些效果直接作用在画面上会导致字没法看清
所以得对那些位图个别使用
使用需要自己整合
文件 分两个包 因为超出2M大小了
biten1.0.zip (696.79 KB, 下载次数: 163)
bitmap_enhance.zip (1.87 MB, 下载次数: 166)
把下面那个解压到上面那个目录里就行
假如要用画面滤镜的话 请用我提供的 RGSS103J.dll
最大支持 2560*1920 (应该够了吧)
渐变问题也修复了
可以从任意尺寸放大到任意尺寸 但是不能缩小 因为RGSS渲染最多渲染到窗口大小 假如窗口小于需要渲染的初始范围 那些就无法显示了
逻辑是这样
游戏原本分辨率 640*480
现在窗口大小 比方 1280*960
本来只有左上角一块有画面
用了滤镜 加上放大效果
现在整个窗口都有了
这是放大的含义
窗口分辨率什么的要自己去选择

评分

参与人数 1赞 +1 收起 理由
mariofans + 1 解决了困扰多年的XP snap_to_bitmap只截表.

查看全部评分

梦石
0
星屑
2605
在线时间
896 小时
注册时间
2011-4-30
回帖
108

开拓者

发表于 2019-5-16 12:44:07 | 显示全部楼层
不知为何,用自编译的Game.exe会停止运行

点评

对 想起来函数名也改了..总之复制一下那个脚本页就好了  发表于 2019-5-20 14:08
你是直接复制了dll过去吗 我其实改了脚本 要先人工加载一下tbb.dll的  发表于 2019-5-20 14:04
额..  发表于 2019-5-20 14:03
...一个多线程库 那关了吧 反正没啥用 我是想不到为啥还出错 我回去了看看  发表于 2019-5-20 14:02
呸,是我Graphics里边的dll方法名没改。。。。。  发表于 2019-5-20 13:59
回复

使用道具 举报

梦石
0
星屑
13562
在线时间
2753 小时
注册时间
2014-10-4
回帖
705

R考场第七期纪念奖

 楼主| 发表于 2019-5-16 16:12:37 | 显示全部楼层
mariofans 发表于 2019-5-16 12:44
不知为何,用自编译的Game.exe会停止运行

你用动态调试器打开运行下看看挂在哪了?
因为出异常的话会优先给调试端看 不会马上挂的
然后就能清楚为什么会挂了
可能是空指针 写入超出范围啥的
肯定有原因的
分析下基本能看出来
我感觉应该不是我这边的问题
我改了dll 只换exe理论上没问题
我不知道你改了啥 不好猜测
要不你发一份exe给我我晚上分析一下?
我现在有事在外面
回复

使用道具 举报

梦石
0
星屑
2605
在线时间
896 小时
注册时间
2011-4-30
回帖
108

开拓者

发表于 2019-5-16 23:51:42 | 显示全部楼层
本帖最后由 mariofans 于 2019-5-17 14:08 编辑
SixRC 发表于 2019-5-16 16:12
你用动态调试器打开运行下看看挂在哪了?
因为出异常的话会优先给调试端看 不会马上挂的
然后就能清楚为什 ...


是基于这个改编的(测试这个也会挂)
汇编层面的东西我就不了解了。。。
ScrSh.png

第二次的报错位置

第二次的报错位置

Custom RGSS Player.rar

67.58 KB, 下载次数: 104

点评

假如是VS的话我查了 应该是项目->属性->链接器->高级->数据执行保护(DEP) 关掉就好了 别的编译器应该没这玩意  发表于 2019-5-17 10:54
所以解决一是看看你的编译器有没有和内存执行/保护相关的选项 二是在每个被执行的code前都要改它们的内存权限 就比较麻烦了  发表于 2019-5-17 10:50
已经确定问题了 和 DEP 相关 现在的编译器可能默认开启 DEP 保护内存安全 这个在程序生命周期内是无法修改的  发表于 2019-5-17 10:49
不过也不能说是内存属性问题 因为权限都一样 但是一个不能执行一个能 得查查具体是什么决定的  发表于 2019-5-17 10:19
确定了 是内存属性的问题 应该和编译器有关 我在想解决方法了  发表于 2019-5-17 10:15
回复

使用道具 举报

梦石
0
星屑
13562
在线时间
2753 小时
注册时间
2014-10-4
回帖
705

R考场第七期纪念奖

 楼主| 发表于 2019-5-17 00:59:17 | 显示全部楼层
本帖最后由 SixRC 于 2019-5-17 11:29 编辑
mariofans 发表于 2019-5-16 23:51
是基于这个改编的(测试这个也会挂)
汇编层面的东西我就不了解了。。。 ...


最新情况
用下面这个 RGSS103J.dll 就行了
改了rm创建堆栈时的参数 现在默认有内存执行权限了 兼容性好
RGSS103J.zip (497.09 KB, 下载次数: 109)
//
已经搞定了 在点评 下面是昨天的
//
收到 现在睡觉了 明天早课 我下课看
我看了下
你在原生exe基础上改的话应该不会出错吧?
假如那样 我现有的猜测是
ruby申请的内存是读写的也就是不可执行的
原game.exe可能注册了异常处理函数
在执行没有执行权限的内存时会改内存权限
可以试试把CCBBSS_CODE的内存权限改下
( virtualprotect 啥的)
或者用你编译的exe 在脚本里试试
code=[0xC2, 0x10, 0] # ret 10h
然后 CallWindowProc 看看会不会挂?
(字符串地址=[code].pack("p").unpack("l")[0]
或者api里用p直接传)

我觉得没啥地方能出错了
假如觉得麻烦的话就等我下

我想了想又觉得不是这个问题
因为平时也没遇到过这种事情
完全是我脑补出来的
算了 明天看到再说

或者和程序的默认堆栈属性有关
感觉我要起不来了

点评

关于效率问题 我发现 OpenCV 没有调用GPU 呃 应该是我没有编译相关的东西进去 我下次试着编译个利用GPU加速的看看 还想作些改进的 不过懒..  发表于 2019-5-17 14:56
p 是 p 在ccbbss_process里面吗 因为hook了画面刷新的过程 而 p 会刷新画面 所以会死循环挂掉 这函数里也不能 Graphics.update 的 只能用 MessageBox(CC_T) 替代  发表于 2019-5-17 14:53
现在OK了非常感谢,实时缩放的话Cubic太掉帧了就换成Linear了_(:D」∠)_  发表于 2019-5-17 14:32
找到原因了,之前测试的时候在那一句之后紧接着一个p方法的锅。。去掉就没事了不过为什么会这样呢  发表于 2019-5-17 14:14
原始exe也错了2333  发表于 2019-5-17 14:09
回复

使用道具 举报

梦石
0
星屑
2605
在线时间
896 小时
注册时间
2011-4-30
回帖
108

开拓者

发表于 2019-5-20 14:48:04 | 显示全部楼层
本帖最后由 mariofans 于 2019-5-20 14:58 编辑

现在的问题还在缩放上,我只用了纯缩放,只要在关卡中用上缩放总会把58~59帧降到28以下
在标题或者家中移动时基本不掉帧,一旦进入关卡中事件比较多的时候掉帧就很严重
这时候去掉处理直接让SRC原路返回的话又能回到58帧以上
(我用了类变量实现随时变更的缩放)
  1. def ccbbss_process(src)
  2.     if @@dest_bitmap
  3.       CCBBSS_SRC_BITMAP.biten_resize(@@dest_bitmap, 2)
  4.       return @@dest_bitmap
  5.     end
  6.     return CCBBSS_SRC_BITMAP
  7.   end
复制代码

起初怀疑仍是处理的时间长,就调查了一下处理时间,从640x480到1280x960也就花了0.002
然后怀疑是Set_Bitmap的问题,但无论@@dest_bitmap存在与否Set_Bitmap都会执行,难道是大图转换的时间长?
然后我又记录了Set_Bitmap的时间,发现也是0.00x
然后我又不知道问题在哪里了

标题

标题

关卡

关卡
QQ图片20190520145757.png
QQ图片20190520145802.png

点评

好吧。。。要怎么发  发表于 2019-5-20 16:11
能私发我一份工程吗 这样我也看不出什么来..只要能看得出问题的工程就行  发表于 2019-5-20 15:59
无论用哪种方式缩放都会掉  发表于 2019-5-20 14:51
回复

使用道具 举报

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

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部