zpng 0.1.0 → 0.1.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.
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +78 -73
- data/README.md.tpl +1 -1
- data/Rakefile +1 -2
- data/VERSION +1 -1
- data/lib/zpng/adam7_decoder.rb +63 -0
- data/lib/zpng/cli.rb +44 -2
- data/lib/zpng/color.rb +43 -4
- data/lib/zpng/image.rb +23 -8
- data/lib/zpng/scan_line.rb +23 -14
- data/lib/zpng/string_ext.rb +11 -0
- data/lib/zpng.rb +3 -1
- data/spec/color_spec.rb +11 -0
- data/spec/spec_helper.rb +29 -3
- data/zpng.gemspec +8 -5
- metadata +8 -5
data/Gemfile
CHANGED
@@ -2,8 +2,8 @@ source "http://rubygems.org"
|
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
4
|
# gem "activesupport", ">= 2.3.5"
|
5
|
-
gem 'colorize'
|
6
5
|
gem 'hexdump'
|
6
|
+
gem 'rainbow'
|
7
7
|
|
8
8
|
# Add dependencies to develop your gem here.
|
9
9
|
# Include everything needed to run rake, tests, features, etc.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
colorize (0.5.8)
|
5
4
|
diff-lcs (1.1.3)
|
6
5
|
git (1.2.5)
|
7
6
|
hexdump (0.2.3)
|
@@ -11,6 +10,7 @@ GEM
|
|
11
10
|
rake
|
12
11
|
rdoc
|
13
12
|
json (1.7.5)
|
13
|
+
rainbow (1.1.4)
|
14
14
|
rake (10.0.2)
|
15
15
|
rdoc (3.12)
|
16
16
|
json (~> 1.4)
|
@@ -28,7 +28,7 @@ PLATFORMS
|
|
28
28
|
|
29
29
|
DEPENDENCIES
|
30
30
|
bundler (>= 1.0.0)
|
31
|
-
colorize
|
32
31
|
hexdump
|
33
32
|
jeweler (~> 1.8.4)
|
33
|
+
rainbow
|
34
34
|
rspec (>= 2.8.0)
|
data/README.md
CHANGED
@@ -20,13 +20,18 @@ Usage
|
|
20
20
|
-q, --quiet Silent any warnings (can be used multiple times)
|
21
21
|
-C, --chunks Show file chunks (default)
|
22
22
|
-i, --info General image info (default)
|
23
|
-
-A, --ascii Try to display image as ASCII (works best with monochrome images)
|
24
23
|
-S, --scanlines Show scanlines info
|
25
24
|
-P, --palette Show palette
|
26
25
|
-E, --extract-chunk ID extract a single chunk
|
27
26
|
-U, --unpack-imagedata unpack Image Data (IDAT) chunk(s), output to stdout
|
27
|
+
|
28
28
|
-c, --crop GEOMETRY crop image, {WIDTH}x{HEIGHT}+{X}+{Y},
|
29
29
|
puts results on stdout unless --ascii given
|
30
|
+
|
31
|
+
-A, --ascii Try to convert image to ASCII (works best with monochrome images)
|
32
|
+
-N, --ansi Try to display image as ANSI colored text
|
33
|
+
-2, --256 Try to display image as 256-colored text
|
34
|
+
-W, --wide Use 2 horizontal characters per one pixel
|
30
35
|
|
31
36
|
### Info
|
32
37
|
|
@@ -39,7 +44,7 @@ Usage
|
|
39
44
|
|
40
45
|
# zpng --chunks qr_aux_chunks.png
|
41
46
|
|
42
|
-
[.] <Chunk #00 IHDR size= 13, crc=36a28ef4,
|
47
|
+
[.] <Chunk #00 IHDR size= 13, crc=36a28ef4, idx=0, interlace=0, filter=0, compression=0, height=35, width=35, depth=1, color=0> CRC OK
|
43
48
|
[.] <Chunk #01 gAMA size= 4, crc=0bfc6105 > CRC OK
|
44
49
|
[.] <Chunk #02 sRGB size= 1, crc=aece1ce9 > CRC OK
|
45
50
|
[.] <Chunk #03 cHRM size= 32, crc=9cba513c > CRC OK
|
@@ -53,82 +58,82 @@ Usage
|
|
53
58
|
|
54
59
|
source image: 
|
55
60
|
|
56
|
-
# zpng --ascii qr_rgb.png
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
61
|
+
# zpng --ascii --wide qr_rgb.png
|
62
|
+
|
63
|
+
|
64
|
+
############## #### #### ## #### ##############
|
65
|
+
## ## #### ## #### ## ##
|
66
|
+
## ###### ## ## ########## ## ## #### ## ###### ##
|
67
|
+
## ###### ## #### ## ## ######## #### ## ###### ##
|
68
|
+
## ###### ## ######## ## ## ######## ## ###### ##
|
69
|
+
## ## ## ## ## ########## ## ##
|
70
|
+
############## ## ## ## ## ## ## ## ## ## ##############
|
71
|
+
## ## #### #### ####
|
72
|
+
######## ## ## #### ## #### #### ###### ##
|
73
|
+
## #### #### #### ## #### ## ###### ####
|
74
|
+
## ###### #### #### ## #### #### ## ###### ##
|
75
|
+
###### ## ########## ## ## #### ## ##
|
76
|
+
#### #### ## ## ## ## ######## #### ####
|
77
|
+
## ## #### #### ## ## ###### #### ####
|
78
|
+
## ############ #### ## ## ########## ##############
|
79
|
+
## ######## ###### #### ## #### ## #### ##
|
80
|
+
#### #### ###### #### ## #### ################
|
81
|
+
## ###### #### #### ################## ##
|
82
|
+
######## ########## #### #### ## ## ## ##
|
83
|
+
#### ## ## ## ## ########## ## ## #### ##
|
84
|
+
############ ########## ## ## #### ##
|
85
|
+
###### ## ######## ## ###### ## ######
|
86
|
+
###### ######## ######## ## ## ############## ####
|
87
|
+
## ## #### #### ## #### ## #### ############ ##
|
88
|
+
## ############## ## #### #### ########## ##
|
89
|
+
## ###### ## #### #### ## ##
|
90
|
+
############## ## ## #### ###### ## ##
|
91
|
+
## ## ###### ## ## ############ ###### ##
|
92
|
+
## ###### ## ## ######## ## ################
|
93
|
+
## ###### ## ###### ## ######## ## ## ##
|
94
|
+
## ###### ## ###### ########## ## #### ## ##
|
95
|
+
## ## ######## #### #### ###### ##
|
96
|
+
############## ## ## #### ## #### ## #### ##
|
92
97
|
|
93
98
|
### Scanlines
|
94
99
|
|
95
100
|
# zpng --scanlines qr_rgb.png
|
96
101
|
|
97
|
-
[#<ZPNG::ScanLine idx=0
|
98
|
-
#<ZPNG::ScanLine idx=1
|
99
|
-
#<ZPNG::ScanLine idx=2
|
100
|
-
#<ZPNG::ScanLine idx=3
|
101
|
-
#<ZPNG::ScanLine idx=4
|
102
|
-
#<ZPNG::ScanLine idx=5
|
103
|
-
#<ZPNG::ScanLine idx=6
|
104
|
-
#<ZPNG::ScanLine idx=7
|
105
|
-
#<ZPNG::ScanLine idx=8
|
106
|
-
#<ZPNG::ScanLine idx=9
|
107
|
-
#<ZPNG::ScanLine idx=10
|
108
|
-
#<ZPNG::ScanLine idx=11
|
109
|
-
#<ZPNG::ScanLine idx=12
|
110
|
-
#<ZPNG::ScanLine idx=13
|
111
|
-
#<ZPNG::ScanLine idx=14
|
112
|
-
#<ZPNG::ScanLine idx=15
|
113
|
-
#<ZPNG::ScanLine idx=16
|
114
|
-
#<ZPNG::ScanLine idx=17
|
115
|
-
#<ZPNG::ScanLine idx=18
|
116
|
-
#<ZPNG::ScanLine idx=19
|
117
|
-
#<ZPNG::ScanLine idx=20
|
118
|
-
#<ZPNG::ScanLine idx=21
|
119
|
-
#<ZPNG::ScanLine idx=22
|
120
|
-
#<ZPNG::ScanLine idx=23
|
121
|
-
#<ZPNG::ScanLine idx=24
|
122
|
-
#<ZPNG::ScanLine idx=25
|
123
|
-
#<ZPNG::ScanLine idx=26
|
124
|
-
#<ZPNG::ScanLine idx=27
|
125
|
-
#<ZPNG::ScanLine idx=28
|
126
|
-
#<ZPNG::ScanLine idx=29
|
127
|
-
#<ZPNG::ScanLine idx=30
|
128
|
-
#<ZPNG::ScanLine idx=31
|
129
|
-
#<ZPNG::ScanLine idx=32
|
130
|
-
#<ZPNG::ScanLine idx=33
|
131
|
-
#<ZPNG::ScanLine idx=34
|
102
|
+
[#<ZPNG::ScanLine idx=0 offset=1 size=106 bpp=24 filter=1>,
|
103
|
+
#<ZPNG::ScanLine idx=1 offset=107 size=106 bpp=24 filter=4>,
|
104
|
+
#<ZPNG::ScanLine idx=2 offset=213 size=106 bpp=24 filter=4>,
|
105
|
+
#<ZPNG::ScanLine idx=3 offset=319 size=106 bpp=24 filter=4>,
|
106
|
+
#<ZPNG::ScanLine idx=4 offset=425 size=106 bpp=24 filter=2>,
|
107
|
+
#<ZPNG::ScanLine idx=5 offset=531 size=106 bpp=24 filter=2>,
|
108
|
+
#<ZPNG::ScanLine idx=6 offset=637 size=106 bpp=24 filter=4>,
|
109
|
+
#<ZPNG::ScanLine idx=7 offset=743 size=106 bpp=24 filter=0>,
|
110
|
+
#<ZPNG::ScanLine idx=8 offset=849 size=106 bpp=24 filter=1>,
|
111
|
+
#<ZPNG::ScanLine idx=9 offset=955 size=106 bpp=24 filter=0>,
|
112
|
+
#<ZPNG::ScanLine idx=10 offset=1061 size=106 bpp=24 filter=0>,
|
113
|
+
#<ZPNG::ScanLine idx=11 offset=1167 size=106 bpp=24 filter=0>,
|
114
|
+
#<ZPNG::ScanLine idx=12 offset=1273 size=106 bpp=24 filter=1>,
|
115
|
+
#<ZPNG::ScanLine idx=13 offset=1379 size=106 bpp=24 filter=2>,
|
116
|
+
#<ZPNG::ScanLine idx=14 offset=1485 size=106 bpp=24 filter=4>,
|
117
|
+
#<ZPNG::ScanLine idx=15 offset=1591 size=106 bpp=24 filter=0>,
|
118
|
+
#<ZPNG::ScanLine idx=16 offset=1697 size=106 bpp=24 filter=4>,
|
119
|
+
#<ZPNG::ScanLine idx=17 offset=1803 size=106 bpp=24 filter=0>,
|
120
|
+
#<ZPNG::ScanLine idx=18 offset=1909 size=106 bpp=24 filter=4>,
|
121
|
+
#<ZPNG::ScanLine idx=19 offset=2015 size=106 bpp=24 filter=4>,
|
122
|
+
#<ZPNG::ScanLine idx=20 offset=2121 size=106 bpp=24 filter=0>,
|
123
|
+
#<ZPNG::ScanLine idx=21 offset=2227 size=106 bpp=24 filter=1>,
|
124
|
+
#<ZPNG::ScanLine idx=22 offset=2333 size=106 bpp=24 filter=2>,
|
125
|
+
#<ZPNG::ScanLine idx=23 offset=2439 size=106 bpp=24 filter=0>,
|
126
|
+
#<ZPNG::ScanLine idx=24 offset=2545 size=106 bpp=24 filter=2>,
|
127
|
+
#<ZPNG::ScanLine idx=25 offset=2651 size=106 bpp=24 filter=1>,
|
128
|
+
#<ZPNG::ScanLine idx=26 offset=2757 size=106 bpp=24 filter=1>,
|
129
|
+
#<ZPNG::ScanLine idx=27 offset=2863 size=106 bpp=24 filter=4>,
|
130
|
+
#<ZPNG::ScanLine idx=28 offset=2969 size=106 bpp=24 filter=4>,
|
131
|
+
#<ZPNG::ScanLine idx=29 offset=3075 size=106 bpp=24 filter=4>,
|
132
|
+
#<ZPNG::ScanLine idx=30 offset=3181 size=106 bpp=24 filter=4>,
|
133
|
+
#<ZPNG::ScanLine idx=31 offset=3287 size=106 bpp=24 filter=2>,
|
134
|
+
#<ZPNG::ScanLine idx=32 offset=3393 size=106 bpp=24 filter=4>,
|
135
|
+
#<ZPNG::ScanLine idx=33 offset=3499 size=106 bpp=24 filter=4>,
|
136
|
+
#<ZPNG::ScanLine idx=34 offset=3605 size=106 bpp=24 filter=1>]
|
132
137
|
|
133
138
|
### Palette
|
134
139
|
|
data/README.md.tpl
CHANGED
data/Rakefile
CHANGED
@@ -86,8 +86,7 @@ Rake::Task[:console].clear
|
|
86
86
|
# from /usr/local/lib64/ruby/gems/1.9.1/gems/jeweler-1.8.4/lib/jeweler/tasks.rb
|
87
87
|
desc "Start IRB with all runtime dependencies loaded"
|
88
88
|
task :console, [:script] do |t,args|
|
89
|
-
|
90
|
-
dirs = ['ext', 'lib'].select { |dir| File.directory?(dir) }
|
89
|
+
dirs = ['./ext', './lib'].select { |dir| File.directory?(dir) }
|
91
90
|
|
92
91
|
original_load_path = $LOAD_PATH
|
93
92
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module ZPNG
|
2
|
+
class Adam7Decoder
|
3
|
+
attr_accessor :image
|
4
|
+
|
5
|
+
def initialize image
|
6
|
+
@image = image
|
7
|
+
end
|
8
|
+
|
9
|
+
def scanlines_count
|
10
|
+
(15*image.height/8.0).ceil
|
11
|
+
end
|
12
|
+
|
13
|
+
WIDTHS = [1,1,2,2,2,4,4,4,4,4,4,8,8,8,8]
|
14
|
+
|
15
|
+
# scanline width in pixels
|
16
|
+
def scanline_width idx
|
17
|
+
#image.width/8*(2**(idx/2))
|
18
|
+
WIDTHS[idx*8/image.height]*(image.width/8)
|
19
|
+
end
|
20
|
+
|
21
|
+
# scanline size in bytes, INCLUDING leading filter byte
|
22
|
+
def scanline_size idx
|
23
|
+
(scanline_width(idx) * image.bpp / 8.0).ceil + 1
|
24
|
+
end
|
25
|
+
|
26
|
+
# scanline offset in imagedata
|
27
|
+
def scanline_offset idx
|
28
|
+
#TODO: optimize
|
29
|
+
(0...idx).map{ |x| scanline_size(x) }.inject(&:+) || 0
|
30
|
+
end
|
31
|
+
|
32
|
+
# convert "flat" coords in scanline number & pos in scanline
|
33
|
+
def convert_coords x,y
|
34
|
+
# optimizing this into one switch/case statement gives
|
35
|
+
# about 1-2% speed increase (ruby 1.9.3p286)
|
36
|
+
|
37
|
+
if y%2 == 1
|
38
|
+
# 7th pass: last height/2 full scanlines
|
39
|
+
[x, y/2 + image.height*11/8]
|
40
|
+
elsif x%2 == 1 && y%2 == 0
|
41
|
+
# 6th pass
|
42
|
+
[x/2, y/2 + image.height*7/8]
|
43
|
+
elsif x%8 == 0 && y%8 == 0
|
44
|
+
# 1st pass
|
45
|
+
[x/8, y/8]
|
46
|
+
elsif x%8 == 4 && y%8 == 0
|
47
|
+
# 2nd pass
|
48
|
+
[x/8, y/8 + image.height/8]
|
49
|
+
elsif x%4 == 0 && y%8 == 4
|
50
|
+
# 3rd pass
|
51
|
+
[x/4, y/8 + image.height*2/8]
|
52
|
+
elsif x%4 == 2 && y%4 == 0
|
53
|
+
# 4th pass
|
54
|
+
[x/4, y/4 + image.height*3/8]
|
55
|
+
elsif x%2 == 0 && y%4 == 2
|
56
|
+
# 5th pass
|
57
|
+
[x/2, y/4 + image.height*5/8]
|
58
|
+
else
|
59
|
+
raise "invalid coords"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/zpng/cli.rb
CHANGED
@@ -8,7 +8,6 @@ class ZPNG::CLI
|
|
8
8
|
ACTIONS = {
|
9
9
|
'chunks' => 'Show file chunks (default)',
|
10
10
|
%w'i info' => 'General image info (default)',
|
11
|
-
'ascii' => 'Try to display image as ASCII (works best with monochrome images)',
|
12
11
|
'scanlines' => 'Show scanlines info',
|
13
12
|
'palette' => 'Show palette'
|
14
13
|
}
|
@@ -46,10 +45,25 @@ class ZPNG::CLI
|
|
46
45
|
@actions << :unpack_imagedata
|
47
46
|
end
|
48
47
|
|
48
|
+
opts.separator ""
|
49
49
|
opts.on "-c", "--crop GEOMETRY", "crop image, {WIDTH}x{HEIGHT}+{X}+{Y},",
|
50
50
|
"puts results on stdout unless --ascii given" do |x|
|
51
51
|
@actions << [:crop, x]
|
52
52
|
end
|
53
|
+
|
54
|
+
opts.separator ""
|
55
|
+
opts.on "-A", '--ascii', 'Try to convert image to ASCII (works best with monochrome images)' do
|
56
|
+
@actions << :ascii
|
57
|
+
end
|
58
|
+
opts.on "-N", '--ansi', 'Try to display image as ANSI colored text' do
|
59
|
+
@actions << :ansi
|
60
|
+
end
|
61
|
+
opts.on "-2", '--256', 'Try to display image as 256-colored text' do
|
62
|
+
@actions << :ansi256
|
63
|
+
end
|
64
|
+
opts.on "-W", '--wide', 'Use 2 horizontal characters per one pixel' do
|
65
|
+
@options[:wide] = true
|
66
|
+
end
|
53
67
|
end
|
54
68
|
|
55
69
|
if (argv = optparser.parse(@argv)).empty?
|
@@ -120,7 +134,35 @@ class ZPNG::CLI
|
|
120
134
|
end
|
121
135
|
|
122
136
|
def ascii
|
123
|
-
|
137
|
+
@img.height.times do |y|
|
138
|
+
@img.width.times do |x|
|
139
|
+
c = @img[x,y].to_ascii
|
140
|
+
c *= 2 if @options[:wide]
|
141
|
+
print c
|
142
|
+
end
|
143
|
+
puts
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def ansi
|
148
|
+
spc = @options[:wide] ? " " : " "
|
149
|
+
@img.height.times do |y|
|
150
|
+
@img.width.times do |x|
|
151
|
+
print spc.background(@img[x,y].closest_ansi_color)
|
152
|
+
end
|
153
|
+
puts
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def ansi256
|
158
|
+
require 'rainbow'
|
159
|
+
spc = @options[:wide] ? " " : " "
|
160
|
+
@img.height.times do |y|
|
161
|
+
@img.width.times do |x|
|
162
|
+
print spc.background(@img[x,y].to_s)
|
163
|
+
end
|
164
|
+
puts
|
165
|
+
end
|
124
166
|
end
|
125
167
|
|
126
168
|
def scanlines
|
data/lib/zpng/color.rb
CHANGED
@@ -9,8 +9,33 @@ module ZPNG
|
|
9
9
|
alias :alpha :a
|
10
10
|
def alpha= v; self.a = v; end
|
11
11
|
|
12
|
-
BLACK = Color.new(0,0,0,
|
13
|
-
WHITE = Color.new(
|
12
|
+
BLACK = Color.new(0 , 0, 0, 255)
|
13
|
+
WHITE = Color.new(255,255,255, 255)
|
14
|
+
|
15
|
+
RED = Color.new(255, 0, 0, 255)
|
16
|
+
GREEN = Color.new(0 ,255, 0, 255)
|
17
|
+
BLUE = Color.new(0 , 0,255, 255)
|
18
|
+
|
19
|
+
YELLOW= Color.new(255,255, 0, 255)
|
20
|
+
CYAN = Color.new( 0,255,255, 255)
|
21
|
+
PURPLE= MAGENTA =
|
22
|
+
Color.new(255, 0,255, 255)
|
23
|
+
|
24
|
+
ANSI_COLORS = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
|
25
|
+
|
26
|
+
# euclidian distance - http://en.wikipedia.org/wiki/Euclidean_distance
|
27
|
+
def euclidian other_color
|
28
|
+
r = (self.r.to_i - other_color.r.to_i)**2
|
29
|
+
r += (self.g.to_i - other_color.g.to_i)**2
|
30
|
+
r += (self.b.to_i - other_color.b.to_i)**2
|
31
|
+
Math.sqrt r
|
32
|
+
end
|
33
|
+
|
34
|
+
def closest_ansi_color
|
35
|
+
a = ANSI_COLORS.map{|c| self.class.const_get(c.to_s.upcase) }
|
36
|
+
a.map!{ |c| self.euclidian(c) }
|
37
|
+
ANSI_COLORS[a.index(a.min)]
|
38
|
+
end
|
14
39
|
|
15
40
|
def white?
|
16
41
|
r == 0xff && g == 0xff && b == 0xff
|
@@ -36,6 +61,15 @@ module ZPNG
|
|
36
61
|
"%02X%02X%02X" % [r,g,b]
|
37
62
|
end
|
38
63
|
|
64
|
+
# try to convert to pseudographics
|
65
|
+
def to_ascii h={}
|
66
|
+
white = h[:white] || ' '
|
67
|
+
black = h[:black] || '#'
|
68
|
+
unknown = h[:unknown] || '?'
|
69
|
+
|
70
|
+
self.white?? white : (self.black?? black : unknown)
|
71
|
+
end
|
72
|
+
|
39
73
|
def to_i
|
40
74
|
((a||0) << 24) + ((r||0) << 16) + ((g||0) << 8) + (b||0)
|
41
75
|
end
|
@@ -47,8 +81,13 @@ module ZPNG
|
|
47
81
|
rs = r ? "%02x" % r : "??"
|
48
82
|
gs = g ? "%02x" % g : "??"
|
49
83
|
bs = b ? "%02x" % b : "??"
|
50
|
-
|
51
|
-
|
84
|
+
if a
|
85
|
+
# alpha is non-NULL
|
86
|
+
"#<ZPNG::Color #%s%s%s a=%d>" % [rs,gs,bs,a]
|
87
|
+
else
|
88
|
+
# alpha is NULL
|
89
|
+
"#<ZPNG::Color #%s%s%s>" % [rs,gs,bs]
|
90
|
+
end
|
52
91
|
end
|
53
92
|
end
|
54
93
|
end
|
data/lib/zpng/image.rb
CHANGED
@@ -22,6 +22,10 @@ module ZPNG
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def adam7
|
26
|
+
@adam7 ||= Adam7Decoder.new(self)
|
27
|
+
end
|
28
|
+
|
25
29
|
# load image from file
|
26
30
|
def self.load fname
|
27
31
|
open(fname,"rb") do |f|
|
@@ -49,7 +53,7 @@ module ZPNG
|
|
49
53
|
@chunks << (@header = Chunk::IHDR.new(h))
|
50
54
|
if @header.palette_used?
|
51
55
|
@chunks << (@palette = Chunk::PLTE.new)
|
52
|
-
@palette[0] = h[:bg] || Color::BLACK # add default bg color
|
56
|
+
@palette[0] = h[:background] || h[:bg] || Color::BLACK # add default bg color
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
@@ -98,6 +102,10 @@ module ZPNG
|
|
98
102
|
end
|
99
103
|
end
|
100
104
|
|
105
|
+
def bpp
|
106
|
+
@header && @header.bpp
|
107
|
+
end
|
108
|
+
|
101
109
|
def width
|
102
110
|
@header && @header.width
|
103
111
|
end
|
@@ -110,25 +118,27 @@ module ZPNG
|
|
110
118
|
@header && @header.grayscale?
|
111
119
|
end
|
112
120
|
|
121
|
+
def interlaced?
|
122
|
+
@header && @header.interlace != 0
|
123
|
+
end
|
124
|
+
|
113
125
|
def imagedata
|
114
126
|
@imagedata ||=
|
115
127
|
begin
|
116
|
-
|
117
|
-
raise "only non-interlaced mode is supported for imagedata" if @header.interlace != 0
|
118
|
-
else
|
119
|
-
puts "[?] no image header, assuming non-interlaced RGB".yellow
|
120
|
-
end
|
128
|
+
puts "[?] no image header, assuming non-interlaced RGB".yellow unless @header
|
121
129
|
data = @chunks.find_all{ |c| c.is_a?(Chunk::IDAT) }.map(&:data).join
|
122
130
|
(data && data.size > 0) ? Zlib::Inflate.inflate(data) : ''
|
123
131
|
end
|
124
132
|
end
|
125
133
|
|
126
134
|
def [] x, y
|
135
|
+
x,y = adam7.convert_coords(x,y) if interlaced?
|
127
136
|
scanlines[y][x]
|
128
137
|
end
|
129
138
|
|
130
139
|
def []= x, y, newpixel
|
131
140
|
decode_all_scanlines
|
141
|
+
x,y = adam7.convert_coords(x,y) if interlaced?
|
132
142
|
scanlines[y][x] = newpixel
|
133
143
|
end
|
134
144
|
|
@@ -144,7 +154,8 @@ module ZPNG
|
|
144
154
|
@scanlines ||=
|
145
155
|
begin
|
146
156
|
r = []
|
147
|
-
height.to_i
|
157
|
+
n = interlaced? ? adam7.scanlines_count : height.to_i
|
158
|
+
n.times do |i|
|
148
159
|
r << ScanLine.new(self,i)
|
149
160
|
end
|
150
161
|
r.delete_if(&:bad?)
|
@@ -154,7 +165,11 @@ module ZPNG
|
|
154
165
|
|
155
166
|
def to_s h={}
|
156
167
|
if scanlines.any?
|
157
|
-
|
168
|
+
if interlaced?
|
169
|
+
height.times.map{ |y| width.times.map{ |x| self[x,y].to_ascii(h) }.join }.join("\n")
|
170
|
+
else
|
171
|
+
scanlines.map{ |l| l.to_s(h) }.join("\n")
|
172
|
+
end
|
158
173
|
else
|
159
174
|
super()
|
160
175
|
end
|
data/lib/zpng/scan_line.rb
CHANGED
@@ -7,7 +7,7 @@ module ZPNG
|
|
7
7
|
FILTER_AVERAGE = 3
|
8
8
|
FILTER_PAETH = 4
|
9
9
|
|
10
|
-
attr_accessor :image, :idx, :filter, :offset
|
10
|
+
attr_accessor :image, :idx, :filter, :offset, :bpp
|
11
11
|
|
12
12
|
def initialize image, idx
|
13
13
|
@image,@idx = image,idx
|
@@ -22,7 +22,12 @@ module ZPNG
|
|
22
22
|
@decoded_bytes = "\x00" * (size-1)
|
23
23
|
@filter = FILTER_NONE
|
24
24
|
else
|
25
|
-
@offset =
|
25
|
+
@offset =
|
26
|
+
if image.interlaced?
|
27
|
+
image.adam7.scanline_offset(idx)
|
28
|
+
else
|
29
|
+
idx*size
|
30
|
+
end
|
26
31
|
if @filter = image.imagedata[@offset]
|
27
32
|
@filter = @filter.ord
|
28
33
|
else
|
@@ -39,28 +44,32 @@ module ZPNG
|
|
39
44
|
|
40
45
|
# total scanline size in bytes, INCLUDING leading 'filter' byte
|
41
46
|
def size
|
47
|
+
w =
|
48
|
+
if image.interlaced?
|
49
|
+
image.adam7.scanline_width(idx)
|
50
|
+
else
|
51
|
+
image.width
|
52
|
+
end
|
42
53
|
if @BPP
|
43
|
-
|
54
|
+
w*@BPP+1
|
44
55
|
else
|
45
|
-
(
|
56
|
+
(w*@bpp/8.0+1).ceil
|
46
57
|
end
|
47
58
|
end
|
48
59
|
|
49
60
|
def inspect
|
50
|
-
|
51
|
-
|
52
|
-
|
61
|
+
if image.interlaced?
|
62
|
+
"#<ZPNG::ScanLine idx=%-2d offset=%-3d width=%-2d size=%-2d bpp=%d filter=%d>" %
|
63
|
+
[idx, offset, image.adam7.scanline_width(idx), size, bpp, filter]
|
64
|
+
else
|
65
|
+
"#<ZPNG::ScanLine idx=%-2d offset=%-3d size=%-2d bpp=%d filter=%d>" %
|
66
|
+
[idx, offset, size, bpp, filter]
|
67
|
+
end
|
53
68
|
end
|
54
69
|
|
55
70
|
def to_s h={}
|
56
|
-
white = h[:white] || ' '
|
57
|
-
black = h[:black] || '#'
|
58
|
-
unknown = h[:unknown] || '?'
|
59
|
-
|
60
71
|
@image.width.times.map do |i|
|
61
|
-
|
62
|
-
# printf "[d] %08x %s %s\n", px.to_i, px.inspect, px.to_s unless px.black?
|
63
|
-
px.white?? white : (px.black?? black : unknown)
|
72
|
+
decode_pixel(i).to_ascii(h)
|
64
73
|
end.join
|
65
74
|
end
|
66
75
|
|
data/lib/zpng.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'zlib'
|
3
3
|
require 'stringio'
|
4
|
-
|
4
|
+
|
5
|
+
require 'zpng/string_ext'
|
5
6
|
|
6
7
|
require 'zpng/color'
|
7
8
|
require 'zpng/block'
|
8
9
|
require 'zpng/scan_line'
|
9
10
|
require 'zpng/chunk'
|
10
11
|
require 'zpng/image'
|
12
|
+
require 'zpng/adam7_decoder'
|
11
13
|
|
12
14
|
# see alse http://github.com/wvanbergen/chunky_png/
|
13
15
|
|
data/spec/color_spec.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ZPNG::Color do
|
4
|
+
|
5
|
+
ZPNG::Color::ANSI_COLORS.each do |color_sym|
|
6
|
+
it "finds closest color for #{color_sym}" do
|
7
|
+
color = ZPNG::Color.const_get(color_sym.to_s.upcase)
|
8
|
+
color.closest_ansi_color.should == color_sym
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -7,9 +7,6 @@ require 'zpng'
|
|
7
7
|
# in ./support/ and its subdirectories.
|
8
8
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
9
|
|
10
|
-
RSpec.configure do |config|
|
11
|
-
end
|
12
|
-
|
13
10
|
SAMPLES_DIR = File.join(
|
14
11
|
File.dirname(
|
15
12
|
File.dirname(
|
@@ -22,3 +19,32 @@ SAMPLES =
|
|
22
19
|
else
|
23
20
|
Dir[File.join(SAMPLES_DIR,'qr_*.png')]
|
24
21
|
end
|
22
|
+
|
23
|
+
PNG_SUITE_URL = "http://www.schaik.com/pngsuite/PngSuite-2011apr25.tgz"
|
24
|
+
|
25
|
+
def get_png_suite
|
26
|
+
dir = File.join(SAMPLES_DIR, "png_suite")
|
27
|
+
if Dir.exist?(dir)
|
28
|
+
if Dir[File.join(dir, "*.png")].size > 100
|
29
|
+
# already fetched and unpacked
|
30
|
+
return
|
31
|
+
end
|
32
|
+
else
|
33
|
+
Dir.mkdir(dir)
|
34
|
+
end
|
35
|
+
require 'open-uri'
|
36
|
+
puts "[.] fetching PNG test-suite from #{PNG_SUITE_URL} .. "
|
37
|
+
data = open(PNG_SUITE_URL).read
|
38
|
+
|
39
|
+
fname = File.join(dir, "png_suite.tgz")
|
40
|
+
File.open(fname, "wb"){ |f| f<<data }
|
41
|
+
puts "[.] unpacking .. "
|
42
|
+
system "tar", "xzf", fname, "-C", dir
|
43
|
+
end
|
44
|
+
|
45
|
+
RSpec.configure do |config|
|
46
|
+
config.before :suite do
|
47
|
+
get_png_suite
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
data/zpng.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "zpng"
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andrey \"Zed\" Zaikin"]
|
12
|
-
s.date = "2012-12-
|
12
|
+
s.date = "2012-12-21"
|
13
13
|
s.email = "zed.0xff@gmail.com"
|
14
14
|
s.executables = ["zpng"]
|
15
15
|
s.extra_rdoc_files = [
|
@@ -29,12 +29,14 @@ Gem::Specification.new do |s|
|
|
29
29
|
"VERSION",
|
30
30
|
"bin/zpng",
|
31
31
|
"lib/zpng.rb",
|
32
|
+
"lib/zpng/adam7_decoder.rb",
|
32
33
|
"lib/zpng/block.rb",
|
33
34
|
"lib/zpng/chunk.rb",
|
34
35
|
"lib/zpng/cli.rb",
|
35
36
|
"lib/zpng/color.rb",
|
36
37
|
"lib/zpng/image.rb",
|
37
38
|
"lib/zpng/scan_line.rb",
|
39
|
+
"lib/zpng/string_ext.rb",
|
38
40
|
"samples/captcha_4bpp.png",
|
39
41
|
"samples/modify.rb",
|
40
42
|
"samples/qr_aux_chunks.png",
|
@@ -46,6 +48,7 @@ Gem::Specification.new do |s|
|
|
46
48
|
"samples/qr_rgb.png",
|
47
49
|
"samples/qr_rgba.png",
|
48
50
|
"spec/ascii_spec.rb",
|
51
|
+
"spec/color_spec.rb",
|
49
52
|
"spec/create_image_spec.rb",
|
50
53
|
"spec/crop_spec.rb",
|
51
54
|
"spec/image_spec.rb",
|
@@ -65,21 +68,21 @@ Gem::Specification.new do |s|
|
|
65
68
|
s.specification_version = 3
|
66
69
|
|
67
70
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
68
|
-
s.add_runtime_dependency(%q<colorize>, [">= 0"])
|
69
71
|
s.add_runtime_dependency(%q<hexdump>, [">= 0"])
|
72
|
+
s.add_runtime_dependency(%q<rainbow>, [">= 0"])
|
70
73
|
s.add_development_dependency(%q<rspec>, [">= 2.8.0"])
|
71
74
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
72
75
|
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
73
76
|
else
|
74
|
-
s.add_dependency(%q<colorize>, [">= 0"])
|
75
77
|
s.add_dependency(%q<hexdump>, [">= 0"])
|
78
|
+
s.add_dependency(%q<rainbow>, [">= 0"])
|
76
79
|
s.add_dependency(%q<rspec>, [">= 2.8.0"])
|
77
80
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
78
81
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
79
82
|
end
|
80
83
|
else
|
81
|
-
s.add_dependency(%q<colorize>, [">= 0"])
|
82
84
|
s.add_dependency(%q<hexdump>, [">= 0"])
|
85
|
+
s.add_dependency(%q<rainbow>, [">= 0"])
|
83
86
|
s.add_dependency(%q<rspec>, [">= 2.8.0"])
|
84
87
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
85
88
|
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
metadata
CHANGED
@@ -2,19 +2,19 @@
|
|
2
2
|
name: zpng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Andrey "Zed" Zaikin
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
prerelease: false
|
16
16
|
type: :runtime
|
17
|
-
name:
|
17
|
+
name: hexdump
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -30,7 +30,7 @@ dependencies:
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
prerelease: false
|
32
32
|
type: :runtime
|
33
|
-
name:
|
33
|
+
name: rainbow
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
35
35
|
requirements:
|
36
36
|
- - ! '>='
|
@@ -112,12 +112,14 @@ files:
|
|
112
112
|
- VERSION
|
113
113
|
- bin/zpng
|
114
114
|
- lib/zpng.rb
|
115
|
+
- lib/zpng/adam7_decoder.rb
|
115
116
|
- lib/zpng/block.rb
|
116
117
|
- lib/zpng/chunk.rb
|
117
118
|
- lib/zpng/cli.rb
|
118
119
|
- lib/zpng/color.rb
|
119
120
|
- lib/zpng/image.rb
|
120
121
|
- lib/zpng/scan_line.rb
|
122
|
+
- lib/zpng/string_ext.rb
|
121
123
|
- samples/captcha_4bpp.png
|
122
124
|
- samples/modify.rb
|
123
125
|
- samples/qr_aux_chunks.png
|
@@ -129,6 +131,7 @@ files:
|
|
129
131
|
- samples/qr_rgb.png
|
130
132
|
- samples/qr_rgba.png
|
131
133
|
- spec/ascii_spec.rb
|
134
|
+
- spec/color_spec.rb
|
132
135
|
- spec/create_image_spec.rb
|
133
136
|
- spec/crop_spec.rb
|
134
137
|
- spec/image_spec.rb
|
@@ -151,7 +154,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
151
154
|
version: '0'
|
152
155
|
segments:
|
153
156
|
- 0
|
154
|
-
hash:
|
157
|
+
hash: 2879730800431969805
|
155
158
|
none: false
|
156
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
160
|
requirements:
|