lib/chunky_png/chunk.rb in chunky_png-1.3.11 vs lib/chunky_png/chunk.rb in chunky_png-1.3.12
- old
+ new
@@ -14,14 +14,14 @@
# Reads a chunk from an IO stream.
#
# @param io [IO, #read] The IO stream to read from.
# @return [ChunkyPNG::Chung::Base] The loaded chunk instance.
def self.read(io)
- length, type = read_bytes(io, 8).unpack('Na4')
+ length, type = read_bytes(io, 8).unpack("Na4")
content = read_bytes(io, length)
- crc = read_bytes(io, 4).unpack('N').first
+ crc = read_bytes(io, 4).unpack("N").first
verify_crc!(type, content, crc)
CHUNK_TYPES.fetch(type, Generic).read(type, content)
end
@@ -72,33 +72,33 @@
# Writes the chunk to the IO stream, using the provided content.
# The checksum will be calculated and appended to the stream.
# @param io [IO] The IO stream to write to.
# @param content [String] The content for this chunk.
def write_with_crc(io, content)
- io << [content.length].pack('N') << type << content
- io << [Zlib.crc32(content, Zlib.crc32(type))].pack('N')
+ io << [content.length].pack("N") << type << content
+ io << [Zlib.crc32(content, Zlib.crc32(type))].pack("N")
end
# Writes the chunk to the IO stream.
#
# It will call the +content+ method to get the content for this chunk,
# and will calculate and append the checksum automatically.
# @param io [IO] The IO stream to write to.
def write(io)
- write_with_crc(io, content || '')
+ write_with_crc(io, content || "")
end
end
# The Generic chunk type will read the content from the chunk as it,
# and will write it back as it was read.
class Generic < Base
# The attribute to store the content from the chunk, which gets
# written by the +write+ method.
attr_accessor :content
- def initialize(type, content = '')
- super(type, :content => content)
+ def initialize(type, content = "")
+ super(type, content: content)
end
# Creates an instance, given the chunk's type and content.
# @param type [String] The four character chunk type indicator.
# @param content [String] The content read from the chunk.
@@ -116,15 +116,14 @@
# ChunkyPNG supports all values for these variables that are defined in the
# PNG spec, except for color depth: Only 8-bit depth images are supported.
# Note that it is still possible to access the chunk for such an image, but
# ChunkyPNG will raise an exception if you try to access the pixel data.
class Header < Base
- attr_accessor :width, :height, :depth, :color, :compression, :filtering,
- :interlace
+ attr_accessor :width, :height, :depth, :color, :compression, :filtering, :interlace
def initialize(attrs = {})
- super('IHDR', attrs)
+ super("IHDR", attrs)
@depth ||= 8
@color ||= ChunkyPNG::COLOR_TRUECOLOR
@compression ||= ChunkyPNG::COMPRESSION_DEFAULT
@filtering ||= ChunkyPNG::FILTERING_DEFAULT
@interlace ||= ChunkyPNG::INTERLACING_NONE
@@ -135,47 +134,55 @@
# @param type [String] The four character chunk type indicator (= "IHDR").
# @param content [String] The 13 bytes of content read from the chunk.
# @return [ChunkyPNG::Chunk::End] The new Header chunk instance with the
# variables set to the values according to the content.
def self.read(type, content)
- fields = content.unpack('NNC5')
- new(:width => fields[0],
- :height => fields[1],
- :depth => fields[2],
- :color => fields[3],
- :compression => fields[4],
- :filtering => fields[5],
- :interlace => fields[6])
+ fields = content.unpack("NNC5")
+ new(
+ width: fields[0],
+ height: fields[1],
+ depth: fields[2],
+ color: fields[3],
+ compression: fields[4],
+ filtering: fields[5],
+ interlace: fields[6]
+ )
end
# Returns the content for this chunk when it gets written to a file, by
# packing the image information variables into the correct format.
# @return [String] The 13-byte content for the header chunk.
def content
- [width, height, depth, color, compression, filtering, interlace].
- pack('NNC5')
+ [
+ width,
+ height,
+ depth,
+ color,
+ compression,
+ filtering,
+ interlace,
+ ].pack("NNC5")
end
end
# The End (IEND) chunk indicates the last chunk of a PNG stream. It does
# not contain any data.
class End < Base
-
def initialize
- super('IEND')
+ super("IEND")
end
# Reads the END chunk. It will check if the content is empty.
# @param type [String] The four character chunk type indicator (=
# "IEND").
# @param content [String] The content read from the chunk. Should be
# empty.
# @return [ChunkyPNG::Chunk::End] The new End chunk instance.
# @raise [ChunkyPNG::ExpectationFailed] Raises an exception if the content was not empty.
def self.read(type, content)
- raise ExpectationFailed, 'The IEND chunk should be empty!' if content.bytesize > 0
- self.new
+ raise ExpectationFailed, "The IEND chunk should be empty!" if content.bytesize > 0
+ new
end
# Returns an empty string, because this chunk should always be empty.
# @return [""] An empty string.
def content
@@ -212,23 +219,22 @@
# ChunkyPNG::COLOR_INDEXED (3).
#
# @return [Array<Integer>] Returns an array of alpha channel values
# [0-255].
def palette_alpha_channel
- content.unpack('C*')
+ content.unpack("C*")
end
# Returns the truecolor entry to be replaced by transparent pixels,
#
# This method should only be used for images having color mode
# ChunkyPNG::COLOR_TRUECOLOR (2).
#
# @return [Integer] The color to replace with fully transparent pixels.
def truecolor_entry(bit_depth)
- values = content.unpack('nnn').map do |c|
- ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", c)
- end
+ decode_method_name = :"decode_png_resample_#{bit_depth}bit_value"
+ values = content.unpack("nnn").map { |c| ChunkyPNG::Canvas.send(decode_method_name, c) }
ChunkyPNG::Color.rgb(*values)
end
# Returns the grayscale entry to be replaced by transparent pixels.
#
@@ -236,11 +242,11 @@
# ChunkyPNG::COLOR_GRAYSCALE (0).
#
# @return [Integer] The (grayscale) color to replace with fully
# transparent pixels.
def grayscale_entry(bit_depth)
- value = ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", content.unpack('n')[0])
+ value = ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", content.unpack("n")[0])
ChunkyPNG::Color.grayscale(value)
end
end
class ImageData < Generic
@@ -253,11 +259,11 @@
end
def self.split_in_chunks(data, level = Zlib::DEFAULT_COMPRESSION, chunk_size = 2147483647)
streamdata = Zlib::Deflate.deflate(data, level)
# TODO: Split long streamdata over multiple chunks
- [ ChunkyPNG::Chunk::ImageData.new('IDAT', streamdata) ]
+ [ChunkyPNG::Chunk::ImageData.new("IDAT", streamdata)]
end
end
# The Text (tEXt) chunk contains keyword/value metadata about the PNG
# stream. In this chunk, the value is stored uncompressed.
@@ -269,25 +275,25 @@
# @see ChunkyPNG::Chunk::InternationalText
class Text < Base
attr_accessor :keyword, :value
def initialize(keyword, value)
- super('tEXt')
+ super("tEXt")
@keyword, @value = keyword, value
end
def self.read(type, content)
- keyword, value = content.unpack('Z*a*')
+ keyword, value = content.unpack("Z*a*")
new(keyword, value)
end
# Creates the content to write to the stream, by concatenating the
# keyword with the value, joined by a null character.
#
# @return The content that should be written to the datastream.
def content
- [keyword, value].pack('Z*a*')
+ [keyword, value].pack("Z*a*")
end
end
# The CompressedText (zTXt) chunk contains keyword/value metadata about the
# PNG stream. In this chunk, the value is compressed using Deflate
@@ -297,27 +303,30 @@
# @see ChunkyPNG::Chunk::InternationalText
class CompressedText < Base
attr_accessor :keyword, :value
def initialize(keyword, value)
- super('zTXt')
+ super("zTXt")
@keyword, @value = keyword, value
end
def self.read(type, content)
- keyword, compression, value = content.unpack('Z*Ca*')
+ keyword, compression, value = content.unpack("Z*Ca*")
raise ChunkyPNG::NotSupported, "Compression method #{compression.inspect} not supported!" unless compression == ChunkyPNG::COMPRESSION_DEFAULT
new(keyword, Zlib::Inflate.inflate(value))
end
# Creates the content to write to the stream, by concatenating the
# keyword with the deflated value, joined by a null character.
#
# @return The content that should be written to the datastream.
def content
- [keyword, ChunkyPNG::COMPRESSION_DEFAULT, Zlib::Deflate.deflate(value)].
- pack('Z*Ca*')
+ [
+ keyword,
+ ChunkyPNG::COMPRESSION_DEFAULT,
+ Zlib::Deflate.deflate(value),
+ ].pack("Z*Ca*")
end
end
# The Physical (pHYs) chunk specifies the intended pixel size or aspect
# ratio for display of the image.
@@ -325,35 +334,35 @@
# http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.pHYs
class Physical < Base
attr_accessor :ppux, :ppuy, :unit
def initialize(ppux, ppuy, unit = :unknown)
- raise ArgumentError, 'unit must be either :meters or :unknown' unless [:meters, :unknown].member?(unit)
- super('pHYs')
+ raise ArgumentError, "unit must be either :meters or :unknown" unless [:meters, :unknown].member?(unit)
+ super("pHYs")
@ppux, @ppuy, @unit = ppux, ppuy, unit
end
def dpix
- raise ChunkyPNG::UnitsUnknown, 'the PNG specifies its physical aspect ratio, but does not specify the units of its pixels\' physical dimensions' unless unit == :meters
+ raise ChunkyPNG::UnitsUnknown, "the PNG specifies its physical aspect ratio, but does not specify the units of its pixels' physical dimensions" unless unit == :meters
ppux * INCHES_PER_METER
end
def dpiy
- raise ChunkyPNG::UnitsUnknown, 'the PNG specifies its physical aspect ratio, but does not specify the units of its pixels\' physical dimensions' unless unit == :meters
+ raise ChunkyPNG::UnitsUnknown, "the PNG specifies its physical aspect ratio, but does not specify the units of its pixels' physical dimensions" unless unit == :meters
ppuy * INCHES_PER_METER
end
def self.read(type, content)
- ppux, ppuy, unit = content.unpack('NNC')
+ ppux, ppuy, unit = content.unpack("NNC")
unit = unit == 1 ? :meters : :unknown
new(ppux, ppuy, unit)
end
# Assembles the content to write to the stream for this chunk.
# @return [String] The binary content that should be written to the datastream.
def content
- [ppux, ppuy, unit == :meters ? 1 : 0].pack('NNC')
+ [ppux, ppuy, unit == :meters ? 1 : 0].pack("NNC")
end
INCHES_PER_METER = 0.0254
end
@@ -370,12 +379,12 @@
# @see ChunkyPNG::Chunk::Text
# @see ChunkyPNG::Chunk::CompressedText
class InternationalText < Base
attr_accessor :keyword, :text, :language_tag, :translated_keyword, :compressed, :compression
- def initialize(keyword, text, language_tag = '', translated_keyword = '', compressed = ChunkyPNG::UNCOMPRESSED_CONTENT, compression = ChunkyPNG::COMPRESSION_DEFAULT)
- super('iTXt')
+ def initialize(keyword, text, language_tag = "", translated_keyword = "", compressed = ChunkyPNG::UNCOMPRESSED_CONTENT, compression = ChunkyPNG::COMPRESSION_DEFAULT)
+ super("iTXt")
@keyword = keyword
@text = text
@language_tag = language_tag
@translated_keyword = translated_keyword
@compressed = compressed
@@ -388,32 +397,32 @@
# @return [ChunkyPNG::Chunk::InternationalText] The new End chunk instance.
# @raise [ChunkyPNG::InvalidUTF8] If the chunk contains data that is not UTF8-encoded text.
# @raise [ChunkyPNG::NotSupported] If the chunk refers to an unsupported compression method.
# Currently uncompressed data and deflate are supported.
def self.read(type, content)
- keyword, compressed, compression, language_tag, translated_keyword, text = content.unpack('Z*CCZ*Z*a*')
+ keyword, compressed, compression, language_tag, translated_keyword, text = content.unpack("Z*CCZ*Z*a*")
raise ChunkyPNG::NotSupported, "Compression flag #{compressed.inspect} not supported!" unless compressed == ChunkyPNG::UNCOMPRESSED_CONTENT || compressed == ChunkyPNG::COMPRESSED_CONTENT
raise ChunkyPNG::NotSupported, "Compression method #{compression.inspect} not supported!" unless compression == ChunkyPNG::COMPRESSION_DEFAULT
text = Zlib::Inflate.inflate(text) if compressed == ChunkyPNG::COMPRESSED_CONTENT
- text.force_encoding('utf-8')
+ text.force_encoding("utf-8")
raise ChunkyPNG::InvalidUTF8, "Invalid unicode encountered in iTXt chunk" unless text.valid_encoding?
- translated_keyword.force_encoding('utf-8')
+ translated_keyword.force_encoding("utf-8")
raise ChunkyPNG::InvalidUTF8, "Invalid unicode encountered in iTXt chunk" unless translated_keyword.valid_encoding?
new(keyword, text, language_tag, translated_keyword, compressed, compression)
end
# Assembles the content to write to the stream for this chunk.
# @return [String] The binary content that should be written to the datastream.
def content
- text_field = text.encode('utf-8')
- text_field = (compressed == ChunkyPNG::COMPRESSED_CONTENT) ? Zlib::Deflate.deflate(text_field) : text_field
+ text_field = text.encode("utf-8")
+ text_field = compressed == ChunkyPNG::COMPRESSED_CONTENT ? Zlib::Deflate.deflate(text_field) : text_field
- [keyword, compressed, compression, language_tag, translated_keyword.encode('utf-8'), text_field].pack('Z*CCZ*Z*a*')
+ [keyword, compressed, compression, language_tag, translated_keyword.encode("utf-8"), text_field].pack("Z*CCZ*Z*a*")
end
end
# Maps chunk types to classes, based on the four byte chunk type indicator
# at the beginning of a chunk.
@@ -421,17 +430,17 @@
# If a chunk type is not specified in this hash, the Generic chunk type
# will be used.
#
# @see ChunkyPNG::Chunk.read
CHUNK_TYPES = {
- 'IHDR' => Header,
- 'IEND' => End,
- 'IDAT' => ImageData,
- 'PLTE' => Palette,
- 'tRNS' => Transparency,
- 'tEXt' => Text,
- 'zTXt' => CompressedText,
- 'iTXt' => InternationalText,
- 'pHYs' => Physical,
+ "IHDR" => Header,
+ "IEND" => End,
+ "IDAT" => ImageData,
+ "PLTE" => Palette,
+ "tRNS" => Transparency,
+ "tEXt" => Text,
+ "zTXt" => CompressedText,
+ "iTXt" => InternationalText,
+ "pHYs" => Physical,
}
end
end