Skip to content

Commit

Permalink
Better support for iTXt chunks that can be read/written as metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
murbanski committed Sep 26, 2019
1 parent 143b9cd commit 148a849
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ The file documents the changes to this library over the different versions.
=== Unreleased changes

- Implemented <tt>ChunkyPNG::Dimension#hash</tt> to fix some specs after a behavior change in RSpec.
- Better support for iTXt chunks that can be read/written as metadata

=== 1.3.11 - 2018-11-21

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ avatar.save('composited.png', :fast_rgba) # Force the fast saving routine.
image = ChunkyPNG::Image.from_file('with_metadata.png')
puts image.metadata['Title']
image.metadata['Author'] = 'Willem van Bergen'
image.metadata['custom_chunk'] = ChunkyPNG::Chunk::InternationalText.new('custom_chunk', "Hola!", "es")
image.save('with_metadata.png') # Overwrite file

# Low level access to PNG chunks
Expand Down
4 changes: 4 additions & 0 deletions lib/chunky_png/chunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ def initialize(type, attributes = {})
attributes.each { |k, v| send("#{k}=", v) }
end

def ==(other)
content == other.content
end

# 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.
Expand Down
7 changes: 3 additions & 4 deletions lib/chunky_png/datastream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,10 @@ def chunks
# Returns all the textual metadata key/value pairs as hash.
# @return [Hash] A hash containing metadata fields and their values.
def metadata
metadata = {}
other_chunks.each do |chunk|
metadata[chunk.keyword] = chunk.value if chunk.respond_to?(:keyword) && chunk.respond_to?(:value)
other_chunks.each_with_object({}) do |chunk, hash|
hash[chunk.keyword] = chunk.value if chunk.respond_to?(:keyword) && chunk.respond_to?(:value)
hash[chunk.keyword] = chunk if chunk.respond_to?(:keyword) && chunk.respond_to?(:text)
end
metadata
end

# Returns the uncompressed image data, combined from all the IDAT chunks
Expand Down
4 changes: 3 additions & 1 deletion lib/chunky_png/image.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ def initialize_copy(other)
# @see ChunkyPNG::Image::METADATA_COMPRESSION_TRESHOLD
def metadata_chunks
metadata.map do |key, value|
if value.length >= METADATA_COMPRESSION_TRESHOLD
if value.kind_of?(ChunkyPNG::Chunk::Base) # Add it directly - programmer _probably_ knows what he's doing...
value
elsif value.length >= METADATA_COMPRESSION_TRESHOLD
ChunkyPNG::Chunk::CompressedText.new(key, value)
else
ChunkyPNG::Chunk::Text.new(key, value)
Expand Down
12 changes: 10 additions & 2 deletions spec/chunky_png/datastream_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,18 @@
expect(ds.metadata["Copyright"]).to eql "Copyright Willem van Schaik, Singapore 1995-96"
end

it "ignores iTXt chunks" do
it "handles iTXt chunks specially" do
filename = resource_file("itxt_chunk.png")
ds = ChunkyPNG::Datastream.from_file(filename)
expect(ds.metadata).to be_empty
expect(ds.metadata).to eq({
"coach" => ChunkyPNG::Chunk::InternationalText.new(
"coach",
"US extracurricular sports teacher at a school (UK: PE teacher) lowest class on a passenger aircraft (UK: economy)",
"en-us",
"trainer",
ChunkyPNG::COMPRESSED_CONTENT,
)
})
end
end

Expand Down
6 changes: 4 additions & 2 deletions spec/chunky_png/image_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
image = ChunkyPNG::Image.new(10, 10)
image.metadata["Title"] = "My amazing icon!"
image.metadata["Author"] = "Willem van Bergen"
image.metadata["iTXt_fun"] = ChunkyPNG::Chunk::InternationalText.new("iTXt_fun", "Hola!", "es")
image.save(filename)

metadata = ChunkyPNG::Datastream.from_file(filename).metadata
expect(metadata["Title"]).to eql "My amazing icon!"
expect(metadata["Author"]).to eql "Willem van Bergen"
expect(metadata["Title"]).to eql "My amazing icon!"
expect(metadata["Author"]).to eql "Willem van Bergen"
expect(metadata["iTXt_fun"]).to eq ChunkyPNG::Chunk::InternationalText.new("iTXt_fun", "Hola!", "es")
end

it "should load empty images correctly" do
Expand Down

0 comments on commit 148a849

Please sign in to comment.