zpng 0.1.2 → 0.2.0

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/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
- -U, --unpack-imagedata unpack Image Data (IDAT) chunk(s), output to stdout
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, idx=0, interlace=0, filter=0, compression=0, height=35, width=35, depth=1, color=0> CRC OK
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
- [#<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>]
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
@@ -0,0 +1,10 @@
1
+ ways to hide info in PNG:
2
+ * IHDR: longer than 13 bytes
3
+ * IEND:
4
+ * longer than 0 bytes
5
+ * data after IEND
6
+ * TEXT chunks
7
+ * zTXT chunks
8
+ * IDAT:
9
+ * data after last scanline
10
+ * last bits in scanline when bpp%8 != 0
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
data/lib/zpng.rb CHANGED
@@ -3,6 +3,7 @@ require 'zlib'
3
3
  require 'stringio'
4
4
 
5
5
  require 'zpng/string_ext'
6
+ require 'zpng/deep_copyable'
6
7
 
7
8
  require 'zpng/color'
8
9
  require 'zpng/block'
@@ -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
- def initialize image
6
- @image = image
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
- #image.width/8*(2**(idx/2))
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 + image.height*11/8]
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 + image.height*7/8]
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 + image.height/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 + image.height*2/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 + image.height*3/8]
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 + image.height*5/8]
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
@@ -2,6 +2,8 @@ module ZPNG
2
2
  class Chunk
3
3
  attr_accessor :size, :type, :data, :crc, :idx
4
4
 
5
+ include DeepCopyable
6
+
5
7
  def self.from_stream io
6
8
  size, type = io.read(8).unpack('Na4')
7
9
  io.seek(-8,IO::SEEK_CUR)
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 "-U", "--unpack-imagedata", "unpack Image Data (IDAT) chunk(s), output to stdout" do
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
- @need_fname_header = (argv.size > 1)
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].closest_ansi_color)
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].to_s)
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
- pp @img.scanlines
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 < Struct.new(:r,:g,:b,:a)
2
+ class Color
3
+ attr_accessor :r, :g, :b, :a
4
+ attr_accessor :depth, :alpha_depth
3
5
 
4
- def initialize *args
5
- super
6
- self.a ||= 0xff
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= v; self.a = v; end
21
+ def alpha= a; @a=a; end
11
22
 
12
- BLACK = Color.new(0 , 0, 0, 255)
13
- WHITE = Color.new(255,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, 255)
16
- GREEN = Color.new(0 ,255, 0, 255)
17
- BLUE = Color.new(0 , 0,255, 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, 255)
20
- CYAN = Color.new( 0,255,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, 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, alpha = nil
57
- Color.new value,value,value, alpha
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 h={}
66
- white = h[:white] || ' '
67
- black = h[:black] || '#'
68
- unknown = h[:unknown] || '?'
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
- self.white?? white : (self.black?? black : unknown)
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
- def inspect
78
- if r && g && b && a
79
- "#<ZPNG::Color #%02x%02x%02x a=%d>" % [r,g,b,a]
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
- rs = r ? "%02x" % r : "??"
82
- gs = g ? "%02x" % g : "??"
83
- bs = b ? "%02x" % b : "??"
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
@@ -0,0 +1,7 @@
1
+ module ZPNG
2
+ module DeepCopyable
3
+ def deep_copy
4
+ Marshal.load(Marshal.dump(self))
5
+ end
6
+ end
7
+ 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 to_s h={}
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(h) }.join }.join("\n")
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.to_s(h) }.join("\n")
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
- Marshal.load(Marshal.dump(self)).crop!(params)
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
@@ -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 to_s h={}
70
+ def to_ascii *args
71
71
  @image.width.times.map do |i|
72
- decode_pixel(i).to_ascii(h)
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
- raw.unpack 'C2'
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
- # RGBA
151
- return Color.new(*raw.unpack('C4'))
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
- if [1,2,4].include?(@bpp)
158
- #color should be extended to a 8-bit range
159
- if color%2 == 0
160
- color <<= (8-@bpp)
161
- else
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
- nbytes.times do |i|
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"
@@ -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).to_s(:white => '.', :black => '#').strip.should == ASCII_QR.strip
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.closest_ansi_color.should == color_sym
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
@@ -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 to_s") { img.to_s.strip.split("\n").size.should == 8 }
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 to_s") { img.to_s.strip.split("\n").size.should == 8 }
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 to_s") { img.to_s.strip.split("\n").size.should == 8 }
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 to_s") { img.to_s.strip.split("\n").size.should == 8 }
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 to_s") { img.to_s.strip.split("\n").size.should == 8 }
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 to_s") { img.to_s.strip.split("\n").size.should == 8 }
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.to_s(:white => '.', :black => '#').strip.should == QR_SQUARE.strip
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.to_s(:white => '.', :black => '#').strip.should == QR_SQUARE.strip
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.to_s(:white => '.', :black => '#').strip.should == QR_SQUARE.strip
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.to_s.should == img.to_s
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.to_s(:white => '.', :black => '#').strip.should == ASCII_MODIFIED_QR.strip
52
+ img.to_ascii('#.').strip.should == ASCII_MODIFIED_QR.strip
53
53
  end
54
54
  end
55
55
  end
@@ -29,7 +29,7 @@ describe Image do
29
29
 
30
30
  s = '#'*16
31
31
  s[x] = ' '
32
- img.to_s.should == s
32
+ img.to_ascii('# ').should == s
33
33
 
34
34
  # fname = "out-#{x}-#{bpp}-#{color}.png"
35
35
  # img.save fname
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.1.2"
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-21"
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.1.2
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-21 00:00:00.000000000 Z
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: -657082677898355514
163
+ hash: -93398394471482814
158
164
  none: false
159
165
  required_rubygems_version: !ruby/object:Gem::Requirement
160
166
  requirements: