查看: 2821|回复: 0

[原创发布] RGSS·GIF解码

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

R考场第七期纪念奖

发表于 2020-9-4 02:47:28 | 显示全部楼层 |阅读模式

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

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

×
本帖最后由 SixRC 于 2020-9-4 23:48 编辑

更新v1.1
增加了对 disposal method 和 delay time 的支持
现在可以无需额外判断的播放gif 范例及注意见代码
[fold=RM代码]
[pre lang="ruby"]=begin
-----------------------------GIF-Decoder--1-1-------------------------------
-------------------------------------------------SixRC----2020-9-4----------
--------支持透明度等-----不支持那些extension block----能偷的懒我都偷了------
----版本-1-1----------------------------------------------------------------
--增加对-disposal-method-以及-delay-time(秒数)-的支持-----------------------
----传入位图的目标区域会被全部改写(若纯透明则为0000)--请注意和blt的区别-----
---------------------------------范例---------------------------------------
gif = GifDecoder.new "01.gif"
s = Sprite.new
s.bitmap = Bitmap.new(gif.width, gif.height)
while gif.decode(s.bitmap)
  (Graphics.frame_rate * gif.delay_time).ceil.times{Graphics.update}
end
(Graphics.frame_rate * gif.delay_time).ceil.times{Graphics.update}
gif.dispose
s.dispose
s.bitmap.dispose
=end
class GifDecoder
  READ = Win32API.new("gifdcd", "read_gif", "pp", "l")
  DECODE = Win32API.new("gifdcd", "decode_gif", "llllp", "l")
  DISPOSE = Win32API.new("gifdcd", "dispose_gif", "l", "v")
  attr_reader :width, :height, :delay_time
  # 输入文件名 自己读宽高
  def initialize(fn)
    temp = "\0" * 8
    @gif = READ.call(fn, temp)
    @width, @height = temp.unpack("ll")
    @disposed = false
  end
  # 如果gif读取完毕 返回false
  # 传入位图 待写入的位置 x y 和透明度
  # 也就是位图宽高可以大于gif的宽高
  # 注意 x + 位图的宽不可以超过 gif 的宽 否则可能溢出
  def decode(bitmap, x = 0, y = 0, alpha = 255)
    addr = bitmap.addr + bitmap.width * 4 * (bitmap.height - 1)
    stride = -bitmap.width * 4
    addr = addr + x * 4 + y * stride
    dt = "\0" * 4
    ret = DECODE.call(@gif, addr, stride, alpha, dt) & 0xFF
    @delay_time = dt.unpack("l")[0] / 100.0
    return ret != 0
  end
  # 释放资源  
  # 每次加载一个gif文件 只能解码一次 没写回头功能
  def dispose
    return if @disposed
    DISPOSE.call(@gif)
    @disposed = true
  end
end
class Bitmap
  CWP = Win32API.new('user32.dll','CallWindowProc','ppiii','i')
  GetAddr=[139,116,36,8,139,54,139,118,8,139,118,16,139,124,36,4,137,55,194,16,0].pack("C*")
  def addr
    s="\0"*4
    CWP.call(GetAddr,s,object_id*2+16,0,0)
    s.unpack("L")[0]
  end
end[/pre]
[/fold]
gifdcd_v11.zip (234.43 KB, 下载次数: 29, 售价: 1 星屑)
基本完善了 大概不更新了

下面原帖

好久没发帖子了 凑合一下

简言之就是 spec-gif89a 根据这个(加一些别的资料)写了一个 gif 的解码功能(c++) 然后给RGSS接口 然后RGSS端就可以直接播放gif了
虽然其实我是想找现成的然后偷懒的 可是看了好多gif解码库 都感觉有点 ? 不如自己整一个
然后整是整出来了 就是只有基本功能..算了 能用就行 效率也ok 我满足了
(extension block 没处理 disposal method 这个参数也没理)
(别的影响输出的基本上处理了吧)

基本逻辑是搞一个GIF解码类
新建实例传入图片文件名 返回宽高信息
然后每次解码 就是写入到一个位图 解码的返回值true or false false就是文件读完了
读完了释放资源
[pre lang="ruby"]gif = GifDecoder.new "1.gif"
s = Sprite.new
s.bitmap = Bitmap.new(gif.width, gif.height)
while gif.decode(s.bitmap)
  5.times{Graphics.update}
  # 大部分gif传入上次输出的结果可以正常播放
  # 假如传空位图不正常的话
  #s.bitmap.clear
end
5.times{Graphics.update}
gif.dispose[/pre]
在每次解码这个过程中
输出的结果可以每帧保存 就能循环放 或者就放一次
每帧暂停的时间就自己掐吧..

具体参数见代码说明
下面正文

这个插到用之前
[fold=RM代码]
[pre lang="ruby"]=begin
-----------------------------GIF-Decoder--1-0-------------------------------
-------------------------------------------------SixRC----2020-9-4----------
--------支持透明度-----不支持很多----能偷的懒我都偷了-----------------------
=end
class GifDecoder
  READ = Win32API.new("gifdcd", "read_gif", "pp", "l")
  DECODE = Win32API.new("gifdcd", "decode_gif", "llll", "l")
  DISPOSE = Win32API.new("gifdcd", "dispose_gif", "l", "v")
  attr_reader :width, :height
  # 输入文件名 自己读宽高
  def initialize(fn)
    temp = "\0" * 8
    @gif = READ.call(fn, temp)
    @width, @height = temp.unpack("ll")
    @disposed = false
  end
  # 如果gif读取完毕 返回false
  # 传入位图 待写入的位置 x y 和透明度
  # 也就是位图宽高可以大于gif的宽高
  # 注意 x + 位图的宽不可以超过 gif 的宽 否则可能溢出
  def decode(bitmap, x = 0, y = 0, alpha = 255)
    addr = bitmap.addr + bitmap.width * 4 * (bitmap.height - 1)
    stride = -bitmap.width * 4
    addr = addr + x * 4 + y * stride
    ret = DECODE.call(@gif, addr, stride, alpha) & 0xFF
    return ret != 0
  end
  # 释放资源  
  # 每次加载一个gif文件 只能解码一次 没写回头功能
  def dispose
    return if @disposed
    DISPOSE.call(@gif)
    @disposed = true
  end
end
class Bitmap
  CWP = Win32API.new('user32.dll','CallWindowProc','ppiii','i')
  GetAddr=[139,116,36,8,139,54,139,118,8,139,118,16,139,124,36,4,137,55,194,16,0].pack("C*")
  def addr
    s="\0"*4
    CWP.call(GetAddr,s,object_id*2+16,0,0)
    s.unpack("L")[0]
  end
end[/pre]
[/fold]
然后把
gifdcd.zip (234.02 KB, 下载次数: 41)
丢到工程目录就行了

至于源码 没啥好看的
就这样吧

评分

参与人数 1赞 +1 收起 理由
zyf722 + 1 塞糖

查看全部评分

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

本版积分规则

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

在本版发帖返回顶部