class Phantom::SVG::Parser::PNGReader

PNG reader.

Public Instance Methods

read(path, _options = {}) click to toggle source

Read png file from path.

# File lib/phantom/parser/png_reader.rb, line 15
def read(path, _options = {})
  reset

  return if path.nil? || path.empty?

  apngasm = APNG::APNGAsm.new
  apngasm.disassemble(path)

  if apngasm.frame_count == 1
    read_png(path)
  else
    read_apng(apngasm)
  end
end

Private Instance Methods

create_frame(path, duration = nil) click to toggle source

Create frame.

# File lib/phantom/parser/png_reader.rb, line 66
def create_frame(path, duration = nil)
  pixbuf = GdkPixbuf::Pixbuf.new(file: path)
  frame = set_param(path, pixbuf, duration)

  frame
end
create_surfaces(path, width, height) click to toggle source

Create surfaces.

# File lib/phantom/parser/png_reader.rb, line 86
def create_surfaces(path, width, height)
  bin = File.binread(path)
  base64 = [bin].pack('m')

  image = REXML::Element.new('image')
  image.add_attributes(
    'width' => width,
    'height' => height,
    'xlink:href' => "data:image/png;base64,#{base64}"
  )

  [image]
end
read_apng(apngasm) click to toggle source
# File lib/phantom/parser/png_reader.rb, line 39
def read_apng(apngasm)
  @width = @height = 0
  Dir.mktmpdir(nil, File.dirname(__FILE__)) do |dir|
    set_frame(apngasm, dir)
  end

  @width = "#{@width}px"
  @height = "#{@height}px"
  @loops = apngasm.get_loops
  @skip_first = apngasm.is_skip_first
  @has_animation = true
end
read_png(path) click to toggle source
# File lib/phantom/parser/png_reader.rb, line 32
def read_png(path)
  frame = create_frame(path)
  @frames << frame
  @width = "#{frame.width}"
  @height = "#{frame.height}"
end
set_frame(apngasm, dir) click to toggle source
# File lib/phantom/parser/png_reader.rb, line 52
def set_frame(apngasm, dir)
  # Create temporary file.
  apngasm.save_pngs(dir)

  # Create frames.
  apngasm.get_frames.each_with_index do |png_frame, index|
    @width = png_frame.width if @width < png_frame.width
    @height = png_frame.height if @height < png_frame.height
    duration = png_frame.delay_numerator.to_f / png_frame.delay_denominator.to_f
    @frames << create_frame("#{dir}/#{index}.png", duration)
  end
end
set_param(path, pixbuf, duration) click to toggle source
# File lib/phantom/parser/png_reader.rb, line 73
def set_param(path, pixbuf, duration)
  frame = Phantom::SVG::Frame.new
  frame.width = "#{pixbuf.width}px"
  frame.height = "#{pixbuf.height}px"
  frame.viewbox.set_from_text("0 0 #{pixbuf.width} #{pixbuf.height}")
  frame.surfaces = create_surfaces(path, pixbuf.width, pixbuf.height)
  frame.duration = duration unless duration.nil?
  frame.namespaces = { 'xmlns' => 'http://www.w3.org/2000/svg',
                       'xlink' => 'http://www.w3.org/1999/xlink' }
  frame
end