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

Project1

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

分解GIF图片为PNG[怨念的产物]

 关闭 [复制链接]

Lv1.梦旅人

有事烧纸

梦石
0
星屑
154
在线时间
509 小时
注册时间
2005-10-22
帖子
6982

贵宾VX城市地图大赛冠军第1届RMTV比赛冠军第1届TG大赛冠军

跳转到指定楼层
1
发表于 2006-11-23 01:03:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
分解GIFv1.0

分解GIF为PNG图片,其实也可以使RM读取GIF```

by 小夏

使用见脚本说明。


新地址

  1. =begin

  2.   脚本:【怨念产物】
  3.   
  4.   功能:分解GIF图片为PNG格式。
  5.   
  6.   说明: 直接用 GIF.analyze_gif 使用。
  7.   
  8.       把需要分解的GIF文件放在工程下的GIF文件夹下即可,运行即可,ms速度比较慢。

  9.   作者:灼眼的夏娜
  10.   
  11. =end

  12. =begin

  13.   GIF文件格式初步讲解:

  14.   1、文件头(6字节):
  15.   
  16.   2、逻辑屏幕标符(7字节) :
  17.   
  18.   3、[全局调色板数据] :根据2中的GlobalFlag确定相关属性,可无。
  19.   
  20.   4、[GIF扩充块]:各种扩充块,可无。
  21.   
  22.      [图形控制扩充块(6字节),图形说明扩充块(13+1+),注释说明扩充块(0+1+),应用程序扩充块(12+1+)]
  23.   
  24.   5、图象描述块:0x2c 开始。
  25.   
  26.   6、[局部调色板]:根据5中的LocalFlag中的LocalPal可以判断有无。
  27.   
  28.   7、图象数据
  29.   
  30.   8、7的第一个字节为LZW编码长度
  31.   
  32.   9、编码长度之后为连续的数据子块,每个数据子块长度为 0 - 256 字节。
  33.   
  34.   10、数据子块的第一个字节为该子块的长度。
  35.   
  36.   11、文件结尾:0x3b

  37. =end

  38. module GIF
  39.   
  40.   # 定义常量
  41.   SIZE_GIFH = 6
  42.   
  43.   SIZE_GIFS = 7
  44.   
  45.   SIZE_GIFI = 9
  46.   
  47.   SIZE_GIFC = 6
  48.   
  49.   SIZE_GIFP = 13
  50.   
  51.   SIZE_GIFA = 12
  52.   
  53.   CODE_MASK = [0x0000,
  54.                0x0001,0x0003,0x0007,0x000f,
  55.                0x001f,0x003f,0x007f,0x00ff,
  56.                0x01ff,0x03ff,0x07ff,0x0fff]
  57.   
  58.   INC_TABLE = [8,8,4,2,0]
  59.   
  60.   BGN_TABLE = [0,4,2,1,0]
  61.   
  62.   # 建立文件夹
  63.   Dir.mkdir("GIF") unless Dir["*"].include?("GIF")
  64.   
  65.   # 函数定义
  66.   module_function
  67.   
  68.   #--------------------------------------------------------------------------
  69.   # ● 分解gif图片
  70.   #--------------------------------------------------------------------------
  71.   def analyze_gif
  72.     @old_dir = Dir.pwd
  73.     Dir.chdir("GIF")
  74.     @total_gif = []
  75.     for g in Dir["*"]
  76.       suf = g.split(/\./)
  77.       if suf[1].is_a?(String) and suf[1].downcase == "gif"
  78.         @total_gif.push(g)
  79.         Dir.mkdir(suf[0]) unless Dir["*"].include? suf[0]
  80.       end
  81.     end
  82.     @total_gif.each{|file| self.readdata(file)}
  83.     Dir.chdir(@old_dir)
  84.     p '全部分解完毕,点击确定退出'
  85.     exit
  86.   end
  87.   
  88.   #--------------------------------------------------------------------------
  89.   # ● 读取文件数据
  90.   #--------------------------------------------------------------------------
  91.   def readdata(filename)
  92.     # 初始化数据
  93.     self.initial_var(filename)
  94.     # 打开文件
  95.     begin
  96.       @f = open(filename,"rb")
  97.       # 读取文件头
  98.       self.read_gifh
  99.       # 读取逻辑屏幕描述块
  100.       self.read_gifs
  101.       # 读取下一个字节
  102.       @temp = @f.read(1)[0]
  103.       # 循环读取每个图象描述块
  104.       while true
  105.         if @temp == 0x2c
  106.           # 读取图象描述块
  107.           self.read_gifi
  108.         end
  109.         if @temp == 0x21
  110.           # 读取图象扩展块
  111.           self.read_gife
  112.         end
  113.         if @temp == 0x3b
  114.           break
  115.         end
  116.         # 读取下一个字节
  117.         @temp = @f.read(1)[0]
  118.       end
  119.       # end
  120.       p @filename + '分解完毕...'
  121.     ensure
  122.       @f.close
  123.     end
  124.   end
  125.   
  126.   #--------------------------------------------------------------------------
  127.   # ● 初始化变量
  128.   #--------------------------------------------------------------------------
  129.   def initial_var(filename)
  130.     @gif_count = 0
  131.     @f = nil
  132.     @temp = nil
  133.     @filename = filename.split(/\./)[0]
  134.     @now_path = @filename + "/"
  135.   end
  136.   
  137.   #--------------------------------------------------------------------------
  138.   # ● 读取文件头
  139.   #--------------------------------------------------------------------------
  140.   def read_gifh
  141.     @gifh = @f.read(SIZE_GIFH)
  142.     if @gifh[0,3] != "GIF"
  143.       raise "不是GIF文件!"
  144.     end
  145.     if @gifh[3,3] != "87a" and @gifh[3,3] != "89a"
  146.       raise "不支持的版本!"
  147.     end
  148.   end
  149.   
  150.   #--------------------------------------------------------------------------
  151.   # ● 读取逻辑屏幕描述块
  152.   #--------------------------------------------------------------------------
  153.   def read_gifs
  154.     @gifs = @f.read(SIZE_GIFS).unpack("S2C3")
  155.     # 获取调色板位数
  156.     @_pal_bits = (@gifs[2] & 7) + 1
  157.     # 是否有全局调色板
  158.     if @gifs[2] >> 7 == 1
  159.       # 全局调色板大小
  160.       @g_pal_size = 3 * (1 << @_pal_bits)
  161.       # 读取全局调色板数据
  162.       @g_pal = @f.read(@g_pal_size).unpack("C*")
  163.     end
  164.   end
  165.   
  166.   #--------------------------------------------------------------------------
  167.   # ● 读取图象描述块
  168.   #--------------------------------------------------------------------------
  169.   def read_gifi
  170.     @gifi = @f.read(SIZE_GIFI).unpack("S4C")
  171.     # 获取宽度和高度
  172.     @_width = @gifi[2]
  173.     @_height = @gifi[3]
  174.     # 清空局部调色板
  175.     @l_pal = nil
  176.     # 是否有局部调色板
  177.     if @gifi[4] >> 7 == 1
  178.       # 获取调色板位数
  179.       @_pal_bits = (@gifi[4] & 7) + 1
  180.       # 局部调色板大小
  181.       @l_pal_size = 3 * (1 << @_pal_bits)
  182.       # 读取局部调色板数据
  183.       @l_pal = @f.read(@l_pal_size).unpack("C*")
  184.     end
  185.     # 获取交错标记
  186.     @_lace = (@gifi[4] >> 6) & 1
  187.     # 修正调色板位数
  188.     @_pal_bits = @_pal_bits == 1 ? 1 : (@_pal_bits <= 4 ? 4 : 8)
  189.     # 获取行字节数
  190.     @_width_bytes = (((@_width * @_pal_bits) + 31) >> 5) << 2
  191.     # 读取图象压缩数据
  192.     self.read_lzw_data
  193.   end
  194.   
  195.   #--------------------------------------------------------------------------
  196.   # ● 读取图象压缩数据
  197.   #--------------------------------------------------------------------------
  198.   def read_lzw_data
  199.     # 解码用
  200.     lzw_mincodelen = @f.read(1)[0]
  201.     # 帧数加 1
  202.     @gif_count += 1
  203.     # 图象块数据
  204.     image_data = ""
  205.     # 块大小
  206.     blocksize = @f.read(1)[0]
  207.     while blocksize > 0
  208.       image_data += @f.read(blocksize)
  209.       blocksize = @f.read(1)[0]
  210.     end
  211.     # 导出图象
  212.     self.dump_imgs(image_data,lzw_mincodelen)
  213.   end

  214.   #--------------------------------------------------------------------------
  215.   # ● 读取扩充块
  216.   #--------------------------------------------------------------------------
  217.   def read_gife
  218.     label = @f.read(1)[0]
  219.     case label
  220.     when 0xf9 # 图形控制扩展块
  221.       @gifc = @f.read(SIZE_GIFC).unpack("C2SC2")
  222.       # 获取透明颜色
  223.       @_trans_index = nil
  224.       if @gifc[1] & 1 > 0
  225.         @_trans_index = @gifc[3]
  226.       end
  227.     when 0x01 # 图形说明扩展块
  228.       @gifp = @f.read(SIZE_GIFP).unpack("CS4C4")
  229.       blocksize = @f.read(1)[0]
  230.       while blocksize > 0
  231.         @f.read(blocksize)
  232.         blocksize = @f.read(1)[0]
  233.       end
  234.     when 0xfe # 注解说明扩展块
  235.       blocksize = @f.read(1)[0]
  236.       while blocksize > 0
  237.         @f.read(blocksize)
  238.         blocksize = @f.read(1)[0]
  239.       end
  240.     when 0xff # 应用程序扩展块
  241.       @gifa = @f.read(SIZE_GIFA).unpack("C*")
  242.       blocksize = @f.read(1)[0]
  243.       while blocksize > 0
  244.         @f.read(blocksize)
  245.         blocksize = @f.read(1)[0]
  246.       end
  247.     end
  248.   end
  249.   
  250.   #--------------------------------------------------------------------------
  251.   # ● 设置调色板
  252.   #--------------------------------------------------------------------------
  253.   def set_pal
  254.     @_pal = []
  255.     if @l_pal != nil
  256.       @_pal = @l_pal
  257.     elsif @g_pal != nil
  258.       @_pal = @g_pal
  259.     else
  260.       for i in 0...1 << @_pal_bits
  261.         @_pal.push i,i,i
  262.       end
  263.     end
  264.   end
  265.   
  266.   #--------------------------------------------------------------------------
  267.   # ● 解码图形数据
  268.   #--------------------------------------------------------------------------
  269.   def dump_imgs(image_data,lze_len)
  270.     @image_data = image_data.unpack("C*")
  271.    
  272.     self.set_pal
  273.    
  274.     @png_data = []

  275.     @stack = []
  276.     @images = []
  277.    
  278.     @prefix = []
  279.     @suffix = []
  280.    
  281.     @bitcount = @_pal_bits
  282.     @widthcount = 0
  283.    
  284.     @left_bits = 0x00
  285.     @current_bits = lze_len + 0x01
  286.    
  287.     @lzw_clear = 1 << lze_len
  288.     @lzw_eoi = @lzw_clear + 1
  289.     @nowtablendx = @lzw_clear + 2
  290.     @toptablendx = 1 << @current_bits
  291.    
  292.     @wdata = 0
  293.     @wcode = 0
  294.     @oldcode = 0xffff
  295.     @row_num = 0
  296.     @tempchar = 0x00
  297.     @pass = 0x00
  298.     @firstchar = 0
  299.     @tempndx = 0
  300.     # 读取编码字符
  301.     self.read_byte
  302.     # 不是@lzw_eoi则循环
  303.     while @wcode != @lzw_eoi
  304.       # @lzw_clear码
  305.       if @wcode == @lzw_clear
  306.         for i in 0...@lzw_clear
  307.           @prefix[i] = 0xffff
  308.           @suffix[i] = i
  309.         end
  310.         for i in @nowtablendx...4096
  311.           @prefix[i] = 0xffff
  312.           @suffix[i] = 0x00
  313.         end
  314.         @current_bits = lze_len + 0x01
  315.         @nowtablendx = @lzw_clear + 2
  316.         @toptablendx = 1 << @current_bits
  317.         @oldcode = 0xffff
  318.         # 读取编码字符
  319.         self.read_byte
  320.         if @wcode != @lzw_eoi
  321.           while @prefix[@wcode] != 0xffff
  322.             @stack.push(@suffix[@wcode])
  323.             @wcode = @prefix[@wcode]
  324.           end
  325.           @stack.push(@suffix[@wcode])
  326.           @firstchar = @stack[-1]
  327.           # 输出解码数据
  328.           self.output_data
  329.         end
  330.       else
  331.         if @wcode < @nowtablendx
  332.           @tempndx = @wcode
  333.         else
  334.           @tempndx = @oldcode
  335.           @stack.push(@firstchar)
  336.         end
  337.         while @prefix[@tempndx] != 0xffff
  338.           @stack.push(@suffix[@tempndx])
  339.           @tempndx = @prefix[@tempndx]
  340.         end
  341.         @stack.push(@suffix[@tempndx])
  342.         @firstchar = @stack[-1]
  343.         @prefix[@nowtablendx] = @oldcode
  344.         @suffix[@nowtablendx] = @firstchar
  345.         @nowtablendx += 1
  346.         if @nowtablendx == @toptablendx and @current_bits < 12
  347.           @current_bits += 1
  348.           @toptablendx = 1 << @current_bits
  349.         end
  350.         # 输出解码数据
  351.         self.output_data
  352.       end
  353.       @oldcode = @wcode
  354.       # 读取编码字符
  355.       self.read_byte
  356.     end
  357.     Graphics.update
  358.     # 生成png图
  359.     self.make_png
  360.   end

  361.   #--------------------------------------------------------------------------
  362.   # ● 读取下一个字节
  363.   #--------------------------------------------------------------------------
  364.   def read_byte
  365.     while @left_bits < @current_bits
  366.       @next_char = @image_data.shift
  367.       @wdata |= (@next_char << @left_bits)
  368.       @left_bits += 0x08
  369.     end
  370.     @wcode = @wdata & CODE_MASK[@current_bits]
  371.     @wdata >>= @current_bits
  372.     @left_bits -= @current_bits
  373.   end
  374.   
  375.   #--------------------------------------------------------------------------
  376.   # ● 输出解码数据
  377.   #--------------------------------------------------------------------------
  378.   def output_data
  379.     while [email protected]?
  380.       @tempchar |= (@stack.pop << (8 - @bitcount))
  381.       if @bitcount == 8
  382.         @images.push(@tempchar)
  383.         @tempchar = 0x00
  384.         @bitcount = @_pal_bits
  385.       else
  386.         @bitcount += @_pal_bits
  387.       end
  388.       @widthcount += 1
  389.       if @widthcount == @_width
  390.         if @bitcount != @_pal_bits
  391.           @images.push(@tempchar)
  392.           @tempchar = 0x00
  393.           @bitcount = @_pal_bits
  394.         end
  395.         @png_data[@row_num] = @images.clone
  396.         @images.clear
  397.         if @_lace > 0
  398.           @row_num += INC_TABLE[@pass]
  399.           if @row_num >= @_height
  400.             @pass += 1
  401.             @row_num = BGN_TABLE[@pass]
  402.           end
  403.         else
  404.           @row_num += 1
  405.         end
  406.         @widthcount = 0
  407.       end
  408.     end
  409.   end
  410.   
  411.   #--------------------------------------------------------------------------
  412.   # ● 生成png图片
  413.   #--------------------------------------------------------------------------
  414.   def make_png
  415.     fp = open(@now_path+@filename + sprintf("%02d",@gif_count)+".png","wb")
  416.     fp.write(self.make_png_header)
  417.     fp.write(self.make_png_ihdr)
  418.     fp.write(self.make_png_plte) if @_trans_index.nil?
  419.     fp.write(self.make_png_idat)
  420.     fp.write(self.make_png_iend)
  421.     fp.close
  422.   end
  423.    
  424.   #--------------------------------------------------------------------------
  425.   # ● png头文件
  426.   #--------------------------------------------------------------------------
  427.   def make_png_header
  428.     return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
  429.   end
  430.   
  431.   #--------------------------------------------------------------------------
  432.   # ● png信息头块
  433.   #--------------------------------------------------------------------------
  434.   def make_png_ihdr
  435.     ih_size = [13].pack("N")
  436.     ih_sign = "IHDR"
  437.     ih_width = [@_width].pack("N")
  438.     ih_height = [@_height].pack("N")
  439.     if @_trans_index != nil
  440.       ih_bit_depth = [@_pal_bits > 8 ? 16 : 8].pack("C")
  441.       ih_color_type = [6].pack("C")
  442.     else
  443.       ih_bit_depth = [@_pal_bits].pack("C")
  444.       ih_color_type = [3].pack("C")
  445.     end
  446.     ih_compression_method = [0].pack("C")
  447.     ih_filter_method = [0].pack("C")
  448.     ih_interlace_method = [0].pack("C")
  449.     string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
  450.              ih_compression_method + ih_filter_method + ih_interlace_method
  451.     ih_crc = [Zlib.crc32(string)].pack("N")
  452.     return ih_size + string + ih_crc
  453.   end
  454.   
  455.   #--------------------------------------------------------------------------
  456.   # ● png调色板块
  457.   #--------------------------------------------------------------------------
  458.   def make_png_plte
  459.     pl_size = [@_pal.size].pack("N")
  460.     pl_sign = "PLTE"
  461.     pl_data = @_pal.pack("C*")
  462.     pl_crc = [Zlib.crc32(pl_sign + pl_data)].pack("N")
  463.     return pl_size + pl_sign + pl_data + pl_crc
  464.   end
  465.   
  466.   #--------------------------------------------------------------------------
  467.   # ● png数据块
  468.   #--------------------------------------------------------------------------
  469.   def make_png_idat
  470.     lz_data = []
  471.     if @_trans_index != nil
  472.       for i in 0...@png_data.size
  473.         lz_data.push 0
  474.         for j in @png_data[i]
  475.           if j == @_trans_index
  476.             lz_data.push @_pal[j*3],@_pal[j*3+1],@_pal[j*3+2],0
  477.           else
  478.             lz_data.push @_pal[j*3],@_pal[j*3+1],@_pal[j*3+2],255
  479.           end
  480.         end
  481.       end
  482.     else
  483.       for i in 0...@png_data.size
  484.         lz_data.push 0
  485.         lz_data += @png_data[i]
  486.       end
  487.     end
  488.     id_data = Zlib::Deflate.deflate(lz_data.pack("C*"),9)
  489.     id_size = [id_data.size].pack("N")
  490.     id_sign = "IDAT"
  491.     id_crc = [Zlib.crc32(id_sign + id_data)].pack("N")
  492.     return id_size + id_sign + id_data + id_crc
  493.   end
  494.   
  495.   #--------------------------------------------------------------------------
  496.   # ● png 结尾块
  497.   #--------------------------------------------------------------------------
  498.   def make_png_iend
  499.     ie_size = [0].pack("N")
  500.     ie_sign = "IEND"
  501.     ie_crc = [Zlib.crc32(ie_sign)].pack("N")
  502.     return ie_size + ie_sign + ie_crc
  503.   end
  504.   
  505. end

  506. GIF.analyze_gif

复制代码


              [本贴由 叶舞枫 于 2007-4-25 14:18:09 进行了编辑]
神隐中,偶尔诈尸

Lv1.梦旅人

有事烧纸

梦石
0
星屑
154
在线时间
509 小时
注册时间
2005-10-22
帖子
6982

贵宾VX城市地图大赛冠军第1届RMTV比赛冠军第1届TG大赛冠军

2
 楼主| 发表于 2006-11-23 01:03:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
分解GIFv1.0

分解GIF为PNG图片,其实也可以使RM读取GIF```

by 小夏

使用见脚本说明。


新地址

  1. =begin

  2.   脚本:【怨念产物】
  3.   
  4.   功能:分解GIF图片为PNG格式。
  5.   
  6.   说明: 直接用 GIF.analyze_gif 使用。
  7.   
  8.       把需要分解的GIF文件放在工程下的GIF文件夹下即可,运行即可,ms速度比较慢。

  9.   作者:灼眼的夏娜
  10.   
  11. =end

  12. =begin

  13.   GIF文件格式初步讲解:

  14.   1、文件头(6字节):
  15.   
  16.   2、逻辑屏幕标符(7字节) :
  17.   
  18.   3、[全局调色板数据] :根据2中的GlobalFlag确定相关属性,可无。
  19.   
  20.   4、[GIF扩充块]:各种扩充块,可无。
  21.   
  22.      [图形控制扩充块(6字节),图形说明扩充块(13+1+),注释说明扩充块(0+1+),应用程序扩充块(12+1+)]
  23.   
  24.   5、图象描述块:0x2c 开始。
  25.   
  26.   6、[局部调色板]:根据5中的LocalFlag中的LocalPal可以判断有无。
  27.   
  28.   7、图象数据
  29.   
  30.   8、7的第一个字节为LZW编码长度
  31.   
  32.   9、编码长度之后为连续的数据子块,每个数据子块长度为 0 - 256 字节。
  33.   
  34.   10、数据子块的第一个字节为该子块的长度。
  35.   
  36.   11、文件结尾:0x3b

  37. =end

  38. module GIF
  39.   
  40.   # 定义常量
  41.   SIZE_GIFH = 6
  42.   
  43.   SIZE_GIFS = 7
  44.   
  45.   SIZE_GIFI = 9
  46.   
  47.   SIZE_GIFC = 6
  48.   
  49.   SIZE_GIFP = 13
  50.   
  51.   SIZE_GIFA = 12
  52.   
  53.   CODE_MASK = [0x0000,
  54.                0x0001,0x0003,0x0007,0x000f,
  55.                0x001f,0x003f,0x007f,0x00ff,
  56.                0x01ff,0x03ff,0x07ff,0x0fff]
  57.   
  58.   INC_TABLE = [8,8,4,2,0]
  59.   
  60.   BGN_TABLE = [0,4,2,1,0]
  61.   
  62.   # 建立文件夹
  63.   Dir.mkdir("GIF") unless Dir["*"].include?("GIF")
  64.   
  65.   # 函数定义
  66.   module_function
  67.   
  68.   #--------------------------------------------------------------------------
  69.   # ● 分解gif图片
  70.   #--------------------------------------------------------------------------
  71.   def analyze_gif
  72.     @old_dir = Dir.pwd
  73.     Dir.chdir("GIF")
  74.     @total_gif = []
  75.     for g in Dir["*"]
  76.       suf = g.split(/\./)
  77.       if suf[1].is_a?(String) and suf[1].downcase == "gif"
  78.         @total_gif.push(g)
  79.         Dir.mkdir(suf[0]) unless Dir["*"].include? suf[0]
  80.       end
  81.     end
  82.     @total_gif.each{|file| self.readdata(file)}
  83.     Dir.chdir(@old_dir)
  84.     p '全部分解完毕,点击确定退出'
  85.     exit
  86.   end
  87.   
  88.   #--------------------------------------------------------------------------
  89.   # ● 读取文件数据
  90.   #--------------------------------------------------------------------------
  91.   def readdata(filename)
  92.     # 初始化数据
  93.     self.initial_var(filename)
  94.     # 打开文件
  95.     begin
  96.       @f = open(filename,"rb")
  97.       # 读取文件头
  98.       self.read_gifh
  99.       # 读取逻辑屏幕描述块
  100.       self.read_gifs
  101.       # 读取下一个字节
  102.       @temp = @f.read(1)[0]
  103.       # 循环读取每个图象描述块
  104.       while true
  105.         if @temp == 0x2c
  106.           # 读取图象描述块
  107.           self.read_gifi
  108.         end
  109.         if @temp == 0x21
  110.           # 读取图象扩展块
  111.           self.read_gife
  112.         end
  113.         if @temp == 0x3b
  114.           break
  115.         end
  116.         # 读取下一个字节
  117.         @temp = @f.read(1)[0]
  118.       end
  119.       # end
  120.       p @filename + '分解完毕...'
  121.     ensure
  122.       @f.close
  123.     end
  124.   end
  125.   
  126.   #--------------------------------------------------------------------------
  127.   # ● 初始化变量
  128.   #--------------------------------------------------------------------------
  129.   def initial_var(filename)
  130.     @gif_count = 0
  131.     @f = nil
  132.     @temp = nil
  133.     @filename = filename.split(/\./)[0]
  134.     @now_path = @filename + "/"
  135.   end
  136.   
  137.   #--------------------------------------------------------------------------
  138.   # ● 读取文件头
  139.   #--------------------------------------------------------------------------
  140.   def read_gifh
  141.     @gifh = @f.read(SIZE_GIFH)
  142.     if @gifh[0,3] != "GIF"
  143.       raise "不是GIF文件!"
  144.     end
  145.     if @gifh[3,3] != "87a" and @gifh[3,3] != "89a"
  146.       raise "不支持的版本!"
  147.     end
  148.   end
  149.   
  150.   #--------------------------------------------------------------------------
  151.   # ● 读取逻辑屏幕描述块
  152.   #--------------------------------------------------------------------------
  153.   def read_gifs
  154.     @gifs = @f.read(SIZE_GIFS).unpack("S2C3")
  155.     # 获取调色板位数
  156.     @_pal_bits = (@gifs[2] & 7) + 1
  157.     # 是否有全局调色板
  158.     if @gifs[2] >> 7 == 1
  159.       # 全局调色板大小
  160.       @g_pal_size = 3 * (1 << @_pal_bits)
  161.       # 读取全局调色板数据
  162.       @g_pal = @f.read(@g_pal_size).unpack("C*")
  163.     end
  164.   end
  165.   
  166.   #--------------------------------------------------------------------------
  167.   # ● 读取图象描述块
  168.   #--------------------------------------------------------------------------
  169.   def read_gifi
  170.     @gifi = @f.read(SIZE_GIFI).unpack("S4C")
  171.     # 获取宽度和高度
  172.     @_width = @gifi[2]
  173.     @_height = @gifi[3]
  174.     # 清空局部调色板
  175.     @l_pal = nil
  176.     # 是否有局部调色板
  177.     if @gifi[4] >> 7 == 1
  178.       # 获取调色板位数
  179.       @_pal_bits = (@gifi[4] & 7) + 1
  180.       # 局部调色板大小
  181.       @l_pal_size = 3 * (1 << @_pal_bits)
  182.       # 读取局部调色板数据
  183.       @l_pal = @f.read(@l_pal_size).unpack("C*")
  184.     end
  185.     # 获取交错标记
  186.     @_lace = (@gifi[4] >> 6) & 1
  187.     # 修正调色板位数
  188.     @_pal_bits = @_pal_bits == 1 ? 1 : (@_pal_bits <= 4 ? 4 : 8)
  189.     # 获取行字节数
  190.     @_width_bytes = (((@_width * @_pal_bits) + 31) >> 5) << 2
  191.     # 读取图象压缩数据
  192.     self.read_lzw_data
  193.   end
  194.   
  195.   #--------------------------------------------------------------------------
  196.   # ● 读取图象压缩数据
  197.   #--------------------------------------------------------------------------
  198.   def read_lzw_data
  199.     # 解码用
  200.     lzw_mincodelen = @f.read(1)[0]
  201.     # 帧数加 1
  202.     @gif_count += 1
  203.     # 图象块数据
  204.     image_data = ""
  205.     # 块大小
  206.     blocksize = @f.read(1)[0]
  207.     while blocksize > 0
  208.       image_data += @f.read(blocksize)
  209.       blocksize = @f.read(1)[0]
  210.     end
  211.     # 导出图象
  212.     self.dump_imgs(image_data,lzw_mincodelen)
  213.   end

  214.   #--------------------------------------------------------------------------
  215.   # ● 读取扩充块
  216.   #--------------------------------------------------------------------------
  217.   def read_gife
  218.     label = @f.read(1)[0]
  219.     case label
  220.     when 0xf9 # 图形控制扩展块
  221.       @gifc = @f.read(SIZE_GIFC).unpack("C2SC2")
  222.       # 获取透明颜色
  223.       @_trans_index = nil
  224.       if @gifc[1] & 1 > 0
  225.         @_trans_index = @gifc[3]
  226.       end
  227.     when 0x01 # 图形说明扩展块
  228.       @gifp = @f.read(SIZE_GIFP).unpack("CS4C4")
  229.       blocksize = @f.read(1)[0]
  230.       while blocksize > 0
  231.         @f.read(blocksize)
  232.         blocksize = @f.read(1)[0]
  233.       end
  234.     when 0xfe # 注解说明扩展块
  235.       blocksize = @f.read(1)[0]
  236.       while blocksize > 0
  237.         @f.read(blocksize)
  238.         blocksize = @f.read(1)[0]
  239.       end
  240.     when 0xff # 应用程序扩展块
  241.       @gifa = @f.read(SIZE_GIFA).unpack("C*")
  242.       blocksize = @f.read(1)[0]
  243.       while blocksize > 0
  244.         @f.read(blocksize)
  245.         blocksize = @f.read(1)[0]
  246.       end
  247.     end
  248.   end
  249.   
  250.   #--------------------------------------------------------------------------
  251.   # ● 设置调色板
  252.   #--------------------------------------------------------------------------
  253.   def set_pal
  254.     @_pal = []
  255.     if @l_pal != nil
  256.       @_pal = @l_pal
  257.     elsif @g_pal != nil
  258.       @_pal = @g_pal
  259.     else
  260.       for i in 0...1 << @_pal_bits
  261.         @_pal.push i,i,i
  262.       end
  263.     end
  264.   end
  265.   
  266.   #--------------------------------------------------------------------------
  267.   # ● 解码图形数据
  268.   #--------------------------------------------------------------------------
  269.   def dump_imgs(image_data,lze_len)
  270.     @image_data = image_data.unpack("C*")
  271.    
  272.     self.set_pal
  273.    
  274.     @png_data = []

  275.     @stack = []
  276.     @images = []
  277.    
  278.     @prefix = []
  279.     @suffix = []
  280.    
  281.     @bitcount = @_pal_bits
  282.     @widthcount = 0
  283.    
  284.     @left_bits = 0x00
  285.     @current_bits = lze_len + 0x01
  286.    
  287.     @lzw_clear = 1 << lze_len
  288.     @lzw_eoi = @lzw_clear + 1
  289.     @nowtablendx = @lzw_clear + 2
  290.     @toptablendx = 1 << @current_bits
  291.    
  292.     @wdata = 0
  293.     @wcode = 0
  294.     @oldcode = 0xffff
  295.     @row_num = 0
  296.     @tempchar = 0x00
  297.     @pass = 0x00
  298.     @firstchar = 0
  299.     @tempndx = 0
  300.     # 读取编码字符
  301.     self.read_byte
  302.     # 不是@lzw_eoi则循环
  303.     while @wcode != @lzw_eoi
  304.       # @lzw_clear码
  305.       if @wcode == @lzw_clear
  306.         for i in 0...@lzw_clear
  307.           @prefix[i] = 0xffff
  308.           @suffix[i] = i
  309.         end
  310.         for i in @nowtablendx...4096
  311.           @prefix[i] = 0xffff
  312.           @suffix[i] = 0x00
  313.         end
  314.         @current_bits = lze_len + 0x01
  315.         @nowtablendx = @lzw_clear + 2
  316.         @toptablendx = 1 << @current_bits
  317.         @oldcode = 0xffff
  318.         # 读取编码字符
  319.         self.read_byte
  320.         if @wcode != @lzw_eoi
  321.           while @prefix[@wcode] != 0xffff
  322.             @stack.push(@suffix[@wcode])
  323.             @wcode = @prefix[@wcode]
  324.           end
  325.           @stack.push(@suffix[@wcode])
  326.           @firstchar = @stack[-1]
  327.           # 输出解码数据
  328.           self.output_data
  329.         end
  330.       else
  331.         if @wcode < @nowtablendx
  332.           @tempndx = @wcode
  333.         else
  334.           @tempndx = @oldcode
  335.           @stack.push(@firstchar)
  336.         end
  337.         while @prefix[@tempndx] != 0xffff
  338.           @stack.push(@suffix[@tempndx])
  339.           @tempndx = @prefix[@tempndx]
  340.         end
  341.         @stack.push(@suffix[@tempndx])
  342.         @firstchar = @stack[-1]
  343.         @prefix[@nowtablendx] = @oldcode
  344.         @suffix[@nowtablendx] = @firstchar
  345.         @nowtablendx += 1
  346.         if @nowtablendx == @toptablendx and @current_bits < 12
  347.           @current_bits += 1
  348.           @toptablendx = 1 << @current_bits
  349.         end
  350.         # 输出解码数据
  351.         self.output_data
  352.       end
  353.       @oldcode = @wcode
  354.       # 读取编码字符
  355.       self.read_byte
  356.     end
  357.     Graphics.update
  358.     # 生成png图
  359.     self.make_png
  360.   end

  361.   #--------------------------------------------------------------------------
  362.   # ● 读取下一个字节
  363.   #--------------------------------------------------------------------------
  364.   def read_byte
  365.     while @left_bits < @current_bits
  366.       @next_char = @image_data.shift
  367.       @wdata |= (@next_char << @left_bits)
  368.       @left_bits += 0x08
  369.     end
  370.     @wcode = @wdata & CODE_MASK[@current_bits]
  371.     @wdata >>= @current_bits
  372.     @left_bits -= @current_bits
  373.   end
  374.   
  375.   #--------------------------------------------------------------------------
  376.   # ● 输出解码数据
  377.   #--------------------------------------------------------------------------
  378.   def output_data
  379.     while [email protected]?
  380.       @tempchar |= (@stack.pop << (8 - @bitcount))
  381.       if @bitcount == 8
  382.         @images.push(@tempchar)
  383.         @tempchar = 0x00
  384.         @bitcount = @_pal_bits
  385.       else
  386.         @bitcount += @_pal_bits
  387.       end
  388.       @widthcount += 1
  389.       if @widthcount == @_width
  390.         if @bitcount != @_pal_bits
  391.           @images.push(@tempchar)
  392.           @tempchar = 0x00
  393.           @bitcount = @_pal_bits
  394.         end
  395.         @png_data[@row_num] = @images.clone
  396.         @images.clear
  397.         if @_lace > 0
  398.           @row_num += INC_TABLE[@pass]
  399.           if @row_num >= @_height
  400.             @pass += 1
  401.             @row_num = BGN_TABLE[@pass]
  402.           end
  403.         else
  404.           @row_num += 1
  405.         end
  406.         @widthcount = 0
  407.       end
  408.     end
  409.   end
  410.   
  411.   #--------------------------------------------------------------------------
  412.   # ● 生成png图片
  413.   #--------------------------------------------------------------------------
  414.   def make_png
  415.     fp = open(@now_path+@filename + sprintf("%02d",@gif_count)+".png","wb")
  416.     fp.write(self.make_png_header)
  417.     fp.write(self.make_png_ihdr)
  418.     fp.write(self.make_png_plte) if @_trans_index.nil?
  419.     fp.write(self.make_png_idat)
  420.     fp.write(self.make_png_iend)
  421.     fp.close
  422.   end
  423.    
  424.   #--------------------------------------------------------------------------
  425.   # ● png头文件
  426.   #--------------------------------------------------------------------------
  427.   def make_png_header
  428.     return [0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a].pack("C*")
  429.   end
  430.   
  431.   #--------------------------------------------------------------------------
  432.   # ● png信息头块
  433.   #--------------------------------------------------------------------------
  434.   def make_png_ihdr
  435.     ih_size = [13].pack("N")
  436.     ih_sign = "IHDR"
  437.     ih_width = [@_width].pack("N")
  438.     ih_height = [@_height].pack("N")
  439.     if @_trans_index != nil
  440.       ih_bit_depth = [@_pal_bits > 8 ? 16 : 8].pack("C")
  441.       ih_color_type = [6].pack("C")
  442.     else
  443.       ih_bit_depth = [@_pal_bits].pack("C")
  444.       ih_color_type = [3].pack("C")
  445.     end
  446.     ih_compression_method = [0].pack("C")
  447.     ih_filter_method = [0].pack("C")
  448.     ih_interlace_method = [0].pack("C")
  449.     string = ih_sign + ih_width + ih_height + ih_bit_depth + ih_color_type +
  450.              ih_compression_method + ih_filter_method + ih_interlace_method
  451.     ih_crc = [Zlib.crc32(string)].pack("N")
  452.     return ih_size + string + ih_crc
  453.   end
  454.   
  455.   #--------------------------------------------------------------------------
  456.   # ● png调色板块
  457.   #--------------------------------------------------------------------------
  458.   def make_png_plte
  459.     pl_size = [@_pal.size].pack("N")
  460.     pl_sign = "PLTE"
  461.     pl_data = @_pal.pack("C*")
  462.     pl_crc = [Zlib.crc32(pl_sign + pl_data)].pack("N")
  463.     return pl_size + pl_sign + pl_data + pl_crc
  464.   end
  465.   
  466.   #--------------------------------------------------------------------------
  467.   # ● png数据块
  468.   #--------------------------------------------------------------------------
  469.   def make_png_idat
  470.     lz_data = []
  471.     if @_trans_index != nil
  472.       for i in 0...@png_data.size
  473.         lz_data.push 0
  474.         for j in @png_data[i]
  475.           if j == @_trans_index
  476.             lz_data.push @_pal[j*3],@_pal[j*3+1],@_pal[j*3+2],0
  477.           else
  478.             lz_data.push @_pal[j*3],@_pal[j*3+1],@_pal[j*3+2],255
  479.           end
  480.         end
  481.       end
  482.     else
  483.       for i in 0...@png_data.size
  484.         lz_data.push 0
  485.         lz_data += @png_data[i]
  486.       end
  487.     end
  488.     id_data = Zlib::Deflate.deflate(lz_data.pack("C*"),9)
  489.     id_size = [id_data.size].pack("N")
  490.     id_sign = "IDAT"
  491.     id_crc = [Zlib.crc32(id_sign + id_data)].pack("N")
  492.     return id_size + id_sign + id_data + id_crc
  493.   end
  494.   
  495.   #--------------------------------------------------------------------------
  496.   # ● png 结尾块
  497.   #--------------------------------------------------------------------------
  498.   def make_png_iend
  499.     ie_size = [0].pack("N")
  500.     ie_sign = "IEND"
  501.     ie_crc = [Zlib.crc32(ie_sign)].pack("N")
  502.     return ie_size + ie_sign + ie_crc
  503.   end
  504.   
  505. end

  506. GIF.analyze_gif

复制代码


              [本贴由 叶舞枫 于 2007-4-25 14:18:09 进行了编辑]
神隐中,偶尔诈尸
头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2006-11-21
帖子
240
3
发表于 2006-11-23 01:18:14 | 只看该作者
膜拜夏娜

把夏娜当成偶像{/ll}
签名被屏蔽
回复 支持 反对

使用道具 举报

头像被屏蔽

Lv1.梦旅人 (禁止发言)

梦石
0
星屑
50
在线时间
0 小时
注册时间
2006-11-21
帖子
240
4
发表于 2006-11-23 01:33:08 | 只看该作者
恩,碎片问题好像很严重啊
比如22.gif这个
两张图片加起来6.34k
但一个一个文件夹就占了17.8k空间
那个kaws的,文件总大小495k,占用空间704k,文件夹大小794k,占用空间0.98m
签名被屏蔽
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
71
在线时间
4 小时
注册时间
2006-9-28
帖子
208
5
发表于 2006-11-23 01:36:24 | 只看该作者
{/gg}牛X..高人
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
1 小时
注册时间
2006-8-9
帖子
510
6
发表于 2006-11-23 01:48:06 | 只看该作者
哇......太强悍了
回复 支持 反对

使用道具 举报

Lv1.梦旅人

海 关

梦石
0
星屑
50
在线时间
431 小时
注册时间
2006-1-1
帖子
460
7
发表于 2006-11-23 02:02:53 | 只看该作者
真正的好东西
回复 支持 反对

使用道具 举报

Lv1.梦旅人

有事烧纸

梦石
0
星屑
154
在线时间
509 小时
注册时间
2005-10-22
帖子
6982

贵宾VX城市地图大赛冠军第1届RMTV比赛冠军第1届TG大赛冠军

8
 楼主| 发表于 2006-11-23 02:05:58 | 只看该作者
``` ms 很多地方都还需要改进呢  `` orz....
神隐中,偶尔诈尸
回复 支持 反对

使用道具 举报

Lv1.梦旅人

月下可怜人

梦石
0
星屑
50
在线时间
10 小时
注册时间
2005-11-23
帖子
4085

第1届短篇游戏比赛亚军

9
发表于 2006-11-23 02:21:53 | 只看该作者
orz......不过不会真要拿这个东西对GIF拆侦吧
纵然千里外,我等雁归来。
回复 支持 反对

使用道具 举报

Lv1.梦旅人

逃兵

10
发表于 2006-11-23 03:18:34 | 只看该作者
偶像啊!
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-5-15 16:28

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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