simple_gif 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/simple_gif/size.rb +107 -0
- 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: []
|