class Term::ANSIColor::PPMReader
def initialize(io, options = {})
def initialize(io, options = {}) @io = io @options = options @buffer = ''.dup if options[:true_coloring] @color = -> pixel { on_color Attribute.true_color(pixel, @options) } else @color = -> pixel { on_color Attribute.nearest_rgb_color(pixel, @options) } end end
def next_line
def next_line while line = @io.gets and line =~ /^#|^\s$/ end line end
def parse_header
def parse_header (line = next_line) =~ /^P([36])$/ or raise "unknown type #{line.to_s.chomp.inspect}" @type = $1.to_i if next_line =~ /^(\d+)\s+(\d+)$/ @width, @height = $1.to_i, $2.to_i else raise "missing dimensions" end unless next_line =~ /^255$/ raise "only 255 max color images allowed" end end
def parse_next_pixel
def parse_next_pixel pixel = nil case @type when 3 @buffer.empty? and @buffer << next_line @buffer.sub!(/(\d+)\s+(\d+)\s+(\d+)\s*/) do pixel = [ $1.to_i, $2.to_i, $3.to_i ] '' end when 6 @buffer.size < 3 and @buffer << @io.read(8192) pixel = @buffer.slice!(0, 3).unpack('C3') end pixel end
def parse_row
def parse_row @width.times.map { parse_next_pixel } end
def reset_io
def reset_io begin @io.rewind rescue Errno::ESPIPE end parse_header end
def rows
def rows reset_io Enumerator.new do |yielder| @height.times do yielder.yield parse_row end end end
def to_a
def to_a rows.to_a end
def to_s
def to_s rows.map do |row| last_pixel = nil row.map do |pixel| if pixel != last_pixel last_pixel = pixel @color.(pixel) << ' ' else ' ' end end.join << reset << ?\n end.join end