赞 | 6 |
VIP | 356 |
好人卡 | 3 |
积分 | 2 |
经验 | 297560 |
最后登录 | 2022-1-18 |
在线时间 | 509 小时 |
Lv1.梦旅人 有事烧纸
- 梦石
- 0
- 星屑
- 154
- 在线时间
- 509 小时
- 注册时间
- 2005-10-22
- 帖子
- 6982
|
加入我们,或者,欢迎回来。
您需要 登录 才可以下载或查看,没有帐号?注册会员
x
分解GIFv1.0
分解GIF为PNG图片,其实也可以使RM读取GIF```
by 小夏
使用见脚本说明。
新地址
- =begin
- 脚本:【怨念产物】
-
- 功能:分解GIF图片为PNG格式。
-
- 说明: 直接用 GIF.analyze_gif 使用。
-
- 把需要分解的GIF文件放在工程下的GIF文件夹下即可,运行即可,ms速度比较慢。
- 作者:灼眼的夏娜
-
- =end
- =begin
- GIF文件格式初步讲解:
- 1、文件头(6字节):
-
- 2、逻辑屏幕标符(7字节) :
-
- 3、[全局调色板数据] :根据2中的GlobalFlag确定相关属性,可无。
-
- 4、[GIF扩充块]:各种扩充块,可无。
-
- [图形控制扩充块(6字节),图形说明扩充块(13+1+),注释说明扩充块(0+1+),应用程序扩充块(12+1+)]
-
- 5、图象描述块:0x2c 开始。
-
- 6、[局部调色板]:根据5中的LocalFlag中的LocalPal可以判断有无。
-
- 7、图象数据
-
- 8、7的第一个字节为LZW编码长度
-
- 9、编码长度之后为连续的数据子块,每个数据子块长度为 0 - 256 字节。
-
- 10、数据子块的第一个字节为该子块的长度。
-
- 11、文件结尾:0x3b
- =end
- module GIF
-
- # 定义常量
- SIZE_GIFH = 6
-
- SIZE_GIFS = 7
-
- SIZE_GIFI = 9
-
- SIZE_GIFC = 6
-
- SIZE_GIFP = 13
-
- SIZE_GIFA = 12
-
- CODE_MASK = [0x0000,
- 0x0001,0x0003,0x0007,0x000f,
- 0x001f,0x003f,0x007f,0x00ff,
- 0x01ff,0x03ff,0x07ff,0x0fff]
-
- INC_TABLE = [8,8,4,2,0]
-
- BGN_TABLE = [0,4,2,1,0]
-
- # 建立文件夹
- Dir.mkdir("GIF") unless Dir["*"].include?("GIF")
-
- # 函数定义
- module_function
-
- #--------------------------------------------------------------------------
- # ● 分解gif图片
- #--------------------------------------------------------------------------
- def analyze_gif
- @old_dir = Dir.pwd
- Dir.chdir("GIF")
- @total_gif = []
- for g in Dir["*"]
- suf = g.split(/\./)
- if suf[1].is_a?(String) and suf[1].downcase == "gif"
- @total_gif.push(g)
- Dir.mkdir(suf[0]) unless Dir["*"].include? suf[0]
- end
- end
- @total_gif.each{|file| self.readdata(file)}
- Dir.chdir(@old_dir)
- p '全部分解完毕,点击确定退出'
- exit
- end
-
- #--------------------------------------------------------------------------
- # ● 读取文件数据
- #--------------------------------------------------------------------------
- def readdata(filename)
- # 初始化数据
- self.initial_var(filename)
- # 打开文件
- begin
- @f = open(filename,"rb")
- # 读取文件头
- self.read_gifh
- # 读取逻辑屏幕描述块
- self.read_gifs
- # 读取下一个字节
- @temp = @f.read(1)[0]
- # 循环读取每个图象描述块
- while true
- if @temp == 0x2c
- # 读取图象描述块
- self.read_gifi
- end
- if @temp == 0x21
- # 读取图象扩展块
- self.read_gife
- end
- if @temp == 0x3b
- break
- end
- # 读取下一个字节
- @temp = @f.read(1)[0]
- end
- # end
- p @filename + '分解完毕...'
- ensure
- @f.close
- end
- end
-
- #--------------------------------------------------------------------------
- # ● 初始化变量
- #--------------------------------------------------------------------------
- def initial_var(filename)
- @gif_count = 0
- @f = nil
- @temp = nil
- @filename = filename.split(/\./)[0]
- @now_path = @filename + "/"
- end
-
- #--------------------------------------------------------------------------
- # ● 读取文件头
- #--------------------------------------------------------------------------
- def read_gifh
- @gifh = @f.read(SIZE_GIFH)
- if @gifh[0,3] != "GIF"
- raise "不是GIF文件!"
- end
- if @gifh[3,3] != "87a" and @gifh[3,3] != "89a"
- raise "不支持的版本!"
- end
- end
-
- #--------------------------------------------------------------------------
- # ● 读取逻辑屏幕描述块
- #--------------------------------------------------------------------------
- def read_gifs
- @gifs = @f.read(SIZE_GIFS).unpack("S2C3")
- # 获取调色板位数
- @_pal_bits = (@gifs[2] & 7) + 1
- # 是否有全局调色板
- if @gifs[2] >> 7 == 1
- # 全局调色板大小
- @g_pal_size = 3 * (1 << @_pal_bits)
- # 读取全局调色板数据
- @g_pal = @f.read(@g_pal_size).unpack("C*")
- end
- end
-
- #--------------------------------------------------------------------------
- # ● 读取图象描述块
- #--------------------------------------------------------------------------
- def read_gifi
- @gifi = @f.read(SIZE_GIFI).unpack("S4C")
- # 获取宽度和高度
- @_width = @gifi[2]
- @_height = @gifi[3]
- # 清空局部调色板
- @l_pal = nil
- # 是否有局部调色板
- if @gifi[4] >> 7 == 1
- # 获取调色板位数
- @_pal_bits = (@gifi[4] & 7) + 1
- # 局部调色板大小
- @l_pal_size = 3 * (1 << @_pal_bits)
- # 读取局部调色板数据
- @l_pal = @f.read(@l_pal_size).unpack("C*")
- end
- # 获取交错标记
- @_lace = (@gifi[4] >> 6) & 1
- # 修正调色板位数
- @_pal_bits = @_pal_bits == 1 ? 1 : (@_pal_bits <= 4 ? 4 : 8)
- # 获取行字节数
- @_width_bytes = (((@_width * @_pal_bits) + 31) >> 5) << 2
- # 读取图象压缩数据
- self.read_lzw_data
- end
-
- #--------------------------------------------------------------------------
- # ● 读取图象压缩数据
- #--------------------------------------------------------------------------
- def read_lzw_data
- # 解码用
- lzw_mincodelen = @f.read(1)[0]
- # 帧数加 1
- @gif_count += 1
- # 图象块数据
- image_data = ""
- # 块大小
- blocksize = @f.read(1)[0]
- while blocksize > 0
- image_data += @f.read(blocksize)
- blocksize = @f.read(1)[0]
- end
- # 导出图象
- self.dump_imgs(image_data,lzw_mincodelen)
- end
-
- #--------------------------------------------------------------------------
- # ● 读取扩充块
- #--------------------------------------------------------------------------
- def read_gife
- label = @f.read(1)[0]
- case label
- when 0xf9 # 图形控制扩展块
- @gifc = @f.read(SIZE_GIFC).unpack("C2SC2")
- # 获取透明颜色
- @_trans_index = nil
- if @gifc[1] & 1 > 0
- @_trans_index = @gifc[3]
- end
- when 0x01 # 图形说明扩展块
- @gifp = @f.read(SIZE_GIFP).unpack("CS4C4")
- blocksize = @f.read(1)[0]
- while blocksize > 0
- @f.read(blocksize)
- blocksize = @f.read(1)[0]
- end
- when 0xfe # 注解说明扩展块
- blocksize = @f.read(1)[0]
- while blocksize > 0
- @f.read(blocksize)
- blocksize = @f.read(1)[0]
- end
- when 0xff # 应用程序扩展块
- @gifa = @f.read(SIZE_GIFA).unpack("C*")
- blocksize = @f.read(1)[0]
- while blocksize > 0
- @f.read(blocksize)
- blocksize = @f.read(1)[0]
- end
- end
- end
-
- #--------------------------------------------------------------------------
- # ● 设置调色板
- #--------------------------------------------------------------------------
- def set_pal
- @_pal = []
- if @l_pal != nil
- @_pal = @l_pal
- elsif @g_pal != nil
- @_pal = @g_pal
- else
- for i in 0...1 << @_pal_bits
- @_pal.push i,i,i
- end
- end
- end
-
- #--------------------------------------------------------------------------
- # ● 解码图形数据
- #--------------------------------------------------------------------------
- def dump_imgs(image_data,lze_len)
- @image_data = image_data.unpack("C*")
-
- self.set_pal
-
- @png_data = []
- @stack = []
- @images = []
-
- @prefix = []
- @suffix = []
-
- @bitcount = @_pal_bits
- @widthcount = 0
-
- @left_bits = 0x00
- @current_bits = lze_len + 0x01
-
- @lzw_clear = 1 << lze_len
- @lzw_eoi = @lzw_clear + 1
- @nowtablendx = @lzw_clear + 2
- @toptablendx = 1 << @current_bits
-
- @wdata = 0
- @wcode = 0
- @oldcode = 0xffff
- @row_num = 0
- @tempchar = 0x00
- @pass = 0x00
- @firstchar = 0
- @tempndx = 0
- # 读取编码字符
- self.read_byte
- # 不是@lzw_eoi则循环
- while @wcode != @lzw_eoi
- # @lzw_clear码
- if @wcode == @lzw_clear
- for i in 0...@lzw_clear
- @prefix[i] = 0xffff
- @suffix[i] = i
- end
- for i in @nowtablendx...4096
- @prefix[i] = 0xffff
- @suffix[i] = 0x00
- end
- @current_bits = lze_len + 0x01
- @nowtablendx = @lzw_clear + 2
- @toptablendx = 1 << @current_bits
- @oldcode = 0xffff
- # 读取编码字符
- self.read_byte
- if @wcode != @lzw_eoi
- while @prefix[@wcode] != 0xffff
- @stack.push(@suffix[@wcode])
- @wcode = @prefix[@wcode]
- end
- @stack.push(@suffix[@wcode])
- @firstchar = @stack[-1]
- # 输出解码数据
- self.output_data
- end
- else
- if @wcode < @nowtablendx
- @tempndx = @wcode
- else
- @tempndx = @oldcode
- @stack.push(@firstchar)
- end
- while @prefix[@tempndx] != 0xffff
- @stack.push(@suffix[@tempndx])
- @tempndx = @prefix[@tempndx]
- end
- @stack.push(@suffix[@tempndx])
- @firstchar = @stack[-1]
- @prefix[@nowtablendx] = @oldcode
- @suffix[@nowtablendx] = @firstchar
- @nowtablendx += 1
- if @nowtablendx == @toptablendx and @current_bits < 12
- @current_bits += 1
- @toptablendx = 1 << @current_bits
- end
- # 输出解码数据
- self.output_data
- end
- @oldcode = @wcode
- # 读取编码字符
- self.read_byte
- end
- Graphics.update
- # 生成png图
- self.make_png
- end
- #--------------------------------------------------------------------------
- # ● 读取下一个字节
- #--------------------------------------------------------------------------
- def read_byte
- while @left_bits < @current_bits
- @next_char = @image_data.shift
- @wdata |= (@next_char << @left_bits)
- @left_bits += 0x08
- end
- @wcode = @wdata & CODE_MASK[@current_bits]
- @wdata >>= @current_bits
- @left_bits -= @current_bits
- end
-
- #--------------------------------------------------------------------------
- # ● 输出解码数据
- #--------------------------------------------------------------------------
- def output_data
- while [email protected]?
- @tempchar |= (@stack.pop << (8 - @bitcount))
- if @bitcount == 8
- @images.push(@tempchar)
- @tempchar = 0x00
- @bitcount = @_pal_bits
- else
- @bitcount += @_pal_bits
- end
- @widthcount += 1
- if @widthcount == @_width
- if @bitcount != @_pal_bits
- @images.push(@tempchar)
- @tempchar = 0x00
- @bitcount = @_pal_bits
- end
- @png_data[@row_num] = @images.clone
- @images.clear
- if @_lace > 0
- @row_num += INC_TABLE[@pass]
- if @row_num >= @_height
- @pass += 1
- @row_num = BGN_TABLE[@pass]
- end
- else
- @row_num += 1
- end
- @widthcount = 0
- end
- end
- end
-
- #--------------------------------------------------------------------------
- # ● 生成png图片
- #--------------------------------------------------------------------------
- def make_png
- fp = open(@now_path+@filename + sprintf("%02d",@gif_count)+".png","wb")
- fp.write(self.make_png_header)
- fp.write(self.make_png_ihdr)
- fp.write(self.make_png_plte) if @_trans_index.nil?
- fp.write(self.make_png_idat)
- fp.write(self.make_png_iend)
- fp.close
- end
-
- #--------------------------------------------------------------------------
- # ● png头文件
- #--------------------------------------------------------------------------
- def make_png_header
- return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
- end
-
- #--------------------------------------------------------------------------
- # ● png信息头块
- #--------------------------------------------------------------------------
- def make_png_ihdr
- ih_size = [13].pack("N")
- ih_sign = "IHDR"
- ih_width = [@_width].pack("N")
- ih_height = [@_height].pack("N")
- if @_trans_index != nil
- ih_bit_depth = [@_pal_bits > 8 ? 16 : 8].pack("C")
- ih_color_type = [6].pack("C")
- else
- ih_bit_depth = [@_pal_bits].pack("C")
- ih_color_type = [3].pack("C")
- end
- ih_compression_method = [0].pack("C")
- ih_filter_method = [0].pack("C")
- ih_interlace_method = [0].pack("C")
- string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
- ih_compression_method + ih_filter_method + ih_interlace_method
- ih_crc = [Zlib.crc32(string)].pack("N")
- return ih_size + string + ih_crc
- end
-
- #--------------------------------------------------------------------------
- # ● png调色板块
- #--------------------------------------------------------------------------
- def make_png_plte
- pl_size = [@_pal.size].pack("N")
- pl_sign = "PLTE"
- pl_data = @_pal.pack("C*")
- pl_crc = [Zlib.crc32(pl_sign + pl_data)].pack("N")
- return pl_size + pl_sign + pl_data + pl_crc
- end
-
- #--------------------------------------------------------------------------
- # ● png数据块
- #--------------------------------------------------------------------------
- def make_png_idat
- lz_data = []
- if @_trans_index != nil
- for i in 0...@png_data.size
- lz_data.push 0
- for j in @png_data[i]
- if j == @_trans_index
- lz_data.push @_pal[j*3],@_pal[j*3+1],@_pal[j*3+2],0
- else
- lz_data.push @_pal[j*3],@_pal[j*3+1],@_pal[j*3+2],255
- end
- end
- end
- else
- for i in 0...@png_data.size
- lz_data.push 0
- lz_data += @png_data[i]
- end
- end
- id_data = Zlib::Deflate.deflate(lz_data.pack("C*"),9)
- id_size = [id_data.size].pack("N")
- id_sign = "IDAT"
- id_crc = [Zlib.crc32(id_sign + id_data)].pack("N")
- return id_size + id_sign + id_data + id_crc
- end
-
- #--------------------------------------------------------------------------
- # ● png 结尾块
- #--------------------------------------------------------------------------
- def make_png_iend
- ie_size = [0].pack("N")
- ie_sign = "IEND"
- ie_crc = [Zlib.crc32(ie_sign)].pack("N")
- return ie_size + ie_sign + ie_crc
- end
-
- end
- GIF.analyze_gif
复制代码
[本贴由 叶舞枫 于 2007-4-25 14:18:09 进行了编辑] |
|