Class: ChunkyPNG::Datastream

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

Overview

The Datastream class represents a PNG formatted datastream. It supports both reading from and writing to strings, streams and files.

A PNG datastream begins with the PNG signature, and then contains multiple chunks, starting with a header (IHDR) chunk and finishing with an end (IEND) chunk.

See Also:

Constant Summary collapse

SIGNATURE =

The signature that each PNG file or stream should begin with.

[137, 80, 78, 71, 13, 10, 26, 10].pack("C8").force_encoding(Encoding::BINARY).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeDatastream

Initializes a new Datastream instance.



43
44
45
46
# File 'lib/chunky_png/datastream.rb', line 43

def initialize
  @other_chunks = []
  @data_chunks  = []
end

Instance Attribute Details

#data_chunksArray<ChunkyPNG::Chunk::ImageData>

The chunks that together compose the images pixel data.

Returns:



36
37
38
# File 'lib/chunky_png/datastream.rb', line 36

def data_chunks
  @data_chunks
end

#end_chunkChunkyPNG::Chunk::Header

The empty chunk that signals the end of this datastream



40
41
42
# File 'lib/chunky_png/datastream.rb', line 40

def end_chunk
  @end_chunk
end

#header_chunkChunkyPNG::Chunk::Header

The header chunk of this datastream.



16
17
18
# File 'lib/chunky_png/datastream.rb', line 16

def header_chunk
  @header_chunk
end

#other_chunksArray<ChunkyPNG::Chunk::Generic>

All other chunks in this PNG file.

Returns:



20
21
22
# File 'lib/chunky_png/datastream.rb', line 20

def other_chunks
  @other_chunks
end

#palette_chunkChunkyPNG::Chunk::Palette

The chunk containing the image’s palette.



24
25
26
# File 'lib/chunky_png/datastream.rb', line 24

def palette_chunk
  @palette_chunk
end

#physical_chunkChunkyPNG::Chunk::Physical

The chunk containing the physical dimensions of the PNG’s pixels.



32
33
34
# File 'lib/chunky_png/datastream.rb', line 32

def physical_chunk
  @physical_chunk
end

#transparency_chunkChunkyPNG::Chunk::Transparency

The chunk containing the transparency information of the palette.



28
29
30
# File 'lib/chunky_png/datastream.rb', line 28

def transparency_chunk
  @transparency_chunk
end

Class Method Details

.empty_bytearrayString

Returns an empty stream using binary encoding that can be used as stream to encode to.

Returns:

  • (String)

    An empty, binary string.



161
162
163
# File 'lib/chunky_png/datastream.rb', line 161

def self.empty_bytearray
  ChunkyPNG::EMPTY_BYTEARRAY.dup
end

.from_blob(str) ⇒ ChunkyPNG::Datastream Also known as: from_string

Reads a PNG datastream from a string.

Parameters:

  • str (String)

    The PNG encoded string to load from.

Returns:



56
57
58
# File 'lib/chunky_png/datastream.rb', line 56

def from_blob(str)
  from_io(StringIO.new(str, "rb"))
end

.from_file(filename) ⇒ ChunkyPNG::Datastream

Reads a PNG datastream from a file.

Parameters:

  • filename (String)

    The path of the file to load from.

Returns:



65
66
67
68
69
# File 'lib/chunky_png/datastream.rb', line 65

def from_file(filename)
  ds = nil
  File.open(filename, "rb") { |f| ds = from_io(f) }
  ds
end

.from_io(io) ⇒ ChunkyPNG::Datastream

Reads a PNG datastream from an input stream

Parameters:

  • io (IO)

    The stream to read from.

Returns:



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/chunky_png/datastream.rb', line 74

def from_io(io)
  io.set_encoding(Encoding::BINARY)
  verify_signature!(io)

  ds = new
  while ds.end_chunk.nil?
    chunk = ChunkyPNG::Chunk.read(io)
    case chunk
      when ChunkyPNG::Chunk::Header       then ds.header_chunk = chunk
      when ChunkyPNG::Chunk::Palette      then ds.palette_chunk = chunk
      when ChunkyPNG::Chunk::Transparency then ds.transparency_chunk = chunk
      when ChunkyPNG::Chunk::ImageData    then ds.data_chunks << chunk
      when ChunkyPNG::Chunk::Physical     then ds.physical_chunk = chunk
      when ChunkyPNG::Chunk::End          then ds.end_chunk = chunk
      else ds.other_chunks << chunk
    end
  end
  ds
end

.verify_signature!(io) ⇒ Object

Verifies that the current stream is a PNG datastream by checking its signature.

This method reads the PNG signature from the stream, setting the current position of the stream directly after the signature, where the IHDR chunk should begin.

Parameters:

  • io (IO)

    The stream to read the PNG signature from.

Raises:

  • (RuntimeError)

    An exception is raised if the PNG signature is not found at the beginning of the stream.



102
103
104
105
106
107
# File 'lib/chunky_png/datastream.rb', line 102

def verify_signature!(io)
  signature = io.read(ChunkyPNG::Datastream::SIGNATURE.length)
  unless signature == ChunkyPNG::Datastream::SIGNATURE
    raise ChunkyPNG::SignatureMismatch, "PNG signature not found, found #{signature.inspect} instead of #{ChunkyPNG::Datastream::SIGNATURE.inspect}!"
  end
end

Instance Method Details

#chunksEnumerable::Enumerator

Returns an enumerator instance for this datastream’s chunks.

Returns:

  • (Enumerable::Enumerator)

    An enumerator for the :each_chunk method.

See Also:



135
136
137
# File 'lib/chunky_png/datastream.rb', line 135

def chunks
  enum_for(:each_chunk)
end

#each_chunk {|chunk| ... } ⇒ Object

Enumerates the chunks in this datastream.

This will iterate over the chunks using the order in which the chunks should appear in the PNG file.

Yields:

  • (chunk)

    Yields the chunks in this datastream, one by one in the correct order.

Yield Parameters:

See Also:



122
123
124
125
126
127
128
129
130
# File 'lib/chunky_png/datastream.rb', line 122

def each_chunk
  yield(header_chunk)
  other_chunks.each { |chunk| yield(chunk) }
  yield(palette_chunk)      if palette_chunk
  yield(transparency_chunk) if transparency_chunk
  yield(physical_chunk)     if physical_chunk
  data_chunks.each { |chunk| yield(chunk) }
  yield(end_chunk)
end

#imagedataString

Returns the uncompressed image data, combined from all the IDAT chunks

Returns:

  • (String)

    The uncompressed image data for this datastream



151
152
153
# File 'lib/chunky_png/datastream.rb', line 151

def imagedata
  ChunkyPNG::Chunk::ImageData.combine_chunks(data_chunks)
end

#metadataHash

Returns all the textual metadata key/value pairs as hash.

Returns:

  • (Hash)

    A hash containing metadata fields and their values.



141
142
143
144
145
146
147
# File 'lib/chunky_png/datastream.rb', line 141

def 
   = {}
  other_chunks.each do |chunk|
    [chunk.keyword] = chunk.value if chunk.respond_to?(:keyword) && chunk.respond_to?(:value)
  end
  
end

#save(filename) ⇒ Object

Saves this datastream as a PNG file.

Parameters:

  • filename (String)

    The filename to use.



174
175
176
# File 'lib/chunky_png/datastream.rb', line 174

def save(filename)
  File.open(filename, "wb") { |f| write(f) }
end

#to_blobString Also known as: to_string, to_s

Encodes this datastream into a string.

Returns:

  • (String)

    The encoded PNG datastream.



180
181
182
183
184
185
# File 'lib/chunky_png/datastream.rb', line 180

def to_blob
  str = StringIO.new
  str.set_encoding("ASCII-8BIT")
  write(str)
  str.string
end

#write(io) ⇒ Object

Writes the datastream to the given output stream.

Parameters:

  • io (IO)

    The output stream to write to.



167
168
169
170
# File 'lib/chunky_png/datastream.rb', line 167

def write(io)
  io << SIGNATURE
  each_chunk { |c| c.write(io) }
end