Class: PNG::Canvas

Inherits:
Object
  • Object
show all
Defined in:
lib/png.rb

Overview

PNG canvas

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(width, height, background = Color::Background) ⇒ Canvas

Returns a new instance of Canvas.



397
398
399
400
401
# File 'lib/png.rb', line 397

def initialize(width, height, background = Color::Background)
  @width = width
  @height = height
  @data = Array.new(@height) { |x| Array.new(@width, background) }
end

Instance Attribute Details

#dataObject (readonly)

Raw data



395
396
397
# File 'lib/png.rb', line 395

def data
  @data
end

#heightObject (readonly)

Height of the canvas



385
386
387
# File 'lib/png.rb', line 385

def height
  @height
end

#widthObject (readonly)

Width of the canvas



390
391
392
# File 'lib/png.rb', line 390

def width
  @width
end

Instance Method Details

#[](x, y) ⇒ Object

Retrieves the color of the pixel at (x, y).



406
407
408
409
410
# File 'lib/png.rb', line 406

def [](x, y)
  raise "bad x value #{x} >= #{@width}" if x >= @width
  raise "bad y value #{y} >= #{@height}" if y >= @height
  @data[@height-y-1][x]
end

#[]=(x, y, color) ⇒ Object

Sets the color of the pixel at (x, y) to color.



415
416
417
418
419
# File 'lib/png.rb', line 415

def []=(x, y, color)
  raise "bad x value #{x} >= #{@width}" if x >= @width
  raise "bad y value #{y} >= #{@height}"  if y >= @height
  @data[@height-y-1][x] = color
end

#inspectObject

:nodoc:



421
422
423
# File 'lib/png.rb', line 421

def inspect # :nodoc:
  '#<%s %dx%d>' % [self.class, @width, @height]
end

#line(x0, y0, x1, y1, color) ⇒ Object

Draws a line using Xiaolin Wu’s antialiasing technique.

en.wikipedia.org/wiki/Xiaolin_Wu’s_line_algorithm



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
# File 'lib/png.rb', line 437

def line(x0, y0, x1, y1, color)
  y0, y1, x0, x1 = y1, y0, x1, x0 if y0 > y1
  dx = x1 - x0
  sx = dx < 0 ? -1 : 1
  dx *= sx
  dy = y1 - y0

  # 'easy' cases
  if dy == 0 then
    Range.new(*[x0,x1].sort).each do |x|
      point(x, y0, color)
    end
    return
  end

  if dx == 0 then
    (y0..y1).each do |y|
      point(x0, y, color)
    end
    return
  end

  if dx == dy then
    x0.step(x1, sx) do |x|
      point(x, y0, color)
      y0 += 1
    end
    return
  end

  # main loop
  point(x0, y0, color)
  e_acc = 0
  if dy > dx then # vertical displacement
    e = (dx << 16) / dy
    (y0...y1-1).each do |i|
      e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xFFFF
      x0 = x0 + sx if (e_acc <= e_acc_temp)
      w = 0xFF-(e_acc >> 8)
      point(x0, y0, color.intensity(w))
      y0 = y0 + 1
      point(x0 + sx, y0, color.intensity(0xFF-w))
    end
    point(x1, y1, color)
    return
  end

  # horizontal displacement
  e = (dy << 16) / dx
  (dx - 1).downto(0) do |i|
    e_acc_temp, e_acc = e_acc, (e_acc + e) & 0xFFFF
    y0 += 1 if (e_acc <= e_acc_temp)
    w = 0xFF-(e_acc >> 8)
    point(x0, y0, color.intensity(w))
    x0 += sx
    point(x0, y0 + 1, color.intensity(0xFF-w))
  end
  point(x1, y1, color)
end

#point(x, y, color) ⇒ Object

Blends color onto the color at point (x, y).



428
429
430
# File 'lib/png.rb', line 428

def point(x, y, color)
  self[x,y] = self[x,y].blend(color)
end

#to_sObject

Returns an ASCII representation of this image



500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
# File 'lib/png.rb', line 500

def to_s
  image = []
  scale = (@width / 39) + 1

  @data.each_with_index do |row, x|
    next if x % scale != 0
    row.each_with_index do |color, y|
      next if y % scale != 0
      image << color.to_ascii
    end
    image << "\n"
  end

  return image.join
end