termin-ansicolor 1.3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -0
- data/.travis.yml +11 -0
- data/CHANGES +60 -0
- data/COPYING +340 -0
- data/Gemfile +5 -0
- data/README.rdoc +55 -0
- data/Rakefile +34 -0
- data/VERSION +1 -0
- data/bin/cdiff +19 -0
- data/bin/colortab +48 -0
- data/bin/decolor +12 -0
- data/bin/term_display +91 -0
- data/bin/term_mandel +52 -0
- data/examples/ColorTest.gif +0 -0
- data/examples/Mona_Lisa.jpg +0 -0
- data/examples/Stilleben.jpg +0 -0
- data/examples/example.rb +92 -0
- data/examples/lambda-red-plain.ppm +135 -0
- data/examples/lambda-red.png +0 -0
- data/examples/lambda-red.ppm +4 -0
- data/examples/pacman.jpg +0 -0
- data/examples/smiley.png +0 -0
- data/examples/wool.jpg +0 -0
- data/lib/termin/ansicolor.rb +247 -0
- data/lib/termin/ansicolor/.keep +0 -0
- data/lib/termin/ansicolor/attribute.rb +143 -0
- data/lib/termin/ansicolor/ppm_reader.rb +96 -0
- data/lib/termin/ansicolor/rgb_color_metrics.rb +161 -0
- data/lib/termin/ansicolor/rgb_triple.rb +121 -0
- data/lib/termin/ansicolor/version.rb +8 -0
- data/term-ansicolor.gemspec +41 -0
- data/tests/ansicolor_test.rb +133 -0
- data/tests/attribute_test.rb +73 -0
- data/tests/ppm_reader_test.rb +46 -0
- data/tests/rgb_color_metrics_test.rb +100 -0
- data/tests/rgb_triple_test.rb +71 -0
- data/tests/test_helper.rb +8 -0
- metadata +146 -0
Binary file
|
@@ -0,0 +1,4 @@
|
|
1
|
+
P6
|
2
|
+
44 22
|
3
|
+
255
|
4
|
+
������������������������������漼嶶嶶漻�����������������������������������������������������������������������������������������������������������������"��������~}����������������������������������������������������������������������������������������������������C@���% �DA�`_�[Y�41����3/���������������������������������������������������������������������������������������������㸸��|{�������������������������RP��$ �������������������������������������������������������������������������������������������������������������������������������vu��/+�������������������������������������������������������������������������������������������������������������������������������ba��JH�������������������������������������������������������������������������������������������������������������������������������)%��ih������������������������������������������������������������������������������������������������������������������������ג����Չ�������������������������������������������������������������������������������������������������������������������ԅ������ݩ��������������������������������������������������������������������������������������������������������������vu�����������������������������������������������������������������������������������������������������������������hg������� ��,(����������������������������������������������������������������������������������������������������ZY�������ig����\[��GD����������������������������������������������������������������������������������������������MK�������xv����������@=��ed����������������������������������������������������������������������������������������@>������Շ�����������������&"�Ԅ�����������������������������������������������������������������������������������51������٘������������������������ܤ�����������������������������������������������������������������������������)$������ݧ�������������������������ۢ������������������������������������������������������������������������忿� ������㶶������������������������������ԃ���)#����������������������������������������������������������������������&"����������������������������������������db��*&������������������������֍���������������������������ܣ��������1.����������������������������������������������EC���`^থ达������᪪�_]��Փ����������������������ؕ��������>;����������������������������������������������������HE����������OL���������������������щ��!�!�!�!�!�"�NL���������������������������������������������������������ߤ��KI������ZX������������������������������������������������������������������������������������������������������������������������������������������������
|
data/examples/pacman.jpg
ADDED
Binary file
|
data/examples/smiley.png
ADDED
Binary file
|
data/examples/wool.jpg
ADDED
Binary file
|
@@ -0,0 +1,247 @@
|
|
1
|
+
module Termin
|
2
|
+
|
3
|
+
# The ANSIColor module can be used for namespacing and mixed into your own
|
4
|
+
# classes.
|
5
|
+
module ANSIColor
|
6
|
+
require 'termin/ansicolor/version'
|
7
|
+
require 'termin/ansicolor/attribute'
|
8
|
+
require 'termin/ansicolor/rgb_triple'
|
9
|
+
require 'termin/ansicolor/ppm_reader'
|
10
|
+
|
11
|
+
Attribute.set :clear , 0 # String#clear is already used to empty string in Ruby 1.9
|
12
|
+
Attribute.set :reset , 0 # synonym for :clear
|
13
|
+
Attribute.set :bold , 1
|
14
|
+
Attribute.set :dark , 2
|
15
|
+
Attribute.set :faint , 2
|
16
|
+
Attribute.set :italic , 3 # not widely implemented
|
17
|
+
Attribute.set :underline , 4
|
18
|
+
Attribute.set :underscore , 4 # synonym for :underline
|
19
|
+
Attribute.set :blink , 5
|
20
|
+
Attribute.set :rapid_blink , 6 # not widely implemented
|
21
|
+
Attribute.set :negative , 7 # no reverse because of String#reverse
|
22
|
+
Attribute.set :concealed , 8
|
23
|
+
Attribute.set :strikethrough , 9 # not widely implemented
|
24
|
+
|
25
|
+
Attribute.set :black , 30
|
26
|
+
Attribute.set :red , 31
|
27
|
+
Attribute.set :green , 32
|
28
|
+
Attribute.set :yellow , 33
|
29
|
+
Attribute.set :blue , 34
|
30
|
+
Attribute.set :magenta , 35
|
31
|
+
Attribute.set :cyan , 36
|
32
|
+
Attribute.set :white , 37
|
33
|
+
|
34
|
+
Attribute.set :on_black , 40
|
35
|
+
Attribute.set :on_red , 41
|
36
|
+
Attribute.set :on_green , 42
|
37
|
+
Attribute.set :on_yellow , 43
|
38
|
+
Attribute.set :on_blue , 44
|
39
|
+
Attribute.set :on_magenta , 45
|
40
|
+
Attribute.set :on_cyan , 46
|
41
|
+
Attribute.set :on_white , 47
|
42
|
+
|
43
|
+
# High intensity, aixterm (works in OS X)
|
44
|
+
Attribute.set :intense_black , 90
|
45
|
+
Attribute.set :bright_black , 90
|
46
|
+
Attribute.set :intense_red , 91
|
47
|
+
Attribute.set :bright_red , 91
|
48
|
+
Attribute.set :intense_green , 92
|
49
|
+
Attribute.set :bright_green , 92
|
50
|
+
Attribute.set :intense_yellow , 93
|
51
|
+
Attribute.set :bright_yellow , 93
|
52
|
+
Attribute.set :intense_blue , 94
|
53
|
+
Attribute.set :bright_blue , 94
|
54
|
+
Attribute.set :intense_magenta , 95
|
55
|
+
Attribute.set :bright_magenta , 95
|
56
|
+
Attribute.set :intense_cyan , 96
|
57
|
+
Attribute.set :bright_cyan , 96
|
58
|
+
Attribute.set :intense_white , 97
|
59
|
+
Attribute.set :bright_white , 97
|
60
|
+
|
61
|
+
# High intensity background, aixterm (works in OS X)
|
62
|
+
Attribute.set :on_intense_black , 100
|
63
|
+
Attribute.set :on_bright_black , 100
|
64
|
+
Attribute.set :on_intense_red , 101
|
65
|
+
Attribute.set :on_bright_red , 101
|
66
|
+
Attribute.set :on_intense_green , 102
|
67
|
+
Attribute.set :on_bright_green , 102
|
68
|
+
Attribute.set :on_intense_yellow , 103
|
69
|
+
Attribute.set :on_bright_yellow , 103
|
70
|
+
Attribute.set :on_intense_blue , 104
|
71
|
+
Attribute.set :on_bright_blue , 104
|
72
|
+
Attribute.set :on_intense_magenta, 105
|
73
|
+
Attribute.set :on_bright_magenta , 105
|
74
|
+
Attribute.set :on_intense_cyan , 106
|
75
|
+
Attribute.set :on_bright_cyan , 106
|
76
|
+
Attribute.set :on_intense_white , 107
|
77
|
+
Attribute.set :on_bright_white , 107
|
78
|
+
|
79
|
+
Attribute.set :color0, 0, :html => '#000000'
|
80
|
+
Attribute.set :color1, 1, :html => '#800000'
|
81
|
+
Attribute.set :color2, 2, :html => '#808000'
|
82
|
+
Attribute.set :color3, 3, :html => '#808000'
|
83
|
+
Attribute.set :color4, 4, :html => '#000080'
|
84
|
+
Attribute.set :color5, 5, :html => '#800080'
|
85
|
+
Attribute.set :color6, 6, :html => '#008080'
|
86
|
+
Attribute.set :color7, 7, :html => '#c0c0c0'
|
87
|
+
|
88
|
+
Attribute.set :color8, 8, :html => '#808080'
|
89
|
+
Attribute.set :color9, 9, :html => '#ff0000'
|
90
|
+
Attribute.set :color10, 10, :html => '#00ff00'
|
91
|
+
Attribute.set :color11, 11, :html => '#ffff00'
|
92
|
+
Attribute.set :color12, 12, :html => '#0000ff'
|
93
|
+
Attribute.set :color13, 13, :html => '#ff00ff'
|
94
|
+
Attribute.set :color14, 14, :html => '#00ffff'
|
95
|
+
Attribute.set :color15, 15, :html => '#ffffff'
|
96
|
+
|
97
|
+
steps = [ 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff ]
|
98
|
+
|
99
|
+
for i in 16..231
|
100
|
+
red, green, blue = (i - 16).to_s(6).rjust(3, '0').each_char.map { |c| steps[c.to_i] }
|
101
|
+
Attribute.set "color#{i}", i, :red => red, :green => green, :blue => blue
|
102
|
+
end
|
103
|
+
|
104
|
+
grey = 8
|
105
|
+
for i in 232..255
|
106
|
+
Attribute.set "color#{i}", i, :red => grey, :green => grey, :blue => grey
|
107
|
+
grey += 10
|
108
|
+
end
|
109
|
+
|
110
|
+
Attribute.set :on_color0, 0, :html => '#000000'
|
111
|
+
Attribute.set :on_color1, 1, :html => '#800000'
|
112
|
+
Attribute.set :on_color2, 2, :html => '#808000'
|
113
|
+
Attribute.set :on_color3, 3, :html => '#808000'
|
114
|
+
Attribute.set :on_color4, 4, :html => '#000080'
|
115
|
+
Attribute.set :on_color5, 5, :html => '#800080'
|
116
|
+
Attribute.set :on_color6, 6, :html => '#008080'
|
117
|
+
Attribute.set :on_color7, 7, :html => '#c0c0c0'
|
118
|
+
|
119
|
+
Attribute.set :on_color8, 8, :html => '#808080'
|
120
|
+
Attribute.set :on_color9, 9, :html => '#ff0000'
|
121
|
+
Attribute.set :on_color10, 10, :html => '#00ff00'
|
122
|
+
Attribute.set :on_color11, 11, :html => '#ffff00'
|
123
|
+
Attribute.set :on_color12, 12, :html => '#0000ff'
|
124
|
+
Attribute.set :on_color13, 13, :html => '#ff00ff'
|
125
|
+
Attribute.set :on_color14, 14, :html => '#00ffff'
|
126
|
+
Attribute.set :on_color15, 15, :html => '#ffffff'
|
127
|
+
|
128
|
+
steps = [ 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff ]
|
129
|
+
|
130
|
+
for i in 16..231
|
131
|
+
red, green, blue = (i - 16).to_s(6).rjust(3, '0').each_char.map { |c| steps[c.to_i] }
|
132
|
+
Attribute.set "on_color#{i}", i, :red => red, :green => green, :blue => blue
|
133
|
+
end
|
134
|
+
|
135
|
+
grey = 8
|
136
|
+
for i in 232..255
|
137
|
+
Attribute.set "on_color#{i}", i, :red => grey, :green => grey, :blue => grey
|
138
|
+
grey += 10
|
139
|
+
end
|
140
|
+
|
141
|
+
# :stopdoc:
|
142
|
+
ATTRIBUTE_NAMES = Attribute.named_attributes.map(&:name)
|
143
|
+
# :startdoc:
|
144
|
+
|
145
|
+
# Returns true if Termin::ANSIColor supports the +feature+.
|
146
|
+
#
|
147
|
+
# The feature :clear, that is mixing the clear color attribute into String,
|
148
|
+
# is only supported on ruby implementations, that do *not* already
|
149
|
+
# implement the String#clear method. It's better to use the reset color
|
150
|
+
# attribute instead.
|
151
|
+
def support?(feature)
|
152
|
+
case feature
|
153
|
+
when :clear
|
154
|
+
!String.instance_methods(false).map(&:to_sym).include?(:clear)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
# Returns true, if the coloring function of this module
|
158
|
+
# is switched on, false otherwise.
|
159
|
+
def self.coloring?
|
160
|
+
@coloring
|
161
|
+
end
|
162
|
+
|
163
|
+
# Turns the coloring on or off globally, so you can easily do
|
164
|
+
# this for example:
|
165
|
+
# Termin::ANSIColor::coloring = STDOUT.isatty
|
166
|
+
def self.coloring=(val)
|
167
|
+
@coloring = val
|
168
|
+
end
|
169
|
+
self.coloring = true
|
170
|
+
|
171
|
+
def self.create_color_method(color_name, color_value)
|
172
|
+
module_eval <<-EOT
|
173
|
+
def #{color_name}(string = nil, &block)
|
174
|
+
color(:#{color_name}, string, &block)
|
175
|
+
end
|
176
|
+
EOT
|
177
|
+
self
|
178
|
+
end
|
179
|
+
|
180
|
+
for attribute in Attribute.named_attributes
|
181
|
+
create_color_method(attribute.name, attribute.code)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Regular expression that is used to scan for ANSI-Attributes while
|
185
|
+
# uncoloring strings.
|
186
|
+
COLORED_REGEXP = /\e\[(?:(?:[349]|10)[0-7]|[0-9]|[34]8;5;\d{1,3})?m/
|
187
|
+
|
188
|
+
# Returns an uncolored version of the string, that is all
|
189
|
+
# ANSI-Attributes are stripped from the string.
|
190
|
+
def uncolor(string = nil) # :yields:
|
191
|
+
if block_given?
|
192
|
+
yield.to_str.gsub(COLORED_REGEXP, '')
|
193
|
+
elsif string.respond_to?(:to_str)
|
194
|
+
string.to_str.gsub(COLORED_REGEXP, '')
|
195
|
+
elsif respond_to?(:to_str)
|
196
|
+
to_str.gsub(COLORED_REGEXP, '')
|
197
|
+
else
|
198
|
+
''
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
alias uncolored uncolor
|
203
|
+
|
204
|
+
# Return +string+ or the result string of the given +block+ colored with
|
205
|
+
# color +name+. If string isn't a string only the escape sequence to switch
|
206
|
+
# on the color +name+ is returned.
|
207
|
+
def color(name, string = nil, &block)
|
208
|
+
attribute = Attribute[name] or raise ArgumentError, "unknown attribute #{name.inspect}"
|
209
|
+
result = ''
|
210
|
+
result << "\e[#{attribute.code}m" if Termin::ANSIColor.coloring?
|
211
|
+
if block_given?
|
212
|
+
result << yield
|
213
|
+
elsif string.respond_to?(:to_str)
|
214
|
+
result << string.to_str
|
215
|
+
elsif respond_to?(:to_str)
|
216
|
+
result << to_str
|
217
|
+
else
|
218
|
+
return result #only switch on
|
219
|
+
end
|
220
|
+
result << "\e[0m" if Termin::ANSIColor.coloring?
|
221
|
+
result
|
222
|
+
end
|
223
|
+
|
224
|
+
def on_color(name, string = nil, &block)
|
225
|
+
attribute = Attribute[name] or raise ArgumentError, "unknown attribute #{name.inspect}"
|
226
|
+
color("on_#{attribute.name}", string, &block)
|
227
|
+
end
|
228
|
+
|
229
|
+
class << self
|
230
|
+
# Returns an array of all Termin::ANSIColor attributes as symbols.
|
231
|
+
def term_ansicolor_attributes
|
232
|
+
::Termin::ANSIColor::ATTRIBUTE_NAMES
|
233
|
+
end
|
234
|
+
|
235
|
+
alias attributes term_ansicolor_attributes
|
236
|
+
end
|
237
|
+
|
238
|
+
# Returns an array of all Termin::ANSIColor attributes as symbols.
|
239
|
+
def term_ansicolor_attributes
|
240
|
+
::Termin::ANSIColor.term_ansicolor_attributes
|
241
|
+
end
|
242
|
+
|
243
|
+
alias attributes term_ansicolor_attributes
|
244
|
+
|
245
|
+
extend self
|
246
|
+
end
|
247
|
+
end
|
File without changes
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Termin
|
2
|
+
module ANSIColor
|
3
|
+
class Attribute
|
4
|
+
@__store__ = {}
|
5
|
+
|
6
|
+
if RUBY_VERSION < '1.9'
|
7
|
+
@__order__ = []
|
8
|
+
|
9
|
+
def self.set(name, code, options = {})
|
10
|
+
name = name.to_sym
|
11
|
+
result = @__store__[name] = new(name, code, options)
|
12
|
+
@__order__ << name
|
13
|
+
@rgb_colors = nil
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.attributes(&block)
|
18
|
+
@__order__.map { |name| @__store__[name] }
|
19
|
+
end
|
20
|
+
else
|
21
|
+
def self.set(name, code, options = {})
|
22
|
+
name = name.to_sym
|
23
|
+
result = @__store__[name] = new(name, code, options)
|
24
|
+
@rgb_colors = nil
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.attributes(&block)
|
29
|
+
@__store__.each_value(&block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.[](name)
|
34
|
+
case
|
35
|
+
when self === name then name
|
36
|
+
when Array === name then nearest_rgb_color name
|
37
|
+
when name.to_s =~ /\A(on_)?(\d+)\z/ then get "#$1color#$2"
|
38
|
+
when name.to_s =~ /\A#([0-9a-f]{3}){1,2}\z/i then nearest_rgb_color name
|
39
|
+
when name.to_s =~ /\Aon_#([0-9a-f]{3}){1,2}\z/i then nearest_rgb_on_color name
|
40
|
+
else get name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.get(name)
|
45
|
+
@__store__[name.to_sym]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.rgb_colors(&block)
|
49
|
+
@rgb_colors ||= attributes.select(&:rgb_color?).each(&block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.named_attributes(&block)
|
53
|
+
@named_attributes ||= attributes.reject(&:rgb_color?).each(&block)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.nearest_rgb_color(color, options = {})
|
57
|
+
rgb = RGBTriple[color]
|
58
|
+
colors = rgb_colors
|
59
|
+
if options.key?(:gray) && !options[:gray]
|
60
|
+
colors = colors.reject(&:gray?)
|
61
|
+
end
|
62
|
+
colors.reject(&:background?).min_by { |c| c.distance_to(rgb, options) }
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.nearest_rgb_on_color(color, options = {})
|
66
|
+
rgb = RGBTriple[color]
|
67
|
+
colors = rgb_colors
|
68
|
+
if options.key?(:gray) && !options[:gray]
|
69
|
+
colors = colors.reject(&:gray?)
|
70
|
+
end
|
71
|
+
colors.select(&:background?).min_by { |c| c.distance_to(rgb, options) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def initialize(name, code, options = {})
|
75
|
+
@name = name.to_sym
|
76
|
+
@code = code.to_s
|
77
|
+
if html = options[:html]
|
78
|
+
@rgb = RGBTriple.from_html(html)
|
79
|
+
elsif !options.empty?
|
80
|
+
@rgb = RGBTriple.from_hash(options)
|
81
|
+
else
|
82
|
+
@rgb = nil # prevent instance variable not initialized warnings
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
attr_reader :name
|
87
|
+
|
88
|
+
def code
|
89
|
+
if rgb_color?
|
90
|
+
background? ? "48;5;#{@code}" : "38;5;#{@code}"
|
91
|
+
else
|
92
|
+
@code
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def apply(string = nil, &block)
|
97
|
+
::Termin::ANSIColor.color(self, string, &block)
|
98
|
+
end
|
99
|
+
|
100
|
+
def background?
|
101
|
+
@name.to_s.start_with?('on_')
|
102
|
+
end
|
103
|
+
|
104
|
+
attr_reader :rgb
|
105
|
+
|
106
|
+
def rgb_color?
|
107
|
+
!!@rgb
|
108
|
+
end
|
109
|
+
|
110
|
+
def gray?
|
111
|
+
rgb_color? && to_rgb_triple.gray?
|
112
|
+
end
|
113
|
+
|
114
|
+
def to_rgb_triple
|
115
|
+
@rgb
|
116
|
+
end
|
117
|
+
|
118
|
+
def distance_to(other, options = {})
|
119
|
+
if our_rgb = to_rgb_triple and
|
120
|
+
other.respond_to?(:to_rgb_triple) and
|
121
|
+
other_rgb = other.to_rgb_triple
|
122
|
+
then
|
123
|
+
our_rgb.distance_to(other_rgb, options)
|
124
|
+
else
|
125
|
+
1 / 0.0
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def gradient_to(other, options = {})
|
130
|
+
if our_rgb = to_rgb_triple and
|
131
|
+
other.respond_to?(:to_rgb_triple) and
|
132
|
+
other_rgb = other.to_rgb_triple
|
133
|
+
then
|
134
|
+
our_rgb.gradient_to(other_rgb, options).map do |rgb_triple|
|
135
|
+
self.class.nearest_rgb_color(rgb_triple, options)
|
136
|
+
end
|
137
|
+
else
|
138
|
+
[]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module Termin
|
2
|
+
module ANSIColor
|
3
|
+
class PPMReader
|
4
|
+
include Termin::ANSIColor
|
5
|
+
|
6
|
+
def initialize(io, options = {})
|
7
|
+
@io = io
|
8
|
+
@options = options
|
9
|
+
@buffer = ''
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset_io
|
13
|
+
begin
|
14
|
+
@io.rewind
|
15
|
+
rescue Errno::ESPIPE
|
16
|
+
end
|
17
|
+
parse_header
|
18
|
+
end
|
19
|
+
|
20
|
+
def each_row
|
21
|
+
reset_io
|
22
|
+
@height.times do
|
23
|
+
yield parse_row
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_a
|
28
|
+
enum_for(:each_row).to_a
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
result = ''
|
33
|
+
each_row do |row|
|
34
|
+
last_pixel = nil
|
35
|
+
for pixel in row
|
36
|
+
if pixel != last_pixel
|
37
|
+
color = Attribute.nearest_rgb_color(pixel, @options)
|
38
|
+
result << on_color(color)
|
39
|
+
last_pixel = pixel
|
40
|
+
end
|
41
|
+
result << ' '
|
42
|
+
end
|
43
|
+
result << reset << "\n"
|
44
|
+
end
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def parse_row
|
51
|
+
row = []
|
52
|
+
@width.times do
|
53
|
+
row << parse_next_pixel
|
54
|
+
end
|
55
|
+
row
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_next_pixel
|
59
|
+
pixel = nil
|
60
|
+
case @type
|
61
|
+
when 3
|
62
|
+
@buffer.empty? and @buffer << next_line
|
63
|
+
@buffer.sub!(/(\d+)\s+(\d+)\s+(\d+)\s*/) do
|
64
|
+
pixel = [ $1.to_i, $2.to_i, $3.to_i ]
|
65
|
+
''
|
66
|
+
end
|
67
|
+
when 6
|
68
|
+
@buffer.size < 3 and @buffer << @io.read(8192)
|
69
|
+
pixel = @buffer.slice!(0, 3).unpack('C3')
|
70
|
+
end
|
71
|
+
pixel
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_header
|
75
|
+
(line = next_line) =~ /^P([36])$/ or raise "unknown type #{line.to_s.chomp.inspect}"
|
76
|
+
@type = $1.to_i
|
77
|
+
|
78
|
+
if next_line =~ /^(\d+)\s+(\d+)$/
|
79
|
+
@width, @height = $1.to_i, $2.to_i
|
80
|
+
else
|
81
|
+
raise "missing dimensions"
|
82
|
+
end
|
83
|
+
|
84
|
+
unless next_line =~ /^255$/
|
85
|
+
raise "only 255 max color images allowed"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def next_line
|
90
|
+
while line = @io.gets and line =~ /^#|^\s$/
|
91
|
+
end
|
92
|
+
line
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|