Raster graphics operations/Ruby: Difference between revisions

Content added Content deleted
m (→‎The Code: improve iterat)
mNo edit summary
Line 133: Line 133:
ios.puts format, "#{@width} #{@height}", "255"
ios.puts format, "#{@width} #{@height}", "255"
ios.binmode if PIXMAP_BINARY_FORMATS.include?(format)
ios.binmode if PIXMAP_BINARY_FORMATS.include?(format)
@height.times do |y|
each_pixel do |x, y|
@width.times do |x|
case format
when "P3" then ios.print @data[x][y].values.join(" "),"\n"
case format
when "P3" then ios.print @data[x][y].values.join(" "),"\n"
when "P6" then ios.print @data[x][y].values.pack('C3')
when "P6" then ios.print @data[x][y].values.pack('C3')
end
end
end
end
end
Line 164: Line 162:
pipe.close rescue false
pipe.close rescue false
end
end
end

def save_as_png(filename)
require 'chunky_png'
#require 'stringio'
stream = StringIO.new("", "r+")
each_pixel {|x, y| stream << self[x, y].values.pack("ccc")}
stream.seek(0)
ChunkyPNG::Canvas.extend(ChunkyPNG::Canvas::StreamImporting)
canvas = ChunkyPNG::Canvas.from_rgb_stream(width, height, stream)
canvas.to_image.save(filename)
end
end


Line 183: Line 192:


bitmap = self.new(width, height)
bitmap = self.new(width, height)
height.times do |y|
bitmap.each_pixel do |x,y|
width.times do |x|
# read 3 bytes
# read 3 bytes
red, green, blue = case format
red, green, blue = case format
when 'P3' then ios.gets.chomp.split
when 'P3' then ios.gets.chomp.split
when 'P6' then ios.read(3).unpack('C3')
when 'P6' then ios.read(3).unpack('C3')
end
bitmap[x,y] = RGBColour.new(red, green, blue)
end
end
bitmap[x,y] = RGBColour.new(red, green, blue)
end
end
ios.close
ios.close
Line 219: Line 226:
def to_grayscale
def to_grayscale
gray = self.class.new(@width, @height)
gray = self.class.new(@width, @height)
@width.times do |x|
each_pixel do |x,y|
gray[x,y] = self[x,y].to_grayscale
@height.times do |y|
gray[x,y] = self[x,y].to_grayscale
end
end
end
gray
gray
end

def to_blackandwhite
hist = histogram

# find the median luminosity
median = nil
sum = 0
hist.keys.sort.each do |lum|
sum += hist[lum]
if sum > @height * @width / 2
median = lum
break
end
end

# create the black and white image
bw = self.class.new(@width, @height)
each_pixel do |x,y|
bw[x,y] = self[x,y].luminosity < median ? RGBColour::BLACK : RGBColour::WHITE
end
bw
end

def save_as_blackandwhite(filename)
to_blackandwhite.save(filename)
end
end


Line 427: Line 458:


###############################################
###############################################
def histogram
def magnify(factor)
bigger = self.class.new(@width * factor, @height * factor)
histogram = Hash.new(0)
@height.times do |y|
each_pixel do |x,y|
@width.times do |x|
colour = self[x,y]
(x*factor .. x*factor + factor-1).each do |xx|
histogram[self[x,y].luminosity] += 1
(y*factor .. y*factor + factor-1).each do |yy|
bigger[xx,yy] = colour
end
end
end
end
end
histogram
bigger
end
end


###############################################
def to_blackandwhite
hist = histogram
def histogram
histogram = Hash.new(0)

each_pixel do |x,y|
# find the median luminosity
histogram[self[x,y].luminosity] += 1
median = nil
sum = 0
hist.keys.sort.each do |lum|
sum += hist[lum]
if sum > @height * @width / 2
median = lum
break
end
end
end
histogram

# create the black and white image
bw = self.class.new(@width, @height)
@height.times do |y|
@width.times do |x|
bw[x,y] = self[x,y].luminosity < median ? RGBColour::BLACK : RGBColour::WHITE
end
end
bw
end

def save_as_blackandwhite(filename)
to_blackandwhite.save(filename)
end
end


Line 608: Line 623:
(2 .. self).reduce(1, :*)
(2 .. self).reduce(1, :*)
end
end
end
end</lang>
</lang>


==A Test Suite==
==A Test Suite==