zpng 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +72 -71
- data/TODO +10 -0
- data/VERSION +1 -1
- data/lib/zpng.rb +1 -0
- data/lib/zpng/adam7_decoder.rb +25 -17
- data/lib/zpng/chunk.rb +2 -0
- data/lib/zpng/cli.rb +21 -6
- data/lib/zpng/color.rb +95 -38
- data/lib/zpng/deep_copyable.rb +7 -0
- data/lib/zpng/image.rb +42 -4
- data/lib/zpng/scan_line.rb +34 -21
- data/misc/chars.png +0 -0
- data/misc/gen_ascii_map.rb +63 -0
- data/spec/adam7_spec.rb +61 -0
- data/spec/ascii_spec.rb +1 -1
- data/spec/color_spec.rb +30 -1
- data/spec/create_image_spec.rb +6 -6
- data/spec/crop_spec.rb +4 -4
- data/spec/modify_spec.rb +1 -1
- data/spec/running_pixel_spec.rb +1 -1
- data/zpng.gemspec +9 -3
- metadata +9 -3
data/README.md
CHANGED
@@ -23,7 +23,7 @@ Usage
|
|
23
23
|
-S, --scanlines Show scanlines info
|
24
24
|
-P, --palette Show palette
|
25
25
|
-E, --extract-chunk ID extract a single chunk
|
26
|
-
-
|
26
|
+
-D, --imagedata dump unpacked Image Data (IDAT) chunk(s) to stdout
|
27
27
|
|
28
28
|
-c, --crop GEOMETRY crop image, {WIDTH}x{HEIGHT}+{X}+{Y},
|
29
29
|
puts results on stdout unless --ascii given
|
@@ -44,7 +44,7 @@ Usage
|
|
44
44
|
|
45
45
|
# zpng --chunks qr_aux_chunks.png
|
46
46
|
|
47
|
-
[.] <Chunk #00 IHDR size= 13, crc=36a28ef4,
|
47
|
+
[.] <Chunk #00 IHDR size= 13, crc=36a28ef4, width=35, height=35, depth=1, color=0, compression=0, filter=0, interlace=0, idx=0> CRC OK
|
48
48
|
[.] <Chunk #01 gAMA size= 4, crc=0bfc6105 > CRC OK
|
49
49
|
[.] <Chunk #02 sRGB size= 1, crc=aece1ce9 > CRC OK
|
50
50
|
[.] <Chunk #03 cHRM size= 32, crc=9cba513c > CRC OK
|
@@ -60,80 +60,81 @@ source image: ![qr_rgb.png](https://github.com/zed-0xff/zpng/raw/master/samples/
|
|
60
60
|
|
61
61
|
# zpng --ascii --wide qr_rgb.png
|
62
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
|
-
|
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
|
+
@@ @@ @@ @@@@ @@ @@ @@@@@@ @@ @@@@@@ @@@@@@
|
97
|
+
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
97
98
|
|
98
99
|
### Scanlines
|
99
100
|
|
100
101
|
# zpng --scanlines qr_rgb.png
|
101
102
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
103
|
+
#<ZPNG::ScanLine idx=0 offset=0 size=106 bpp=24 filter=1>
|
104
|
+
#<ZPNG::ScanLine idx=1 offset=106 size=106 bpp=24 filter=4>
|
105
|
+
#<ZPNG::ScanLine idx=2 offset=212 size=106 bpp=24 filter=4>
|
106
|
+
#<ZPNG::ScanLine idx=3 offset=318 size=106 bpp=24 filter=4>
|
107
|
+
#<ZPNG::ScanLine idx=4 offset=424 size=106 bpp=24 filter=2>
|
108
|
+
#<ZPNG::ScanLine idx=5 offset=530 size=106 bpp=24 filter=2>
|
109
|
+
#<ZPNG::ScanLine idx=6 offset=636 size=106 bpp=24 filter=4>
|
110
|
+
#<ZPNG::ScanLine idx=7 offset=742 size=106 bpp=24 filter=0>
|
111
|
+
#<ZPNG::ScanLine idx=8 offset=848 size=106 bpp=24 filter=1>
|
112
|
+
#<ZPNG::ScanLine idx=9 offset=954 size=106 bpp=24 filter=0>
|
113
|
+
#<ZPNG::ScanLine idx=10 offset=1060 size=106 bpp=24 filter=0>
|
114
|
+
#<ZPNG::ScanLine idx=11 offset=1166 size=106 bpp=24 filter=0>
|
115
|
+
#<ZPNG::ScanLine idx=12 offset=1272 size=106 bpp=24 filter=1>
|
116
|
+
#<ZPNG::ScanLine idx=13 offset=1378 size=106 bpp=24 filter=2>
|
117
|
+
#<ZPNG::ScanLine idx=14 offset=1484 size=106 bpp=24 filter=4>
|
118
|
+
#<ZPNG::ScanLine idx=15 offset=1590 size=106 bpp=24 filter=0>
|
119
|
+
#<ZPNG::ScanLine idx=16 offset=1696 size=106 bpp=24 filter=4>
|
120
|
+
#<ZPNG::ScanLine idx=17 offset=1802 size=106 bpp=24 filter=0>
|
121
|
+
#<ZPNG::ScanLine idx=18 offset=1908 size=106 bpp=24 filter=4>
|
122
|
+
#<ZPNG::ScanLine idx=19 offset=2014 size=106 bpp=24 filter=4>
|
123
|
+
#<ZPNG::ScanLine idx=20 offset=2120 size=106 bpp=24 filter=0>
|
124
|
+
#<ZPNG::ScanLine idx=21 offset=2226 size=106 bpp=24 filter=1>
|
125
|
+
#<ZPNG::ScanLine idx=22 offset=2332 size=106 bpp=24 filter=2>
|
126
|
+
#<ZPNG::ScanLine idx=23 offset=2438 size=106 bpp=24 filter=0>
|
127
|
+
#<ZPNG::ScanLine idx=24 offset=2544 size=106 bpp=24 filter=2>
|
128
|
+
#<ZPNG::ScanLine idx=25 offset=2650 size=106 bpp=24 filter=1>
|
129
|
+
#<ZPNG::ScanLine idx=26 offset=2756 size=106 bpp=24 filter=1>
|
130
|
+
#<ZPNG::ScanLine idx=27 offset=2862 size=106 bpp=24 filter=4>
|
131
|
+
#<ZPNG::ScanLine idx=28 offset=2968 size=106 bpp=24 filter=4>
|
132
|
+
#<ZPNG::ScanLine idx=29 offset=3074 size=106 bpp=24 filter=4>
|
133
|
+
#<ZPNG::ScanLine idx=30 offset=3180 size=106 bpp=24 filter=4>
|
134
|
+
#<ZPNG::ScanLine idx=31 offset=3286 size=106 bpp=24 filter=2>
|
135
|
+
#<ZPNG::ScanLine idx=32 offset=3392 size=106 bpp=24 filter=4>
|
136
|
+
#<ZPNG::ScanLine idx=33 offset=3498 size=106 bpp=24 filter=4>
|
137
|
+
#<ZPNG::ScanLine idx=34 offset=3604 size=106 bpp=24 filter=1>
|
137
138
|
|
138
139
|
### Palette
|
139
140
|
|
data/TODO
ADDED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/zpng.rb
CHANGED
data/lib/zpng/adam7_decoder.rb
CHANGED
@@ -1,21 +1,29 @@
|
|
1
1
|
module ZPNG
|
2
2
|
class Adam7Decoder
|
3
3
|
attr_accessor :image
|
4
|
+
attr_reader :scanlines_count
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
# http://en.wikipedia.org/wiki/Adam7_algorithm#Passes
|
7
|
+
def initialize img
|
8
|
+
@image = img
|
9
|
+
@widths = [
|
10
|
+
[(img.width/8.0).ceil] * (img.height/8.0).ceil, # pass1
|
11
|
+
[((img.width-4)/8.0).ceil] * (img.height/8.0).ceil, # pass2
|
12
|
+
[(img.width/4.0).ceil] * ((img.height-4)/8.0).ceil, # pass3
|
13
|
+
[((img.width-2)/4.0).ceil] * (img.height/4.0).ceil, # pass4
|
14
|
+
[(img.width/2.0).ceil] * ((img.height-2)/4.0).ceil, # pass5
|
15
|
+
[((img.width-1)/2.0).ceil] * (img.height/2.0).ceil, # pass6
|
16
|
+
[img.width] * ((img.height-1)/2.0).ceil # pass7
|
17
|
+
].map{ |x| x == [0] ? [] : x }
|
18
|
+
@scanlines_count = 0
|
19
|
+
# two leading zeroes added specially for convert_coords() code readability
|
20
|
+
@pass_starts = [0,0] + @widths.map(&:size).map{ |x| @scanlines_count+=x }
|
21
|
+
@widths.flatten!
|
7
22
|
end
|
8
23
|
|
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
24
|
# scanline width in pixels
|
16
25
|
def scanline_width idx
|
17
|
-
|
18
|
-
WIDTHS[idx*8/image.height]*(image.width/8)
|
26
|
+
@widths[idx]
|
19
27
|
end
|
20
28
|
|
21
29
|
# scanline size in bytes, INCLUDING leading filter byte
|
@@ -36,25 +44,25 @@ module ZPNG
|
|
36
44
|
|
37
45
|
if y%2 == 1
|
38
46
|
# 7th pass: last height/2 full scanlines
|
39
|
-
[x, y/2 +
|
47
|
+
[x, y/2 + @pass_starts[7]]
|
40
48
|
elsif x%2 == 1 && y%2 == 0
|
41
49
|
# 6th pass
|
42
|
-
[x/2, y/2 +
|
50
|
+
[x/2, y/2 + @pass_starts[6]]
|
43
51
|
elsif x%8 == 0 && y%8 == 0
|
44
|
-
# 1st pass
|
52
|
+
# 1st pass, starts at 0
|
45
53
|
[x/8, y/8]
|
46
54
|
elsif x%8 == 4 && y%8 == 0
|
47
55
|
# 2nd pass
|
48
|
-
[x/8, y/8 +
|
56
|
+
[x/8, y/8 + @pass_starts[2]]
|
49
57
|
elsif x%4 == 0 && y%8 == 4
|
50
58
|
# 3rd pass
|
51
|
-
[x/4, y/8 +
|
59
|
+
[x/4, y/8 + @pass_starts[3]]
|
52
60
|
elsif x%4 == 2 && y%4 == 0
|
53
61
|
# 4th pass
|
54
|
-
[x/4, y/4 +
|
62
|
+
[x/4, y/4 + @pass_starts[4]]
|
55
63
|
elsif x%2 == 0 && y%4 == 2
|
56
64
|
# 5th pass
|
57
|
-
[x/2, y/4 +
|
65
|
+
[x/2, y/4 + @pass_starts[5]]
|
58
66
|
else
|
59
67
|
raise "invalid coords"
|
60
68
|
end
|
data/lib/zpng/chunk.rb
CHANGED
data/lib/zpng/cli.rb
CHANGED
@@ -41,7 +41,7 @@ class ZPNG::CLI
|
|
41
41
|
opts.on "-E", "--extract-chunk ID", "extract a single chunk" do |id|
|
42
42
|
@actions << [:extract_chunk, id.to_i]
|
43
43
|
end
|
44
|
-
opts.on "-
|
44
|
+
opts.on "-D", "--imagedata", "dump unpacked Image Data (IDAT) chunk(s) to stdout" do
|
45
45
|
@actions << :unpack_imagedata
|
46
46
|
end
|
47
47
|
|
@@ -74,7 +74,10 @@ class ZPNG::CLI
|
|
74
74
|
@actions = DEFAULT_ACTIONS if @actions.empty?
|
75
75
|
|
76
76
|
argv.each_with_index do |fname,idx|
|
77
|
-
|
77
|
+
if argv.size > 1 && @options[:verbose] >= 0
|
78
|
+
puts if idx > 0
|
79
|
+
puts "[.] #{fname}".color(:green)
|
80
|
+
end
|
78
81
|
@file_idx = idx
|
79
82
|
@file_name = fname
|
80
83
|
|
@@ -124,7 +127,7 @@ class ZPNG::CLI
|
|
124
127
|
end
|
125
128
|
|
126
129
|
def info
|
127
|
-
puts "[.] image size #{@img.width || '?'}x#{@img.height || '?'}"
|
130
|
+
puts "[.] image size #{@img.width || '?'}x#{@img.height || '?'}, bpp=#{@img.bpp}"
|
128
131
|
puts "[.] uncompressed imagedata size = #{@img.imagedata.size} bytes"
|
129
132
|
puts "[.] palette = #{@img.palette}" if @img.palette
|
130
133
|
end
|
@@ -148,7 +151,7 @@ class ZPNG::CLI
|
|
148
151
|
spc = @options[:wide] ? " " : " "
|
149
152
|
@img.height.times do |y|
|
150
153
|
@img.width.times do |x|
|
151
|
-
print spc.background(@img[x,y].
|
154
|
+
print spc.background(@img[x,y].to_ansi)
|
152
155
|
end
|
153
156
|
puts
|
154
157
|
end
|
@@ -159,14 +162,26 @@ class ZPNG::CLI
|
|
159
162
|
spc = @options[:wide] ? " " : " "
|
160
163
|
@img.height.times do |y|
|
161
164
|
@img.width.times do |x|
|
162
|
-
print spc.background(@img[x,y].
|
165
|
+
print spc.background(@img[x,y].to_html)
|
163
166
|
end
|
164
167
|
puts
|
165
168
|
end
|
166
169
|
end
|
167
170
|
|
168
171
|
def scanlines
|
169
|
-
|
172
|
+
@img.scanlines.each do |sl|
|
173
|
+
p sl
|
174
|
+
case @options[:verbose]
|
175
|
+
when 1
|
176
|
+
Hexdump.dump(sl.raw_data)
|
177
|
+
when 2
|
178
|
+
Hexdump.dump(sl.decoded_bytes)
|
179
|
+
when 3..999
|
180
|
+
Hexdump.dump(sl.raw_data)
|
181
|
+
Hexdump.dump(sl.decoded_bytes)
|
182
|
+
puts
|
183
|
+
end
|
184
|
+
end
|
170
185
|
end
|
171
186
|
|
172
187
|
def palette
|
data/lib/zpng/color.rb
CHANGED
@@ -1,28 +1,54 @@
|
|
1
1
|
module ZPNG
|
2
|
-
class Color
|
2
|
+
class Color
|
3
|
+
attr_accessor :r, :g, :b, :a
|
4
|
+
attr_accessor :depth, :alpha_depth
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
6
|
+
include DeepCopyable
|
7
|
+
|
8
|
+
def initialize *a
|
9
|
+
h = a.last.is_a?(Hash) ? a.pop : {}
|
10
|
+
@r,@g,@b,@a = *a
|
11
|
+
|
12
|
+
# default ALPHA = 0xff - opaque
|
13
|
+
@a ||= h[:alpha] || 0xff
|
14
|
+
|
15
|
+
# default sample depth for r,g,b and alpha = 8 bits
|
16
|
+
@depth = h[:depth] || 8
|
17
|
+
@alpha_depth = h[:alpha_depth] || @depth
|
7
18
|
end
|
8
19
|
|
9
20
|
alias :alpha :a
|
10
|
-
def alpha=
|
21
|
+
def alpha= a; @a=a; end
|
11
22
|
|
12
|
-
BLACK = Color.new(0 , 0, 0
|
13
|
-
WHITE = Color.new(255,255,255
|
23
|
+
BLACK = Color.new(0 , 0, 0)
|
24
|
+
WHITE = Color.new(255,255,255)
|
14
25
|
|
15
|
-
RED = Color.new(255, 0, 0
|
16
|
-
GREEN = Color.new(0 ,255, 0
|
17
|
-
BLUE = Color.new(0 , 0,255
|
26
|
+
RED = Color.new(255, 0, 0)
|
27
|
+
GREEN = Color.new(0 ,255, 0)
|
28
|
+
BLUE = Color.new(0 , 0,255)
|
18
29
|
|
19
|
-
YELLOW= Color.new(255,255, 0
|
20
|
-
CYAN = Color.new( 0,255,255
|
30
|
+
YELLOW= Color.new(255,255, 0)
|
31
|
+
CYAN = Color.new( 0,255,255)
|
21
32
|
PURPLE= MAGENTA =
|
22
|
-
Color.new(255, 0,255
|
33
|
+
Color.new(255, 0,255)
|
23
34
|
|
24
35
|
ANSI_COLORS = [:black, :red, :green, :yellow, :blue, :magenta, :cyan, :white]
|
25
36
|
|
37
|
+
#ASCII_MAP = %q_ .`,-:;~"!<+*^(LJ=?vctsxj12FuoCeyPSah5wVmXA4G9$OR0MQNW#&%@_
|
38
|
+
#ASCII_MAP = %q_ .`,-:;~"!<+*^=VXMQNW#&%@_
|
39
|
+
#ASCII_MAP = %q_ .,:"!*=7FZVXM#%@_
|
40
|
+
|
41
|
+
# see misc/gen_ascii_map.rb
|
42
|
+
ASCII_MAP =
|
43
|
+
[" '''''''```,,",
|
44
|
+
",,---:::::;;;;~~\"\"\"\"",
|
45
|
+
"\"!!!!!!<++*^^^(((LLJ",
|
46
|
+
"=??vvv]ts[j1122FFuoo",
|
47
|
+
"CeyyPEah55333VVmmXA4",
|
48
|
+
"G9$666666RRRRRR00MQQ",
|
49
|
+
"NNW####&&&&&%%%%%%%%",
|
50
|
+
"@@@@@@@"].join
|
51
|
+
|
26
52
|
# euclidian distance - http://en.wikipedia.org/wiki/Euclidean_distance
|
27
53
|
def euclidian other_color
|
28
54
|
r = (self.r.to_i - other_color.r.to_i)**2
|
@@ -31,12 +57,6 @@ module ZPNG
|
|
31
57
|
Math.sqrt r
|
32
58
|
end
|
33
59
|
|
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
|
39
|
-
|
40
60
|
def white?
|
41
61
|
r == 0xff && g == 0xff && b == 0xff
|
42
62
|
end
|
@@ -53,42 +73,79 @@ module ZPNG
|
|
53
73
|
(r+g+b)/3
|
54
74
|
end
|
55
75
|
|
56
|
-
def self.from_grayscale value,
|
57
|
-
Color.new value,value,value,
|
76
|
+
def self.from_grayscale value, alpha_or_hash = nil
|
77
|
+
Color.new value,value,value, alpha_or_hash
|
58
78
|
end
|
59
79
|
|
60
80
|
def to_s
|
61
81
|
"%02X%02X%02X" % [r,g,b]
|
62
82
|
end
|
63
83
|
|
84
|
+
########################################################
|
85
|
+
|
64
86
|
# try to convert to pseudographics
|
65
|
-
def to_ascii
|
66
|
-
|
67
|
-
|
68
|
-
|
87
|
+
def to_ascii map=ASCII_MAP
|
88
|
+
#p self
|
89
|
+
map[self.to_grayscale*(map.size-1)/(2**@depth-1), 1]
|
90
|
+
end
|
91
|
+
|
92
|
+
def to_ansi
|
93
|
+
return to_depth(8).to_ansi if depth != 8
|
94
|
+
a = ANSI_COLORS.map{|c| self.class.const_get(c.to_s.upcase) }
|
95
|
+
a.map!{ |c| self.euclidian(c) }
|
96
|
+
ANSI_COLORS[a.index(a.min)]
|
97
|
+
end
|
69
98
|
|
70
|
-
|
99
|
+
def to_css
|
100
|
+
return to_depth(8).to_css if depth != 8
|
101
|
+
"#%02X%02X%02X" % [r,g,b]
|
71
102
|
end
|
103
|
+
alias :to_html :to_css
|
104
|
+
|
105
|
+
########################################################
|
72
106
|
|
73
107
|
def to_i
|
74
108
|
((a||0) << 24) + ((r||0) << 16) + ((g||0) << 8) + (b||0)
|
75
109
|
end
|
76
110
|
|
77
|
-
|
78
|
-
|
79
|
-
|
111
|
+
# change bit depth, return new Color
|
112
|
+
def to_depth new_depth
|
113
|
+
c = Color.new :depth => new_depth
|
114
|
+
if new_depth > self.depth
|
115
|
+
%w'r g b'.each do |part|
|
116
|
+
color = self.send(part)
|
117
|
+
if color%2 == 0
|
118
|
+
color <<= (new_depth-self.depth)
|
119
|
+
else
|
120
|
+
(new_depth-self.depth).times{ color = color*2 + 1 }
|
121
|
+
end
|
122
|
+
c.send("#{part}=", color)
|
123
|
+
end
|
80
124
|
else
|
81
|
-
|
82
|
-
|
83
|
-
|
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]
|
125
|
+
# new_depth < self.depth
|
126
|
+
%w'r g b'.each do |part|
|
127
|
+
c.send("#{part}=", self.send(part)>>(self.depth-new_depth))
|
90
128
|
end
|
91
129
|
end
|
130
|
+
c
|
131
|
+
end
|
132
|
+
|
133
|
+
def inspect
|
134
|
+
s = "#<ZPNG::Color"
|
135
|
+
if depth == 16
|
136
|
+
s << " r=" + (r ? "%04x" % r : "????")
|
137
|
+
s << " g=" + (g ? "%04x" % g : "????")
|
138
|
+
s << " b=" + (b ? "%04x" % b : "????")
|
139
|
+
else
|
140
|
+
s << " #"
|
141
|
+
s << (r ? "%02x" % r : "??")
|
142
|
+
s << (g ? "%02x" % g : "??")
|
143
|
+
s << (b ? "%02x" % b : "??")
|
144
|
+
end
|
145
|
+
s << " a=#{a}" if a && alpha_depth != 0
|
146
|
+
s << " depth=#{depth}" if depth != 8
|
147
|
+
s << " alpha_depth=#{alpha_depth}" if alpha_depth != 8 && alpha_depth != 0
|
148
|
+
s << ">"
|
92
149
|
end
|
93
150
|
end
|
94
151
|
end
|
data/lib/zpng/image.rb
CHANGED
@@ -3,6 +3,8 @@ module ZPNG
|
|
3
3
|
attr_accessor :data, :header, :chunks, :scanlines, :imagedata, :palette
|
4
4
|
alias :hdr :header
|
5
5
|
|
6
|
+
include DeepCopyable
|
7
|
+
|
6
8
|
PNG_HDR = "\x89PNG\x0d\x0a\x1a\x0a"
|
7
9
|
|
8
10
|
def initialize x
|
@@ -124,6 +126,10 @@ module ZPNG
|
|
124
126
|
@header && @header.interlace != 0
|
125
127
|
end
|
126
128
|
|
129
|
+
def alpha_used?
|
130
|
+
@header && @header.alpha_used?
|
131
|
+
end
|
132
|
+
|
127
133
|
def imagedata
|
128
134
|
@imagedata ||=
|
129
135
|
begin
|
@@ -165,12 +171,12 @@ module ZPNG
|
|
165
171
|
end
|
166
172
|
end
|
167
173
|
|
168
|
-
def
|
174
|
+
def to_ascii *args
|
169
175
|
if scanlines.any?
|
170
176
|
if interlaced?
|
171
|
-
height.times.map{ |y| width.times.map{ |x| self[x,y].to_ascii(
|
177
|
+
height.times.map{ |y| width.times.map{ |x| self[x,y].to_ascii(*args) }.join }.join("\n")
|
172
178
|
else
|
173
|
-
scanlines.map{ |l| l.
|
179
|
+
scanlines.map{ |l| l.to_ascii(*args) }.join("\n")
|
174
180
|
end
|
175
181
|
else
|
176
182
|
super()
|
@@ -244,8 +250,40 @@ module ZPNG
|
|
244
250
|
|
245
251
|
# returns new image
|
246
252
|
def crop params
|
253
|
+
decode_all_scanlines
|
247
254
|
# deep copy first, then crop!
|
248
|
-
|
255
|
+
deep_copy.crop!(params)
|
256
|
+
end
|
257
|
+
|
258
|
+
def each_pixel &block
|
259
|
+
height.times do |y|
|
260
|
+
width.times do |x|
|
261
|
+
yield(self[x,y], x, y)
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# returns new deinterlaced image if deinterlaced
|
267
|
+
# OR returns self if no need to deinterlace
|
268
|
+
def deinterlace
|
269
|
+
return self unless interlaced?
|
270
|
+
require 'pp'
|
271
|
+
pp chunks
|
272
|
+
|
273
|
+
# copy all but 'interlace' header params
|
274
|
+
h = Hash[*%w'width height depth color compression filter'.map{ |k| [k.to_sym, hdr.send(k)] }.flatten]
|
275
|
+
new_img = Image.new h
|
276
|
+
chunks.each do |chunk|
|
277
|
+
next if chunk.is_a?(Chunk::IHDR)
|
278
|
+
next if chunk.is_a?(Chunk::IDAT)
|
279
|
+
next if chunk.is_a?(Chunk::IEND)
|
280
|
+
new_img.chunks << chunk.deep_copy
|
281
|
+
end
|
282
|
+
each_pixel do |c,x,y|
|
283
|
+
new_img[x,y] = c
|
284
|
+
end
|
285
|
+
p new_img.scanlines
|
286
|
+
new_img
|
249
287
|
end
|
250
288
|
end
|
251
289
|
end
|
data/lib/zpng/scan_line.rb
CHANGED
@@ -21,6 +21,7 @@ module ZPNG
|
|
21
21
|
if @image.new?
|
22
22
|
@decoded_bytes = "\x00" * (size-1)
|
23
23
|
@filter = FILTER_NONE
|
24
|
+
@offset = idx*size
|
24
25
|
else
|
25
26
|
@offset =
|
26
27
|
if image.interlaced?
|
@@ -33,7 +34,6 @@ module ZPNG
|
|
33
34
|
else
|
34
35
|
STDERR.puts "[!] #{self.class}: ##@idx: no data at pos 0, scanline dropped".red
|
35
36
|
end
|
36
|
-
@offset += 1
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -67,9 +67,9 @@ module ZPNG
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
def
|
70
|
+
def to_ascii *args
|
71
71
|
@image.width.times.map do |i|
|
72
|
-
decode_pixel(i).to_ascii(
|
72
|
+
decode_pixel(i).to_ascii(*args)
|
73
73
|
end.join
|
74
74
|
end
|
75
75
|
|
@@ -142,27 +142,39 @@ module ZPNG
|
|
142
142
|
when 8
|
143
143
|
[raw.ord, nil]
|
144
144
|
when 16
|
145
|
-
|
145
|
+
if image.alpha_used?
|
146
|
+
raw.unpack 'C2'
|
147
|
+
else
|
148
|
+
# 16-bit grayscale
|
149
|
+
raw.unpack 'n'
|
150
|
+
end
|
146
151
|
when 24
|
147
152
|
# RGB
|
148
153
|
return Color.new(*raw.unpack('C3'))
|
149
154
|
when 32
|
150
|
-
|
151
|
-
|
155
|
+
if image.grayscale? && image.alpha_used?
|
156
|
+
# 16-bit grayscale + 16-bit alpha
|
157
|
+
raw.unpack 'n2'
|
158
|
+
else
|
159
|
+
# RGBA
|
160
|
+
return Color.new(*raw.unpack('C4'))
|
161
|
+
end
|
162
|
+
when 48
|
163
|
+
# RGB 16 bits per sample
|
164
|
+
return Color.new(*raw.unpack('n3'), :depth => 16)
|
165
|
+
when 64
|
166
|
+
# RGB 16 bits per sample + 16-bit alpha
|
167
|
+
return Color.new(*raw.unpack('n4'), :depth => 16, :alpha_depth => 16)
|
152
168
|
else
|
153
169
|
raise "unexpected bpp #{@bpp}"
|
154
170
|
end
|
155
171
|
|
156
172
|
if image.grayscale?
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
(8-@bpp).times{ color = color*2 + 1 }
|
163
|
-
end
|
164
|
-
end
|
165
|
-
Color.from_grayscale(color, alpha)
|
173
|
+
Color.from_grayscale(color,
|
174
|
+
:alpha => alpha,
|
175
|
+
:depth => image.hdr.depth,
|
176
|
+
:alpha_depth => image.alpha_used? ? image.hdr.depth : 0
|
177
|
+
)
|
166
178
|
elsif image.palette
|
167
179
|
color = image.palette[color]
|
168
180
|
color.alpha = alpha
|
@@ -173,17 +185,14 @@ module ZPNG
|
|
173
185
|
end
|
174
186
|
|
175
187
|
def decoded_bytes
|
176
|
-
raise if caller.size > 50
|
188
|
+
#raise if caller.size > 50
|
177
189
|
@decoded_bytes ||=
|
178
190
|
begin
|
179
191
|
# number of bytes per complete pixel, rounding up to one
|
180
192
|
bpp1 = (@bpp/8.0).ceil
|
181
193
|
|
182
|
-
# bytes in one scanline
|
183
|
-
nbytes = (image.width*@bpp/8.0).ceil
|
184
|
-
|
185
194
|
s = ''
|
186
|
-
|
195
|
+
(size-1).times do |i|
|
187
196
|
b0 = (i-bpp1) >= 0 ? s[i-bpp1] : nil
|
188
197
|
s[i] = decode_byte(i, b0, bpp1)
|
189
198
|
end
|
@@ -197,9 +206,13 @@ module ZPNG
|
|
197
206
|
true
|
198
207
|
end
|
199
208
|
|
209
|
+
def raw_data
|
210
|
+
@offset ? @image.imagedata[@offset, size] : ''
|
211
|
+
end
|
212
|
+
|
200
213
|
private
|
201
214
|
def decode_byte x, b0, bpp1
|
202
|
-
raw = @image.imagedata[@offset+x]
|
215
|
+
raw = @image.imagedata[@offset+x+1]
|
203
216
|
|
204
217
|
unless raw
|
205
218
|
STDERR.puts "[!] #{self.class}: ##@idx: no data at pos #{x}".red
|
data/misc/chars.png
ADDED
Binary file
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$: << "../lib"
|
3
|
+
require 'zpng'
|
4
|
+
|
5
|
+
h = Hash.new{ |k,v| k[v] = "" }
|
6
|
+
a = []
|
7
|
+
|
8
|
+
big_img = ZPNG::Image.load("chars.png").deinterlace
|
9
|
+
|
10
|
+
(big_img.width/13).times do |idx|
|
11
|
+
img = big_img.crop(:x=>idx*13, :y=>0, :width=>13, :height =>big_img.height)
|
12
|
+
s = img.to_ascii(' ##')
|
13
|
+
puts s
|
14
|
+
|
15
|
+
c = (idx+32).chr
|
16
|
+
next if c == "_"
|
17
|
+
n = s.count('#')
|
18
|
+
h[n] << c
|
19
|
+
a[n] ||= ''
|
20
|
+
a[n] << c
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "[.] step1 results:"
|
24
|
+
p a
|
25
|
+
while a.index(nil)
|
26
|
+
prevset = false
|
27
|
+
0.upto(a.size-1) do |i|
|
28
|
+
c = a[i]
|
29
|
+
a[i] = c[0] if c && c.size > 1
|
30
|
+
if !c && a[i-1] && !prevset
|
31
|
+
a[i] = a[i-1]
|
32
|
+
prevset = true
|
33
|
+
else
|
34
|
+
prevset = false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
(a.size-1).downto(0) do |i|
|
38
|
+
c = a[i]
|
39
|
+
a[i] = c[0] if c && c.size > 1
|
40
|
+
if !c && a[i+1] && !prevset
|
41
|
+
a[i] = a[i+1]
|
42
|
+
prevset = true
|
43
|
+
else
|
44
|
+
prevset = false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
puts "[.] normalized:"
|
49
|
+
p a
|
50
|
+
puts
|
51
|
+
|
52
|
+
h.keys.sort.each do |n|
|
53
|
+
printf "[.] %3d: %s\n", n, h[n]
|
54
|
+
end
|
55
|
+
puts
|
56
|
+
|
57
|
+
require 'pp'
|
58
|
+
puts "[.] final array:"
|
59
|
+
puts "a = ["
|
60
|
+
a.each_slice(20).map(&:join).each do |slice|
|
61
|
+
puts " #{slice.inspect},"
|
62
|
+
end
|
63
|
+
puts "].join"
|
data/spec/adam7_spec.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe ZPNG::Adam7Decoder do
|
4
|
+
describe "scanline_width" do
|
5
|
+
{
|
6
|
+
"8x8" => [1,1,2,2,2],
|
7
|
+
"8x16" => [1,1,1,1,2],
|
8
|
+
"16x8" => [2,2,4,4,4],
|
9
|
+
"16x16"=> [2,2,2,2,4],
|
10
|
+
"8x9" => [1,1,1,1,2,2],
|
11
|
+
"9x8" => [2,1,3,2,2,5],
|
12
|
+
"9x9" => [2,2,1,1,3,2]
|
13
|
+
}.each do |dims, slw|
|
14
|
+
it "should be right for #{dims} image" do
|
15
|
+
w,h = dims.split('x').map(&:to_i)
|
16
|
+
img = stub(:width => w, :height => h)
|
17
|
+
adam7 = ZPNG::Adam7Decoder.new(img)
|
18
|
+
slw.size.times.map{ |i| adam7.scanline_width(i) }.should == slw
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "scanlines_count" do
|
24
|
+
{
|
25
|
+
"8x8" => 15,
|
26
|
+
"8x16" => 30,
|
27
|
+
"16x8" => 15,
|
28
|
+
"16x16"=> 30,
|
29
|
+
"8x9" => 19,
|
30
|
+
"9x8" => 15,
|
31
|
+
"9x9" => 19,
|
32
|
+
"1x1" => 1,
|
33
|
+
}.each do |dims, n|
|
34
|
+
it "should be right for #{dims} image" do
|
35
|
+
w,h = dims.split('x').map(&:to_i)
|
36
|
+
img = stub(:width => w, :height => h)
|
37
|
+
adam7 = ZPNG::Adam7Decoder.new(img)
|
38
|
+
adam7.scanlines_count.should == n
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "@pass_starts" do
|
44
|
+
{
|
45
|
+
"8x8" => [0, 0, 1, 2, 3, 5, 7, 11, 15],
|
46
|
+
"8x16" => [0, 0, 2, 4, 6, 10, 14, 22, 30],
|
47
|
+
"16x8" => [0, 0, 1, 2, 3, 5, 7, 11, 15],
|
48
|
+
"16x16"=> [0, 0, 2, 4, 6, 10, 14, 22, 30],
|
49
|
+
"8x9" => [0, 0, 2, 4, 5, 8, 10, 15, 19],
|
50
|
+
"9x8" => [0, 0, 1, 2, 3, 5, 7, 11, 15],
|
51
|
+
"9x9" => [0, 0, 2, 4, 5, 8, 10, 15, 19]
|
52
|
+
}.each do |dims, pst|
|
53
|
+
it "should be right for #{dims} image" do
|
54
|
+
w,h = dims.split('x').map(&:to_i)
|
55
|
+
img = stub(:width => w, :height => h)
|
56
|
+
adam7 = ZPNG::Adam7Decoder.new(img)
|
57
|
+
adam7.instance_variable_get("@pass_starts").should == pst
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/spec/ascii_spec.rb
CHANGED
@@ -45,7 +45,7 @@ describe "ZPNG png2ascii" do
|
|
45
45
|
Dir[File.join(SAMPLES_DIR,'qr_*.png')].each do |fname|
|
46
46
|
describe fname do
|
47
47
|
it "generates a nice ascii img" do
|
48
|
-
ZPNG::Image.new(fname).
|
48
|
+
ZPNG::Image.new(fname).to_ascii('#.').strip.should == ASCII_QR.strip
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
data/spec/color_spec.rb
CHANGED
@@ -5,7 +5,36 @@ describe ZPNG::Color do
|
|
5
5
|
ZPNG::Color::ANSI_COLORS.each do |color_sym|
|
6
6
|
it "finds closest color for #{color_sym}" do
|
7
7
|
color = ZPNG::Color.const_get(color_sym.to_s.upcase)
|
8
|
-
color.
|
8
|
+
color.to_ansi.should == color_sym
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "to_depth" do
|
13
|
+
it "decreases color depth" do
|
14
|
+
c = ZPNG::Color.new 0x10, 0x20, 0x30
|
15
|
+
c = c.to_depth(4)
|
16
|
+
c.depth.should == 4
|
17
|
+
c.r.should == 1
|
18
|
+
c.g.should == 2
|
19
|
+
c.b.should == 3
|
20
|
+
end
|
21
|
+
|
22
|
+
it "increases color depth" do
|
23
|
+
c = ZPNG::Color.new 0,2,3, :depth => 4
|
24
|
+
c = c.to_depth(8)
|
25
|
+
c.depth.should == 8
|
26
|
+
c.r.should == 0
|
27
|
+
c.g.should == 0x20
|
28
|
+
c.b.should == 0x3f
|
29
|
+
end
|
30
|
+
|
31
|
+
it "keeps color depth" do
|
32
|
+
c = ZPNG::Color.new 0x11, 0x22, 0x33
|
33
|
+
c = c.to_depth(8)
|
34
|
+
c.depth.should == 8
|
35
|
+
c.r.should == 0x11
|
36
|
+
c.g.should == 0x22
|
37
|
+
c.b.should == 0x33
|
9
38
|
end
|
10
39
|
end
|
11
40
|
end
|
data/spec/create_image_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Image do
|
|
12
12
|
describe "new( :bpp => #{bpp}, :color => #{color} )" do
|
13
13
|
subject(:img){ _new_img(bpp,color) }
|
14
14
|
it("should export"){ img.export.should start_with(Image::PNG_HDR) }
|
15
|
-
it("should
|
15
|
+
it("should to_ascii") { img.to_ascii.split("\n").size.should == 8 }
|
16
16
|
|
17
17
|
subject{ img.hdr }
|
18
18
|
its(:depth) { should == bpp }
|
@@ -24,7 +24,7 @@ describe Image do
|
|
24
24
|
describe "new( :bpp => 16, :color => false )" do
|
25
25
|
subject(:img){ _new_img(16,false) }
|
26
26
|
it("should export"){ img.export.should start_with(Image::PNG_HDR) }
|
27
|
-
it("should
|
27
|
+
it("should to_ascii") { img.to_ascii.split("\n").size.should == 8 }
|
28
28
|
|
29
29
|
subject{ img.hdr }
|
30
30
|
its(:depth) { should == 8 } # 8 bits per color + 8 per alpha = 16 bpp
|
@@ -39,7 +39,7 @@ describe Image do
|
|
39
39
|
describe "new( :bpp => 24, :color => false )" do
|
40
40
|
subject(:img){ _new_img(24,false) }
|
41
41
|
it("should export"){ img.export.should start_with(Image::PNG_HDR) }
|
42
|
-
it("should
|
42
|
+
it("should to_ascii") { img.to_ascii.split("\n").size.should == 8 }
|
43
43
|
|
44
44
|
subject{ img.hdr }
|
45
45
|
its(:depth) { should == 8 } # each channel depth = 8
|
@@ -49,7 +49,7 @@ describe Image do
|
|
49
49
|
describe "new( :bpp => 24, :color => true )" do
|
50
50
|
subject(:img){ _new_img(24,true) }
|
51
51
|
it("should export"){ img.export.should start_with(Image::PNG_HDR) }
|
52
|
-
it("should
|
52
|
+
it("should to_ascii") { img.to_ascii.split("\n").size.should == 8 }
|
53
53
|
|
54
54
|
subject{ img.hdr }
|
55
55
|
its(:depth) { should == 8 } # each channel depth = 8
|
@@ -59,7 +59,7 @@ describe Image do
|
|
59
59
|
describe "new( :bpp => 32, :color => false )" do
|
60
60
|
subject(:img){ _new_img(32,false) }
|
61
61
|
it("should export"){ img.export.should start_with(Image::PNG_HDR) }
|
62
|
-
it("should
|
62
|
+
it("should to_ascii") { img.to_ascii.split("\n").size.should == 8 }
|
63
63
|
|
64
64
|
subject{ img.hdr }
|
65
65
|
its(:depth) { should == 8 } # each channel depth = 8
|
@@ -69,7 +69,7 @@ describe Image do
|
|
69
69
|
describe "new( :bpp => 32, :color => true )" do
|
70
70
|
subject(:img){ _new_img(32,true) }
|
71
71
|
it("should export"){ img.export.should start_with(Image::PNG_HDR) }
|
72
|
-
it("should
|
72
|
+
it("should to_ascii") { img.to_ascii.split("\n").size.should == 8 }
|
73
73
|
|
74
74
|
subject{ img.hdr }
|
75
75
|
its(:depth) { should == 8 } # each channel depth = 8
|
data/spec/crop_spec.rb
CHANGED
@@ -69,24 +69,24 @@ describe Image do
|
|
69
69
|
|
70
70
|
it "should extract left square" do
|
71
71
|
img.crop! :x => 1, :y => 1, :width => 7, :height => 7
|
72
|
-
img.
|
72
|
+
img.to_ascii('#.').strip.should == QR_SQUARE.strip
|
73
73
|
end
|
74
74
|
|
75
75
|
it "should extract right square" do
|
76
76
|
img.crop! :x => 27, :y => 1, :width => 7, :height => 7
|
77
|
-
img.
|
77
|
+
img.to_ascii('#.').strip.should == QR_SQUARE.strip
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should extract bottom square" do
|
81
81
|
img.crop! :x => 1, :y => 27, :width => 7, :height => 7
|
82
|
-
img.
|
82
|
+
img.to_ascii('#.').strip.should == QR_SQUARE.strip
|
83
83
|
end
|
84
84
|
|
85
85
|
it "keeps whole original image if crop is larger than image" do
|
86
86
|
img2 = img.crop :x => 0, :y => 0, :width => 7000, :height => 7000
|
87
87
|
img2.width.should == img.width
|
88
88
|
img2.height.should == img.height
|
89
|
-
img2.
|
89
|
+
img2.to_ascii.should == img.to_ascii
|
90
90
|
end
|
91
91
|
end
|
92
92
|
end
|
data/spec/modify_spec.rb
CHANGED
@@ -49,7 +49,7 @@ describe "ZPNG modify" do
|
|
49
49
|
img.width.times do |x|
|
50
50
|
img[x,0] = (x%2==0) ? ZPNG::Color::WHITE : ZPNG::Color::BLACK
|
51
51
|
end
|
52
|
-
img.
|
52
|
+
img.to_ascii('#.').strip.should == ASCII_MODIFIED_QR.strip
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
data/spec/running_pixel_spec.rb
CHANGED
data/zpng.gemspec
CHANGED
@@ -5,17 +5,18 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "zpng"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
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-23"
|
13
13
|
s.email = "zed.0xff@gmail.com"
|
14
14
|
s.executables = ["zpng"]
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"LICENSE.txt",
|
17
17
|
"README.md",
|
18
|
-
"README.md.tpl"
|
18
|
+
"README.md.tpl",
|
19
|
+
"TODO"
|
19
20
|
]
|
20
21
|
s.files = [
|
21
22
|
".document",
|
@@ -26,6 +27,7 @@ Gem::Specification.new do |s|
|
|
26
27
|
"README.md",
|
27
28
|
"README.md.tpl",
|
28
29
|
"Rakefile",
|
30
|
+
"TODO",
|
29
31
|
"VERSION",
|
30
32
|
"bin/zpng",
|
31
33
|
"lib/zpng.rb",
|
@@ -34,9 +36,12 @@ Gem::Specification.new do |s|
|
|
34
36
|
"lib/zpng/chunk.rb",
|
35
37
|
"lib/zpng/cli.rb",
|
36
38
|
"lib/zpng/color.rb",
|
39
|
+
"lib/zpng/deep_copyable.rb",
|
37
40
|
"lib/zpng/image.rb",
|
38
41
|
"lib/zpng/scan_line.rb",
|
39
42
|
"lib/zpng/string_ext.rb",
|
43
|
+
"misc/chars.png",
|
44
|
+
"misc/gen_ascii_map.rb",
|
40
45
|
"samples/captcha_4bpp.png",
|
41
46
|
"samples/modify.rb",
|
42
47
|
"samples/qr_aux_chunks.png",
|
@@ -47,6 +52,7 @@ Gem::Specification.new do |s|
|
|
47
52
|
"samples/qr_plte_bw.png",
|
48
53
|
"samples/qr_rgb.png",
|
49
54
|
"samples/qr_rgba.png",
|
55
|
+
"spec/adam7_spec.rb",
|
50
56
|
"spec/ascii_spec.rb",
|
51
57
|
"spec/color_spec.rb",
|
52
58
|
"spec/create_image_spec.rb",
|
metadata
CHANGED
@@ -2,14 +2,14 @@
|
|
2
2
|
name: zpng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
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-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
prerelease: false
|
@@ -100,6 +100,7 @@ extra_rdoc_files:
|
|
100
100
|
- LICENSE.txt
|
101
101
|
- README.md
|
102
102
|
- README.md.tpl
|
103
|
+
- TODO
|
103
104
|
files:
|
104
105
|
- .document
|
105
106
|
- .rspec
|
@@ -109,6 +110,7 @@ files:
|
|
109
110
|
- README.md
|
110
111
|
- README.md.tpl
|
111
112
|
- Rakefile
|
113
|
+
- TODO
|
112
114
|
- VERSION
|
113
115
|
- bin/zpng
|
114
116
|
- lib/zpng.rb
|
@@ -117,9 +119,12 @@ files:
|
|
117
119
|
- lib/zpng/chunk.rb
|
118
120
|
- lib/zpng/cli.rb
|
119
121
|
- lib/zpng/color.rb
|
122
|
+
- lib/zpng/deep_copyable.rb
|
120
123
|
- lib/zpng/image.rb
|
121
124
|
- lib/zpng/scan_line.rb
|
122
125
|
- lib/zpng/string_ext.rb
|
126
|
+
- misc/chars.png
|
127
|
+
- misc/gen_ascii_map.rb
|
123
128
|
- samples/captcha_4bpp.png
|
124
129
|
- samples/modify.rb
|
125
130
|
- samples/qr_aux_chunks.png
|
@@ -130,6 +135,7 @@ files:
|
|
130
135
|
- samples/qr_plte_bw.png
|
131
136
|
- samples/qr_rgb.png
|
132
137
|
- samples/qr_rgba.png
|
138
|
+
- spec/adam7_spec.rb
|
133
139
|
- spec/ascii_spec.rb
|
134
140
|
- spec/color_spec.rb
|
135
141
|
- spec/create_image_spec.rb
|
@@ -154,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
154
160
|
version: '0'
|
155
161
|
segments:
|
156
162
|
- 0
|
157
|
-
hash: -
|
163
|
+
hash: -93398394471482814
|
158
164
|
none: false
|
159
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
166
|
requirements:
|