simple_gif 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/lib/simple_gif/size.rb +107 -0
  3. metadata +44 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b9f4059ff0fefe827c694a8eb16268e3c64b20f1
4
+ data.tar.gz: 3706bd0d9fafb8fe1e332090821b25249ddf5b80
5
+ SHA512:
6
+ metadata.gz: 7566aade650d0d6b04d71cdad549fa7b34af5f179702ae2d3a0b8e6dda2f4f7db621acbec0f168edea77bede7ae76a8dd842bbfe540bb746ffd855d9a01979f4
7
+ data.tar.gz: 75f3a78957bbf7112d67c7ffe2e4c068eee5e6dbfdc2b401741925d8277e3ace3ad7b45cf016febe148629865c766436ece78d2f73bc49d65a16865e309ad09b
@@ -0,0 +1,107 @@
1
+ # TODO
2
+ # do not store first frame -- use background color
3
+ # this would help with add[diff:...] for the first frame
4
+
5
+ def writeGIF **_kwargs
6
+ kwargs = {filename: "temp.gif", background: [255,255,255]}.merge _kwargs
7
+ file = File.open kwargs[:filename], "wb:ASCII-8BIT"
8
+
9
+ current = history = width = height = nil
10
+ yield lambda{ |frame|
11
+ width, height = frame.is_a?(Array) ? [frame.first.size, frame.size] : [kwargs[:width], kwargs[:height]]
12
+ history, current = [], Array.new(width * height, kwargs[:background]) unless history
13
+ step = {}
14
+ if frame.is_a? Array
15
+ current = frame.flatten(1).zip(current).map.with_index{ |(color, cur), i|
16
+ step[i] = color if cur != color
17
+ color
18
+ }
19
+ else
20
+ for (i, j), color in frame
21
+ k = i * width + j
22
+ step[k] = current[k] = color if current[k] != color
23
+ end
24
+ end
25
+ history << step unless step.empty?
26
+ # p history.size
27
+ }
28
+ ensure
29
+ file.write "GIF89a"
30
+
31
+ # Logical Screen Descriptor
32
+ file.write [width, height].pack "SS"
33
+ file.write "\xF7\x00\x00"
34
+
35
+ # Global Color Table
36
+ color_table = history.flat_map(&:values).uniq
37
+ raise "sorry, can't have more than 255 colors" if color_table.size > 255
38
+ color_table[255] = [([*0..255].reverse - color_table.map(&:first))[0]] * 3
39
+ color_table.each{ |i| file.write (i || [255,255,255]).pack "CCC" }
40
+
41
+ # Comment Extension block
42
+ file.write "\x21\xFE\x1F"
43
+ file.write "SimpleGIF (c) Nakilon@gmail.com"
44
+ file.write "\x00"
45
+
46
+ # Application Extension block
47
+ file.write "\x21\xFF\x0B"
48
+ file.write "NETSCAPE2.0"
49
+ file.write "\x03\x01\x00\x00\x00"
50
+
51
+ for step in history#.drop 1
52
+
53
+ ### Graphic Control Extension
54
+ file.write "\x21\xF9\x04\x01"
55
+ file.write [100/(kwargs[:fps] || 2)].pack "S"
56
+ file.write "\xFF\x00"
57
+
58
+ left, right = step.map{ |k,| k % width }.minmax
59
+ top, bottom = step.map{ |k,| k / width }.minmax
60
+
61
+ # Image Descriptor
62
+ file.write "\x2C"
63
+ file.write [left, top, right-left+1, bottom-top+1].pack "S*"
64
+ file.write "\x00"
65
+
66
+ # Image Data
67
+ file.write "\x08"
68
+
69
+ indices = Array.new((right-left+1) * (bottom-top+1), 255)
70
+ step.each{ |k,v| indices[
71
+ k - width*top - left - \
72
+ (left + width - right - 1)*(k/width - top)
73
+ ] = color_table.index v }
74
+
75
+ result = []
76
+ table = (0..257).zip
77
+ tree = (0..257).map{[]}
78
+ s = []
79
+ indices.zip do |b| sb = s + b
80
+ next s = sb if sb.inject(tree){ |t,i| t && t[i] }
81
+ result << [table.index(s), (table.size - 1).to_s(2).size]
82
+ table << sb
83
+ sb.inject(tree){ |i,j| i[j] ||= [] }
84
+ s = b
85
+ end
86
+ x = [[256, 9], *result, table.index(s), 257].
87
+ map{ |i, bs| "%0#{bs || result.last.last}b" % i }.
88
+ reverse.join.reverse.
89
+ scan(/.{1,8}/).map{ |i| i.reverse.to_i 2 }
90
+
91
+ begin
92
+ chunk = x[0,255]
93
+ file.write [chunk.size, *chunk].pack "C*"
94
+ end while x = x[255..-1]
95
+
96
+ file.write "\x00"
97
+
98
+ end
99
+
100
+ file.write "\x3B"
101
+ file.close
102
+
103
+ `open -a "/Applications/Google Chrome.app" '#{kwargs[:filename]}'` \
104
+ if kwargs[:open]
105
+ end
106
+
107
+ require_relative(ARGV[0] || "../../examples/life.rb") if $0 == __FILE__
metadata ADDED
@@ -0,0 +1,44 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_gif
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Victor Maslov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-12 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: This is uploaded only for personal usage yet.
14
+ email: nakilon@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - lib/simple_gif/size.rb
20
+ homepage: http://rubygems.org/gems/simple_gif
21
+ licenses:
22
+ - MIT
23
+ metadata: {}
24
+ post_install_message:
25
+ rdoc_options: []
26
+ require_paths:
27
+ - lib
28
+ required_ruby_version: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirements: []
39
+ rubyforge_project:
40
+ rubygems_version: 2.0.14
41
+ signing_key:
42
+ specification_version: 4
43
+ summary: A simple GIF renderer.
44
+ test_files: []