Module: ChunkyPNG::Canvas::PNGDecoding

Included in:
ChunkyPNG::Canvas
Defined in:
lib/chunky_png/canvas/png_decoding.rb

Overview

The PNGDecoding contains methods for decoding PNG datastreams to create a Canvas object. The datastream can be provided as filename, string or IO stream.

Overview of the decoding process:

  • The optional PLTE and tRNS chunk are decoded for the color palette of the original image.

  • The contents of the IDAT chunks is combined, and uncompressed using Inflate decompression to the image pixelstream.

  • Based on the color mode, width and height of the original image, which is read from the PNG header (IHDR chunk), the amount of bytes per line is determined.

  • For every line of pixels in the encoded image, the original byte values are restored by unapplying the milter method for that line.

  • The read bytes are unfiltered given by the filter function specified by the first byte of the line.

  • The unfiltered pixelstream are is into colored pixels, using the color mode.

  • All lines combined to form the original image.

For interlaced images, the original image was split into 7 subimages. These images get decoded just like the process above (from step 3), and get combined to form the original images.

Instance Method Summary collapse

Instance Method Details

#decode_png_pixelstream(stream, width, height, color_mode, depth, interlace, decoding_palette, transparent_color) ⇒ ChunkyPNG::Canvas

Decodes a canvas from a PNG encoded pixelstream, using a given width, height, color mode and interlacing mode.



95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/chunky_png/canvas/png_decoding.rb', line 95

def decode_png_pixelstream(stream, width, height, color_mode, depth, interlace, decoding_palette, transparent_color)
  raise ChunkyPNG::ExpectationFailed, "This palette is not suitable for decoding!" if decoding_palette && !decoding_palette.can_decode?

  image = case interlace
    when ChunkyPNG::INTERLACING_NONE;  decode_png_without_interlacing(stream, width, height, color_mode, depth, decoding_palette)
    when ChunkyPNG::INTERLACING_ADAM7; decode_png_with_adam7_interlacing(stream, width, height, color_mode, depth, decoding_palette)
    else raise ChunkyPNG::NotSupported, "Don't know how the handle interlacing method #{interlace}!"
  end

  image.pixels.map! { |c| c == transparent_color ? ChunkyPNG::Color::TRANSPARENT : c } if transparent_color
  return image
end

#from_blob(str) ⇒ ChunkyPNG::Canvas Also known as: from_string

Decodes a Canvas from a PNG encoded string.



35
36
37
# File 'lib/chunky_png/canvas/png_decoding.rb', line 35

def from_blob(str)
  from_datastream(ChunkyPNG::Datastream.from_blob(str))
end

#from_datastream(ds) ⇒ ChunkyPNG::Canvas

Decodes the Canvas from a PNG datastream instance.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/chunky_png/canvas/png_decoding.rb', line 60

def from_datastream(ds)
  width      = ds.header_chunk.width
  height     = ds.header_chunk.height
  color_mode = ds.header_chunk.color
  interlace  = ds.header_chunk.interlace
  depth      = ds.header_chunk.depth

  if width == 0 || height == 0
    raise ExpectationFailed, "Invalid image size, width: #{width}, height: #{height}"
  end

  decoding_palette, transparent_color = nil, nil
  case color_mode
    when ChunkyPNG::COLOR_INDEXED
      decoding_palette = ChunkyPNG::Palette.from_chunks(ds.palette_chunk, ds.transparency_chunk)
    when ChunkyPNG::COLOR_TRUECOLOR
      transparent_color = ds.transparency_chunk.truecolor_entry(depth) if ds.transparency_chunk
    when ChunkyPNG::COLOR_GRAYSCALE
      transparent_color = ds.transparency_chunk.grayscale_entry(depth) if ds.transparency_chunk
  end

  decode_png_pixelstream(ds.imagedata, width, height, color_mode, depth, interlace, decoding_palette, transparent_color)
end

#from_file(filename) ⇒ ChunkyPNG::Canvas

Decodes a Canvas from a PNG encoded file.



44
45
46
# File 'lib/chunky_png/canvas/png_decoding.rb', line 44

def from_file(filename)
  from_datastream(ChunkyPNG::Datastream.from_file(filename))
end

#from_io(io) ⇒ ChunkyPNG::Canvas Also known as: from_stream

Decodes a Canvas from a PNG encoded stream.



51
52
53
# File 'lib/chunky_png/canvas/png_decoding.rb', line 51

def from_io(io)
  from_datastream(ChunkyPNG::Datastream.from_io(io))
end