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.



45
46
47
48
# File 'lib/chunky_png/datastream.rb', line 45

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:



38
39
40
# File 'lib/chunky_png/datastream.rb', line 38

def data_chunks
  @data_chunks
end

#end_chunkChunkyPNG::Chunk::Header

The empty chunk that signals the end of this datastream



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

def end_chunk
  @end_chunk
end

#header_chunkChunkyPNG::Chunk::Header

The header chunk of this datastream.



18
19
20
# File 'lib/chunky_png/datastream.rb', line 18

def header_chunk
  @header_chunk
end

#other_chunksArray<ChunkyPNG::Chunk::Generic>

All other chunks in this PNG file.

Returns:



22
23
24
# File 'lib/chunky_png/datastream.rb', line 22

def other_chunks
  @other_chunks
end

#palette_chunkChunkyPNG::Chunk::Palette

The chunk containing the image’s palette.



26
27
28
# File 'lib/chunky_png/datastream.rb', line 26

def palette_chunk
  @palette_chunk
end

#physical_chunkChunkyPNG::Chunk::Physical

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



34
35
36
# File 'lib/chunky_png/datastream.rb', line 34

def physical_chunk
  @physical_chunk
end

#transparency_chunkChunkyPNG::Chunk::Transparency

The chunk containing the transparency information of the palette.



30
31
32
# File 'lib/chunky_png/datastream.rb', line 30

def transparency_chunk
  @transparency_chunk
end

Class Method Details

.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:



58
59
60
# File 'lib/chunky_png/datastream.rb', line 58

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:



67
68
69
70
71
# File 'lib/chunky_png/datastream.rb', line 67

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:



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

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.



104
105
106
107
108
109
# File 'lib/chunky_png/datastream.rb', line 104

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:



137
138
139
# File 'lib/chunky_png/datastream.rb', line 137

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:



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

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



153
154
155
# File 'lib/chunky_png/datastream.rb', line 153

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.



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

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.



170
171
172
# File 'lib/chunky_png/datastream.rb', line 170

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.



176
177
178
179
180
181
# File 'lib/chunky_png/datastream.rb', line 176

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.



163
164
165
166
# File 'lib/chunky_png/datastream.rb', line 163

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