spittle 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +12 -0
- data/README +19 -0
- data/Rakefile +45 -0
- data/VERSION +1 -0
- data/bin/spittle +15 -0
- data/examples/sprites/README +5 -0
- data/examples/sprites/apple/apple.png +0 -0
- data/examples/sprites/apple/divider.png +0 -0
- data/examples/sprites/apple/downloads.png +0 -0
- data/examples/sprites/apple/fragment.css +63 -0
- data/examples/sprites/apple/iphone.png +0 -0
- data/examples/sprites/apple/itunes.png +0 -0
- data/examples/sprites/apple/mac.png +0 -0
- data/examples/sprites/apple/search.png +0 -0
- data/examples/sprites/apple/sprite.png +0 -0
- data/examples/sprites/apple/store.png +0 -0
- data/examples/sprites/apple/support.png +0 -0
- data/examples/sprites/fragment.css +0 -0
- data/examples/sprites/index.html +33 -0
- data/examples/sprites/server.rb +10 -0
- data/examples/sprites/sprite.css +91 -0
- data/examples/sprites/words/fragment.css +28 -0
- data/examples/sprites/words/latitude.png +0 -0
- data/examples/sprites/words/of.png +0 -0
- data/examples/sprites/words/set.png +0 -0
- data/examples/sprites/words/specified.png +0 -0
- data/examples/sprites/words/sprite.css +24 -0
- data/examples/sprites/words/sprite.png +0 -0
- data/lib/spittle/chunk.rb +12 -0
- data/lib/spittle/directory_spriter.rb +63 -0
- data/lib/spittle/file_header.rb +7 -0
- data/lib/spittle/filters.rb +64 -0
- data/lib/spittle/idat.rb +26 -0
- data/lib/spittle/iend.rb +9 -0
- data/lib/spittle/ihdr.rb +30 -0
- data/lib/spittle/image.rb +114 -0
- data/lib/spittle/parser.rb +54 -0
- data/lib/spittle/processor.rb +28 -0
- data/lib/spittle/sprite.rb +39 -0
- data/lib/spittle/stylesheet_builder.rb +22 -0
- data/lib/spittle.rb +16 -0
- data/spec/builders/image_builder.rb +22 -0
- data/spec/css_fragments/deep/style/fragment.css +1 -0
- data/spec/css_fragments/some/fragment.css +1 -0
- data/spec/expected_output/merge_right_test.png +0 -0
- data/spec/expected_output/write_test.png +0 -0
- data/spec/images/lightening.png +0 -0
- data/spec/integration_spec.rb +134 -0
- data/spec/lib/file_header_spec.rb +10 -0
- data/spec/lib/idat_spec.rb +30 -0
- data/spec/lib/ihdr_spec.rb +43 -0
- data/spec/lib/image_spec.rb +19 -0
- data/spec/lib/parser_spec.rb +12 -0
- data/spec/lib/sprite_spec.rb +36 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/sprite_dirs/words/latitude.png +0 -0
- data/spec/sprite_dirs/words/of.png +0 -0
- data/spec/sprite_dirs/words/set.png +0 -0
- data/spec/sprite_dirs/words/specified.png +0 -0
- data/spec/tmp/merge_right_test.png +0 -0
- data/spec/tmp/write_test.png +0 -0
- metadata +137 -0
data/.gitignore
ADDED
data/README
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
[ PNG, PNG, PNG ] (°_°)
|
2
|
+
[ PNG, PNG, PNG ] (° )
|
3
|
+
[ PNG, PNG, PNG ] )°)
|
4
|
+
[ PNG, PNG, )°)
|
5
|
+
[ PNG, )°)
|
6
|
+
[ )°)
|
7
|
+
|
8
|
+
\(°_°)/ -> SPRITES!!!
|
9
|
+
|
10
|
+
|
11
|
+
It takes your PNG's, chews them up and spits out sprites!
|
12
|
+
|
13
|
+
point bin/spittle at a directory, and watch it sprite away!
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
currently only supports images of the same height - this will change soon.
|
18
|
+
|
19
|
+
thx to tjennings for the initial spike and help
|
data/Rakefile
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "spittle"
|
8
|
+
gem.summary = %Q{pure ruby PNG}
|
9
|
+
gem.description = %Q{pure ruby PNG}
|
10
|
+
gem.email = ["qzzzq1@gmail.com", "tyler.jennings@gmail.com"]
|
11
|
+
gem.homepage = "http://github.com/aberant/spittle"
|
12
|
+
gem.authors = ["aberant", "tjennings"]
|
13
|
+
gem.add_development_dependency "rspec" #, ">= 1.2.9"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'spec/rake/spectask'
|
22
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
23
|
+
spec.libs << 'lib' << 'spec'
|
24
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
26
|
+
|
27
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
30
|
+
spec.rcov = true
|
31
|
+
end
|
32
|
+
|
33
|
+
task :spec #=> :check_dependencies
|
34
|
+
|
35
|
+
task :default => :spec
|
36
|
+
|
37
|
+
require 'rake/rdoctask'
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
+
|
41
|
+
rdoc.rdoc_dir = 'rdoc'
|
42
|
+
rdoc.title = "spittle #{version}"
|
43
|
+
rdoc.rdoc_files.include('README*')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.0
|
data/bin/spittle
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/../lib/spittle.rb"
|
4
|
+
|
5
|
+
dir = ARGV[0]
|
6
|
+
|
7
|
+
if dir
|
8
|
+
Spittle::Processor.new(:source => dir).write
|
9
|
+
else
|
10
|
+
puts
|
11
|
+
puts "spittle! it chews up your PNG's and spits out sprites!"
|
12
|
+
puts "useage: spittle DIRECTORY"
|
13
|
+
puts "eg. spittle my_images"
|
14
|
+
puts
|
15
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
The sprites here are pre generated. If you want to see it work yourself delete the the two sprite.png files and all the *.css. Then simply run '../bin/spittle' and it should regenreate the sprites.
|
2
|
+
|
3
|
+
The server script will start a WEBrick server on port 3000 and serve from this directory. If everything worked out you should see the two sprite samples displayed in index.html.
|
4
|
+
|
5
|
+
.
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,63 @@
|
|
1
|
+
.apple_itunes {
|
2
|
+
background: transparent url(/apple/sprite.png) -350px 0px no-repeat;
|
3
|
+
width:116;
|
4
|
+
height:38;
|
5
|
+
text-indent:-5000px;
|
6
|
+
}
|
7
|
+
|
8
|
+
.apple_mac {
|
9
|
+
background: transparent url(/apple/sprite.png) -466px 0px no-repeat;
|
10
|
+
width:116;
|
11
|
+
height:38;
|
12
|
+
text-indent:-5000px;
|
13
|
+
}
|
14
|
+
|
15
|
+
.apple_apple {
|
16
|
+
background: transparent url(/apple/sprite.png) 0px 0px no-repeat;
|
17
|
+
width:117;
|
18
|
+
height:38;
|
19
|
+
text-indent:-5000px;
|
20
|
+
}
|
21
|
+
|
22
|
+
.apple_store {
|
23
|
+
background: transparent url(/apple/sprite.png) -744px 0px no-repeat;
|
24
|
+
width:116;
|
25
|
+
height:38;
|
26
|
+
text-indent:-5000px;
|
27
|
+
}
|
28
|
+
|
29
|
+
.apple_search {
|
30
|
+
background: transparent url(/apple/sprite.png) -582px 0px no-repeat;
|
31
|
+
width:162;
|
32
|
+
height:38;
|
33
|
+
text-indent:-5000px;
|
34
|
+
}
|
35
|
+
|
36
|
+
.apple_divider {
|
37
|
+
background: transparent url(/apple/sprite.png) -117px 0px no-repeat;
|
38
|
+
width:1;
|
39
|
+
height:38;
|
40
|
+
text-indent:-5000px;
|
41
|
+
}
|
42
|
+
|
43
|
+
.apple_support {
|
44
|
+
background: transparent url(/apple/sprite.png) -860px 0px no-repeat;
|
45
|
+
width:116;
|
46
|
+
height:38;
|
47
|
+
text-indent:-5000px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.apple_downloads {
|
51
|
+
background: transparent url(/apple/sprite.png) -118px 0px no-repeat;
|
52
|
+
width:116;
|
53
|
+
height:38;
|
54
|
+
text-indent:-5000px;
|
55
|
+
}
|
56
|
+
|
57
|
+
.apple_iphone {
|
58
|
+
background: transparent url(/apple/sprite.png) -234px 0px no-repeat;
|
59
|
+
width:116;
|
60
|
+
height:38;
|
61
|
+
text-indent:-5000px;
|
62
|
+
}
|
63
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>A simple sprite test</title>
|
4
|
+
<link href="/sprite.css" type="text/css" rel="stylesheet" />
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<style>
|
8
|
+
.float_left {float:left}
|
9
|
+
.menu {height: 100px}
|
10
|
+
</style>
|
11
|
+
Hello. See spittle run:
|
12
|
+
<div class="words_of">of</div>
|
13
|
+
<div class="words_latitude">latitude</div>
|
14
|
+
<div class="words_set">set</div>
|
15
|
+
|
16
|
+
Some random menu bar
|
17
|
+
<div>
|
18
|
+
<span class="menu float_left apple_apple">apple</span>
|
19
|
+
<span class="menu float_left apple_divider"></span>
|
20
|
+
<span class="menu float_left apple_store">store</span>
|
21
|
+
<span class="menu float_left apple_divider"></span>
|
22
|
+
<span class="menu float_left apple_itunes">ipod</span>
|
23
|
+
<span class="menu float_left apple_divider"></span>
|
24
|
+
<span class="menu float_left apple_iphone">iphone</span>
|
25
|
+
<span class="menu float_left apple_divider"></span>
|
26
|
+
<span class="menu float_left apple_downloads">downloads</span>
|
27
|
+
<span class="menu float_left apple_divider"></span>
|
28
|
+
<span class="menu float_left apple_support">suport</span>
|
29
|
+
<span class="menu float_left apple_divider"></span>
|
30
|
+
<span class="menu float_left apple_search">search</span>
|
31
|
+
</div>
|
32
|
+
</body>
|
33
|
+
</html>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
.apple_itunes {
|
2
|
+
background: transparent url(/apple/sprite.png) -350px 0px no-repeat;
|
3
|
+
width:116;
|
4
|
+
height:38;
|
5
|
+
text-indent:-5000px;
|
6
|
+
}
|
7
|
+
|
8
|
+
.apple_mac {
|
9
|
+
background: transparent url(/apple/sprite.png) -466px 0px no-repeat;
|
10
|
+
width:116;
|
11
|
+
height:38;
|
12
|
+
text-indent:-5000px;
|
13
|
+
}
|
14
|
+
|
15
|
+
.apple_apple {
|
16
|
+
background: transparent url(/apple/sprite.png) 0px 0px no-repeat;
|
17
|
+
width:117;
|
18
|
+
height:38;
|
19
|
+
text-indent:-5000px;
|
20
|
+
}
|
21
|
+
|
22
|
+
.apple_store {
|
23
|
+
background: transparent url(/apple/sprite.png) -744px 0px no-repeat;
|
24
|
+
width:116;
|
25
|
+
height:38;
|
26
|
+
text-indent:-5000px;
|
27
|
+
}
|
28
|
+
|
29
|
+
.apple_search {
|
30
|
+
background: transparent url(/apple/sprite.png) -582px 0px no-repeat;
|
31
|
+
width:162;
|
32
|
+
height:38;
|
33
|
+
text-indent:-5000px;
|
34
|
+
}
|
35
|
+
|
36
|
+
.apple_divider {
|
37
|
+
background: transparent url(/apple/sprite.png) -117px 0px no-repeat;
|
38
|
+
width:1;
|
39
|
+
height:38;
|
40
|
+
text-indent:-5000px;
|
41
|
+
}
|
42
|
+
|
43
|
+
.apple_support {
|
44
|
+
background: transparent url(/apple/sprite.png) -860px 0px no-repeat;
|
45
|
+
width:116;
|
46
|
+
height:38;
|
47
|
+
text-indent:-5000px;
|
48
|
+
}
|
49
|
+
|
50
|
+
.apple_downloads {
|
51
|
+
background: transparent url(/apple/sprite.png) -118px 0px no-repeat;
|
52
|
+
width:116;
|
53
|
+
height:38;
|
54
|
+
text-indent:-5000px;
|
55
|
+
}
|
56
|
+
|
57
|
+
.apple_iphone {
|
58
|
+
background: transparent url(/apple/sprite.png) -234px 0px no-repeat;
|
59
|
+
width:116;
|
60
|
+
height:38;
|
61
|
+
text-indent:-5000px;
|
62
|
+
}
|
63
|
+
|
64
|
+
.words_set {
|
65
|
+
background: transparent url(/words/sprite.png) -85px 0px no-repeat;
|
66
|
+
width:26;
|
67
|
+
height:21;
|
68
|
+
text-indent:-5000px;
|
69
|
+
}
|
70
|
+
|
71
|
+
.words_specified {
|
72
|
+
background: transparent url(/words/sprite.png) -111px 0px no-repeat;
|
73
|
+
width:70;
|
74
|
+
height:21;
|
75
|
+
text-indent:-5000px;
|
76
|
+
}
|
77
|
+
|
78
|
+
.words_latitude {
|
79
|
+
background: transparent url(/words/sprite.png) 0px 0px no-repeat;
|
80
|
+
width:66;
|
81
|
+
height:21;
|
82
|
+
text-indent:-5000px;
|
83
|
+
}
|
84
|
+
|
85
|
+
.words_of {
|
86
|
+
background: transparent url(/words/sprite.png) -66px 0px no-repeat;
|
87
|
+
width:19;
|
88
|
+
height:21;
|
89
|
+
text-indent:-5000px;
|
90
|
+
}
|
91
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.words_set {
|
2
|
+
background: transparent url(/words/sprite.png) -85px 0px no-repeat;
|
3
|
+
width:26;
|
4
|
+
height:21;
|
5
|
+
text-indent:-5000px;
|
6
|
+
}
|
7
|
+
|
8
|
+
.words_specified {
|
9
|
+
background: transparent url(/words/sprite.png) -111px 0px no-repeat;
|
10
|
+
width:70;
|
11
|
+
height:21;
|
12
|
+
text-indent:-5000px;
|
13
|
+
}
|
14
|
+
|
15
|
+
.words_latitude {
|
16
|
+
background: transparent url(/words/sprite.png) 0px 0px no-repeat;
|
17
|
+
width:66;
|
18
|
+
height:21;
|
19
|
+
text-indent:-5000px;
|
20
|
+
}
|
21
|
+
|
22
|
+
.words_of {
|
23
|
+
background: transparent url(/words/sprite.png) -66px 0px no-repeat;
|
24
|
+
width:19;
|
25
|
+
height:21;
|
26
|
+
text-indent:-5000px;
|
27
|
+
}
|
28
|
+
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
.words_of {
|
2
|
+
background: transparent url(/words/sprite.png) -66px 0px no-repeat;
|
3
|
+
width:19;
|
4
|
+
text-indent:-5000px;
|
5
|
+
}
|
6
|
+
|
7
|
+
.words_set {
|
8
|
+
background: transparent url(/words/sprite.png) -85px 0px no-repeat;
|
9
|
+
width:26;
|
10
|
+
text-indent:-5000px;
|
11
|
+
}
|
12
|
+
|
13
|
+
.words_specified {
|
14
|
+
background: transparent url(/words/sprite.png) -111px 0px no-repeat;
|
15
|
+
width:70;
|
16
|
+
text-indent:-5000px;
|
17
|
+
}
|
18
|
+
|
19
|
+
.words_latitude {
|
20
|
+
background: transparent url(/words/sprite.png) 0px 0px no-repeat;
|
21
|
+
width:66;
|
22
|
+
text-indent:-5000px;
|
23
|
+
}
|
24
|
+
|
Binary file
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module PNG
|
2
|
+
class Chunk
|
3
|
+
def chunk_name
|
4
|
+
raise "looks like you havn't subclassed and defined a chunk_name"
|
5
|
+
end
|
6
|
+
|
7
|
+
def to_chunk
|
8
|
+
to_check = chunk_name + encode
|
9
|
+
[encode.length].pack("N") + to_check + [Zlib.crc32(to_check)].pack("N")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class DirectoryProcessor
|
2
|
+
def initialize(dir)
|
3
|
+
@dir = dir
|
4
|
+
files = images
|
5
|
+
@sprite = PNG::Sprite.new
|
6
|
+
files.each {|f| @sprite.append(PNG::Image.open(f))}
|
7
|
+
end
|
8
|
+
|
9
|
+
def images
|
10
|
+
Dir.glob(@dir + "/*.png").reject{|i| i.match /sprite\.png/}
|
11
|
+
end
|
12
|
+
|
13
|
+
def write
|
14
|
+
@sprite.write(sprite_file)
|
15
|
+
File.open(css_file, 'w') do |f|
|
16
|
+
f.write(css)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def cleanup
|
21
|
+
File.delete(sprite_file) rescue {}
|
22
|
+
File.delete(css_file) rescue {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def sprite_file
|
26
|
+
@dir + "/sprite.png"
|
27
|
+
end
|
28
|
+
|
29
|
+
def css_file
|
30
|
+
@dir + "/fragment.css"
|
31
|
+
end
|
32
|
+
|
33
|
+
def dir_name
|
34
|
+
@dir.split('/').last
|
35
|
+
end
|
36
|
+
|
37
|
+
def image_loc
|
38
|
+
#TODO: Lame!
|
39
|
+
("/" + @dir + "/sprite.png").gsub("/./", "/")
|
40
|
+
end
|
41
|
+
|
42
|
+
FRAG = <<-EOF
|
43
|
+
.<name>_<image_name> {
|
44
|
+
background: transparent url(<image_loc>) <offset>px 0px no-repeat;
|
45
|
+
width:<width>;
|
46
|
+
height:<height>;
|
47
|
+
text-indent:-5000px;
|
48
|
+
}
|
49
|
+
|
50
|
+
EOF
|
51
|
+
|
52
|
+
def css
|
53
|
+
@sprite.locations.inject("") do |out, image|
|
54
|
+
image_name, properties = image
|
55
|
+
out << FRAG.gsub("<name>", dir_name).
|
56
|
+
gsub("<image_name>", image_name.to_s).
|
57
|
+
gsub("<width>", properties[:width].to_s).
|
58
|
+
gsub("<height>", properties[:height].to_s).
|
59
|
+
gsub("<offset>", properties[:x].to_s).
|
60
|
+
gsub("<image_loc>", image_loc)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module PNG
|
2
|
+
class Filters
|
3
|
+
class << self
|
4
|
+
#TODO: feature envy, this behavior belongs to a row.
|
5
|
+
def fetch_pixel(idx, row)
|
6
|
+
return 0 if idx < 0
|
7
|
+
return row[idx] || 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def call( filter_type, value, index, row, last_row, record_width )
|
11
|
+
case filter_type
|
12
|
+
when 0
|
13
|
+
no_filter( value, index, row, last_row, record_width )
|
14
|
+
when 1
|
15
|
+
left( value, index, row, last_row, record_width )
|
16
|
+
when 2
|
17
|
+
up( value, index, row, last_row, record_width )
|
18
|
+
when 3
|
19
|
+
avg( value, index, row, last_row, record_width )
|
20
|
+
when 4
|
21
|
+
paeth( value, index, row, last_row, record_width )
|
22
|
+
else
|
23
|
+
raise "Invalid filter type (#{filter_type})"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def no_filter( value, index, row, last_row, record_width )
|
28
|
+
value
|
29
|
+
end
|
30
|
+
|
31
|
+
def left( value, index, row, last_row, record_width )
|
32
|
+
(value + fetch_pixel(index - record_width, row)) % 256
|
33
|
+
end
|
34
|
+
|
35
|
+
def up( value, index, row, last_row, record_width )
|
36
|
+
(value + fetch_pixel(index, last_row)) % 256
|
37
|
+
end
|
38
|
+
|
39
|
+
def avg( value, index, row, last_row, record_width )
|
40
|
+
(value + ( (fetch_pixel(index - record_width, row) + fetch_pixel(index, last_row)) / 2 ).floor) % 256
|
41
|
+
end
|
42
|
+
|
43
|
+
def paeth( value, index, row, last_row, record_width )
|
44
|
+
a = fetch_pixel(index - record_width, row)
|
45
|
+
b = fetch_pixel(index, last_row)
|
46
|
+
c = fetch_pixel(index - record_width, last_row)
|
47
|
+
p = a + b - c
|
48
|
+
pa = (p - a).abs
|
49
|
+
pb = (p - b).abs
|
50
|
+
pc = (p - c).abs
|
51
|
+
|
52
|
+
pr = c
|
53
|
+
if ( pa <= pb and pa <= pc)
|
54
|
+
pr = a
|
55
|
+
elsif (pb <= pc)
|
56
|
+
pr = b
|
57
|
+
end
|
58
|
+
|
59
|
+
(value + pr) % 256
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/spittle/idat.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module PNG
|
2
|
+
class IDAT < Chunk
|
3
|
+
# I don't like that @compressed contains different values depending on how you're using it
|
4
|
+
# maybe we should introduce a builder?
|
5
|
+
def initialize( uncompressed="" )
|
6
|
+
@compressed = ""
|
7
|
+
@compressed += Zlib::Deflate.deflate( uncompressed.pack("C*") ) unless uncompressed == ""
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<( data )
|
11
|
+
@compressed << data
|
12
|
+
end
|
13
|
+
|
14
|
+
def encode
|
15
|
+
@compressed
|
16
|
+
end
|
17
|
+
|
18
|
+
def uncompressed
|
19
|
+
@uncompressed ||= Zlib::Inflate.inflate( @compressed ).unpack("C*")
|
20
|
+
end
|
21
|
+
|
22
|
+
def chunk_name
|
23
|
+
"IDAT"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/spittle/iend.rb
ADDED
data/lib/spittle/ihdr.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module PNG
|
2
|
+
class IHDR < Chunk
|
3
|
+
attr_accessor :width, :height, :depth, :color_type
|
4
|
+
# attr_accessor :compression_method, :filter_method, :interlace_method
|
5
|
+
|
6
|
+
def self.new_from_raw( data )
|
7
|
+
raw = data.unpack("N2C5")
|
8
|
+
|
9
|
+
new( *raw[0..3] )
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize( width, height, depth=8, color_type=2 )
|
13
|
+
raise "for now, spittle only supports images with a bit depth of 8" unless depth == 8
|
14
|
+
raise "for now, spittle only supports color type 2 or 6" unless color_type == 2 || color_type == 6
|
15
|
+
@width, @height, @depth, @color_type = width, height, depth, color_type
|
16
|
+
end
|
17
|
+
|
18
|
+
def encode
|
19
|
+
to_a.pack("N2C5")
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_a
|
23
|
+
[@width, @height, @depth, @color_type, 0, 0, 0]
|
24
|
+
end
|
25
|
+
|
26
|
+
def chunk_name
|
27
|
+
"IHDR"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|