All formats

ChunkyPNG

LanguageRuby (pure Ruby, no native extension)
LicenseMIT
Repositorygithub.com/wvanbergen/chunky_png
Documentationrubydoc.info/gems/chunky_png, wiki
Depends onnothing (Ruby's zlib)
Read / writeyes / yes, all color types (16-bit is reduced to 8 bits), text chunks, interlacing

ChunkyPNG reads and writes PNG in plain Ruby, so it installs anywhere without compiling C code or installing ImageMagick. It gives pixel-level access (each pixel is a 32-bit RGBA integer), simple operations (crop, compose, rotate, flip, nearest-neighbor and bilinear resampling), text metadata and raw chunk access.

It’s slow for large images and uses a lot of memory, since every pixel is a Ruby integer. Use it for small images, generated graphics (badges, sparklines, QR codes) or where native dependencies aren’t allowed. The oily_png gem adds a C extension that speeds up encoding and decoding with the same API.

Installation#

Shell
gem install chunky_png

Or in a Gemfile: gem "chunky_png".

Basic usage: read, change and save a PNG#

Ruby
require "chunky_png"

image = ChunkyPNG::Image.from_file("in.png")
puts "#{image.width} x #{image.height}"

# read a pixel and split it into channels
pixel = image[0, 0]
puts [ChunkyPNG::Color.r(pixel), ChunkyPNG::Color.g(pixel),
      ChunkyPNG::Color.b(pixel), ChunkyPNG::Color.a(pixel)].inspect

# draw a half-transparent red square
(0...20).each do |y|
  (0...20).each do |x|
    image[x, y] = ChunkyPNG::Color.rgba(255, 0, 0, 128)
  end
end

image.save("out.png", :best_compression)

How to get PNG width and height without decoding#

Datastream reads the chunks without decoding pixel data:

Ruby
require "chunky_png"

header = ChunkyPNG::Datastream.from_file("in.png").header_chunk
puts "#{header.width} x #{header.height}, bit depth #{header.depth}, color type #{header.color}"

How to create a PNG from scratch#

Ruby
require "chunky_png"

png = ChunkyPNG::Image.new(64, 64, ChunkyPNG::Color::TRANSPARENT)
png.rect(8, 8, 55, 55, ChunkyPNG::Color("black"), ChunkyPNG::Color("orange"))
png.circle(32, 32, 12, ChunkyPNG::Color::WHITE, ChunkyPNG::Color("teal"))
png.save("badge.png")

How to read and write PNG text metadata#

metadata maps keys to values of the tEXt and zTXt chunks:

Ruby
require "chunky_png"

image = ChunkyPNG::Image.from_file("in.png")
image.metadata.each { |key, value| puts "#{key}: #{value}" }

image.metadata["Title"] = "Sunset"
image.metadata["Author"] = "Jane Doe"
image.save("out.png")

How to resize and crop a PNG#

Ruby
require "chunky_png"

image = ChunkyPNG::Image.from_file("in.png")
thumb = image.resample_bilinear(100, 100)   # or resample_nearest_neighbor for pixel art
part = image.crop(10, 10, 200, 150)          # x, y, width, height
thumb.save("thumb.png")
part.save("part.png")

Tips#