查看: 3613|回复: 5

[原创发布] 不规则位图传送/Blt增强

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

R考场第七期纪念奖

发表于 2019-10-25 14:57:54 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 SixRC 于 2019-10-28 17:14 编辑

更新情况在四楼 主楼不想改

不单纯blt矩形 根据mask位图的透明度blt 直接效果图吧 比较好理解
[fold] 0.gif
1.gif
3.gif [/fold]
一共是两块内容
一块是 MaskBlt
一块是 BltMask
MaskBlt :
mask_blt(x,y,src,rect,mask,opc = 255)
就是多了一个 mask 这个参数可以直接是位图 也可以是等下的 BltMask 类型
这个mask的大小必须和Rect一致 或者更大 不然会炸的 一般反正就一样就行
根据这个mask各点的透明度来进行blt操作
还有一个mask_blt_reverse 参数是一样的 就是进行了 255 - 透明度的操作
这个函数 进行了多线程加持 而且基于之前我写的很多优化 效率很高
单线程情况耗时大概是原版blt的 13/11
现在一般都有多线程了 那效率就很好henhao了

BltMask :
这块基于 agg(anti grain geometry)
是对位图进行画图的类 就是画线 画多边形 圆等的 还有作一些简单坐标变换的
初始化
[pre lang="ruby"]aa = BltMask.new(400, 400)[/pre]
会新建相应大小的位图 并进行初始化
不需要时请 aa.dispose
这个类作图的逻辑是这样的
加入点 圆 弧线等 然后渲染 渲染会清空之前的点序列
我知道这样说不太好理解 我看agg的时候开始也很迷
比分画线
[pre lang="ruby"]aa.move_to(0, 0)
aa.line_to(100, 100)
aa.draw_line[/pre]
move_to 就是移到那里
line_to 就是画过去
draw_line 就是渲染
画个实心圆
[pre lang="ruby"]aa.ellipse(200, 200, 100, 100)
aa.draw_poly[/pre]
复合也行
[pre lang="ruby"]aa.move_to(0, 0)
aa.line_to(100, 100)
aa.ellipse(200,200,100,100)
aa.line_to(400,400)
aa.draw_line[/pre]
画好了就能当mask_blt的参数 直接传 aa 进去就行
用完了记得 aa.clear 清空位图
下面是所有方法介绍
[fold=线相关]move_to(x, y)
移到那里
可以是浮点数
line_to(x, y)
画到那里
可以是浮点数
curve3(cx, cy, x, y)
贝塞尔曲线
控制点和目标点
可以是浮点数
curve4(cx1, cy1, cx2, cy2, x, y)
同上
多了个控制点
[/fold]
[fold=弧圆相关]ellipse(x, y, rx, ry, step = 0, cw = false)
坐标和半径
step是画圆内接多边形 0是圆
cw是顺时针逆时针
arc(x, y, rx, ry, a1, a2, rad = false)
画弧线
坐标和半径
然后是起始角度终止角度 顺时针
最后参数是是否为 rad 角 pi or 180 ?
默认后面[/fold]
[fold=渲染相关]draw_line(width = 0)
粗细 0为默认
可浮
draw_dash(len = 5, gap = 5, width = 0)
画虚线
实线长、线间隔、粗细
可浮
draw_poly
画实心多边形/不规则图形 无参[/fold]
[fold=坐标转换]坐标转换是这样工作的
先一系列变换 然后实的计算
相当于加点->渲染
translate(x, y)
平移
scale(x, y)
缩放 对象是坐标
也就是 x y 轴的缩放
rotate(a, rad = false)
旋转 绕 0,0
transform
进行变换
比分
aa.translate(-x,- y)
aa.rotate(80)
aa.translate(x, y)
aa.transform
是绕 x y 转了80度
trans_reset
重设转换 就是清空
每次变换完记得刷新

坐标转换在渲染前进行
是对点集进行处理的过程[/fold]
[fold=其他]end_poly
封闭图形
比分
move_to(0,0)
line_to(100,50)
line_to(50,100)
最后不需要回到0,0
end_poly 一下就行 会回到原点

clear
清空位图

dispose
释放内存[/fold]
[fold=线段衔接柔化]soft = true/false
开关
soft_value = xxx
值 默认1
会自动在渲染的时候进行操作[/fold]
如上
一般就是 设置好mask 然后mask_blt
示例没有 自己试着玩吧
下面代码
[fold=MaskBlt]
[pre lang="ruby"]Win32API.new("kernel32","LoadLibraryA","p","v").call("MaskBlt/tbb")
class Bitmap
  alias initialize_maskblt initialize
  attr_accessor :maskblt_addr
  MASKBLT_WPMPL = Win32API.new('kernel32','WriteProcessMemory','lplll','l')
  def initialize(*args)
    initialize_maskblt(*args)
    temp = "\0" * 4
    MASKBLT_WPMPL.call(-1, temp, self.__id__*2 + 0x10, 4, 0)
    MASKBLT_WPMPL.call(-1, temp, temp.unpack("l")[0] + 8, 4, 0)
    MASKBLT_WPMPL.call(-1, temp, temp.unpack("l")[0] + 0x10, 4, 0)
    @maskblt_addr = temp.unpack("l")[0]
  end         
  MaskBlt = Win32API.new("MaskBlt/MaskBlt","mask_blt","llllllllllllll","v")
  def mask_blt(x,y,src,rect,mask,opc = 255)
    MaskBlt.call(src.maskblt_addr,src.width,src.height,rect.x,rect.y,
                   self.maskblt_addr,self.width,self.height,x,y,
                   rect.width, rect.height, opc, mask.maskblt_addr)
  end   
  MaskBltRev = Win32API.new("MaskBlt/MaskBlt","mask_blt_reverse","llllllllllllll","v")
  def mask_blt_reverse(x,y,src,rect,mask,opc = 255)
    MaskBltRev.call(src.maskblt_addr,src.width,src.height,rect.x,rect.y,
                   self.maskblt_addr,self.width,self.height,x,y,
                   rect.width, rect.height, opc, mask.maskblt_addr)
  end
end
[/pre]
[/fold]
[fold=BltMask]
[pre lang="ruby"]class BltMask
  attr_reader :maskblt_addr
  attr_accessor :soft, :soft_value
  INIT = Win32API.new("MaskBlt/BltMask","init","pp","v")
  def initialize(width, height)
    @bitmap = Bitmap.new(width, height)
    @width, @height = width, height
    @maskblt_addr = @bitmap.maskblt_addr
    ll = "0000"
    pp = "pppp"
    INIT.call(ll, pp)
    @path_storage = ll.unpack("l")[0]
    @trans = pp.unpack("l")[0]
    @soft = false
    @soft_value = 1
  end
  LINETO = Win32API.new("MaskBlt/BltMask","line_to","lp","v")
  def line_to(x, y)
    p = [x.to_f,y.to_f].pack("dd")
    LINETO.call(@path_storage,p)
  end
  MOVETO = Win32API.new("MaskBlt/BltMask","move_to","lp","v")
  def move_to(x, y)
    p = [x.to_f,y.to_f].pack("dd")
    MOVETO.call(@path_storage,p)
  end
  ELLIPSE = Win32API.new("MaskBlt/BltMask","ellipse","lpll","v")
  def ellipse(x, y, rx, ry, step = 0, cw = false)
    p = [x.to_f, y.to_f, rx.to_f, ry.to_f].pack("d4")
    ELLIPSE.call(@path_storage, p, step, cw ? 1 : 0)
  end
  ARC = Win32API.new("MaskBlt/BltMask","arc","lpl","v")
  def arc(x, y, rx, ry, a1, a2, rad = false)
    p = [x.to_f, y.to_f, rx.to_f, ry.to_f, a1.to_f, a2.to_f].pack("d6")
    ARC.call(@path_storage, p, rad ? 1 : 0)
  end
  DRAWLINE = Win32API.new("MaskBlt/BltMask","draw_line","llllpl","v")
  def draw_line(width = 0)
    DRAWLINE.call(@maskblt_addr,@width,@height,@path_storage,
                  [width.to_f,@soft_value.to_f].pack("dd"),
                  @soft ? 1 : 0)
  end
  DRAWDASH = Win32API.new("MaskBlt/BltMask","draw_dash","llllpl","v")
  def draw_dash(len = 5, gap = 5, width = 0)
    p = [width.to_f, len.to_f, gap.to_f,@soft_value.to_f].pack("d4")
    DRAWDASH.call(@maskblt_addr,@width,@height,@path_storage,p,@soft ? 1 : 0)
  end
  ENDPOLY = Win32API.new("MaskBlt/BltMask","end_poly","l","v")
  def end_poly
    ENDPOLY.call(@path_storage)
  end
  DRAWPOLY = Win32API.new("MaskBlt/BltMask","draw_poly","lllllp","v")
  def draw_poly
    DRAWPOLY.call(@maskblt_addr,@width,@height,@path_storage,
                  @soft ? 1 : 0,[@soft_value.to_f].pack("d"))
  end
  CURVE3 = Win32API.new("MaskBlt/BltMask","curve3","lp","v")            
  def curve3(cx, cy, x, y)
    p = [cx.to_f, cy.to_f, x.to_f, y.to_f].pack("d4")
    CURVE3.call(@path_storage, p)
  end
  CURVE4 = Win32API.new("MaskBlt/BltMask","curve4","lp","v")   
  def curve4(cx1, cy1, cx2, cy2, x, y)
    p = [cx1.to_f, cy1.to_f, cx2.to_f, cy2.to_f, x.to_f, y.to_f].pack("d6")
    CURVE4.call(@path_storage, p)
  end
  ROTATE = Win32API.new("MaskBlt/BltMask","rotate","lpl","v")
  def rotate(a, rad = false)
    p = [a.to_f].pack("d")
    ROTATE.call(@trans, p, rad ? 1 : 0)
  end
  TRANSFORM = Win32API.new("MaskBlt/BltMask","transform","ll","v")
  def transform
    TRANSFORM.call(@path_storage, @trans)
  end
  TRANSLATE = Win32API.new("MaskBlt/BltMask","translate","lp","v")
  def translate(x, y)
    p = [x.to_f, y.to_f].pack("d2")
    TRANSLATE.call(@trans, p)
  end
  SCALE = Win32API.new("MaskBlt/BltMask","scale","lp","v")
  def scale(x, y)
    p = [x.to_f, y.to_f].pack("d2")
    SCALE.call(@trans, p)
  end
  TRANSRESET = Win32API.new("MaskBlt/BltMask","trans_reset","l","v")
  def trans_reset
    TRANSRESET.call(@trans)
  end
  def clear
    @bitmap.clear
  end
  DISPOSE = Win32API.new("MaskBlt/BltMask","dispose","ll","v")   
  def dispose
    DISPOSE.call(@path_storage, @trans)
    @bitmap.dispose
  end
end
[/pre]
[/fold]
插到随便什么地方
MaskBlt.zip (236.58 KB, 下载次数: 67)
解压到文件目录

就这样

评分

参与人数 2星屑 +500 赞 +1 收起 理由
hyrious + 1 塞糖
fux2 + 500 精品文章

查看全部评分

老黄鸡

梦石
4
星屑
45692
在线时间
7947 小时
注册时间
2009-7-6
回帖
13335

MZ评测员RM创作大赛01组委会开拓者贵宾

发表于 2019-10-26 10:57:41 | 显示全部楼层
相当方便了(用造好的就是舒服

点评

谢谢大黄鸡!  发表于 2019-10-26 12:46
RGDirect - DirectX驱动的RGSS,点我了解.
(排满,暂停)RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复

使用道具 举报

梦石
1
星屑
23236
在线时间
9564 小时
注册时间
2012-6-19
回帖
7018

开拓者短篇九导演组冠军

发表于 2019-10-26 21:57:24 | 显示全部楼层
本帖最后由 喵呜喵5 于 2019-10-26 22:45 编辑

哇,先开个工程试试看

=======

又能鼓捣出一些新玩意儿了~
如果rect也能支持这个mask就好了……


Animation.gif


点评

配图无敌了... 涉及到Rect的地方对Rect的使用方式都不同 毕竟原设计上rect就是四个简单量的替代吧 并不是很重要 要改就得把所有地方都改啦  发表于 2019-10-26 23:06
回复

使用道具 举报

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

R考场第七期纪念奖

 楼主| 发表于 2019-10-28 17:12:40 | 显示全部楼层
发个更新贴 以后若更新会改在这里
一是考虑到mask其实大部分像素alpha都是0 所以加了判断 牺牲微不足道的效率(~%6) 可以获得成倍的速度提升
二是毕竟牺牲了一些  所以就对其作了进一步优化
方式是手写了汇编
原先编译器优化的代码比较 诡异 和我写的思路不太一致
和它斗智斗勇半天 它还是不懂我 我累了 就直接汇编了
结果 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈
耗时降低了约 42%
加上第一个修改 综合耗时看情况约是原先的 30%~60% 基本是快了一番
所以是 重 大 的 版本更新
MaskBlt_v11.zip (39.98 KB, 下载次数: 45)
替换原来的 MaskBlt.dll 就行啦
现在基本上没啥好更新的了 冬眠了

评分

参与人数 2赞 +2 收起 理由
VIPArcher + 1 塞糖
hyrious + 1 塞糖

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

在本版发帖返回顶部