A pure ruby PNG file manipulation & validation
(If you need a high-level PNG creation toolkit - take a look at SugarPNG)
gem install zpng
- supports
iTXt
(international text) chunks - full support of 16-bit color & alpha depth
# zpng -h
Usage: zpng [options] filename.png
-i, --info General image info (default)
-c, --chunk(s) [ID] Show chunks (default) or single chunk by its #
-m, --metadata Show image metadata, if any (default)
-S, --scanlines Show scanlines info
-P, --palette Show palette
--colors Show colors used
-E, --extract-chunk ID extract a single chunk
-D, --imagedata dump unpacked Image Data (IDAT) chunk(s) to stdout
-C, --crop GEOMETRY crop image, {WIDTH}x{HEIGHT}+{X}+{Y},
puts results on stdout unless --ascii given
-R, --rebuild NEW_FILENAME rebuild image, useful in restoring borked images
-A, --ascii Try to convert image to ASCII (works best with monochrome images)
--ascii-string STRING Use specific string to map pixels to ASCII characters
-N, --ansi Try to display image as ANSI colored text
-2, --256 Try to display image as 256-colored text
-W, --wide Use 2 horizontal characters per one pixel
-v, --verbose Run verbosely (can be used multiple times)
-q, --quiet Silent any warnings (can be used multiple times)
-I, --console opens IRB console with specified image loaded
# zpng qr_rgb.png
[.] image size 35x35, 24bpp, COLOR_RGB
[.] uncompressed imagedata size = 3710 bytes
[.] <Chunk #00 IHDR size= 13, crc=91bb240e, color=2, compression=0, depth=8, filter=0, height=35, interlace=0, offset=8, width=35> CRC OK
[.] <Chunk #01 sRGB size= 1, crc=aece1ce9 > CRC OK
[.] <Chunk #02 IDAT size= 399, crc=59790716 > CRC OK
[.] <Chunk #03 IEND size= 0, crc=ae426082 > CRC OK
# zpng -v qr_rgb.png
[.] image size 35x35, 24bpp, COLOR_RGB
[.] uncompressed imagedata size = 3710 bytes
01 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| + 3678 bytes
[.] <Chunk #00 IHDR size= 13, crc=91bb240e, color=2, compression=0, depth=8, filter=0, height=35, idx=0, interlace=0, offset=8, width=35> CRC OK
00 00 00 23 00 00 00 23 08 02 00 00 00 |...#...#..... |
[.] <Chunk #01 sRGB size= 1, crc=aece1ce9 > CRC OK
00 |. |
[.] <Chunk #02 IDAT size= 399, crc=59790716 > CRC OK
48 c7 bd 56 41 12 c4 20 08 d3 8e ff ff b2 7b 70 |H..VA.. ......{p|
86 d2 24 44 db c3 7a d8 d9 b6 08 18 03 a1 cf 39 |..$D..z........9| + 367 bytes
[.] <Chunk #03 IEND size= 0, crc=ae426082 > CRC OK
( add more -v
's for even more verbose output)
# zpng --chunks qr_aux_chunks.png
[.] <Chunk #00 IHDR size= 13, crc=36a28ef4, color=0, compression=0, depth=1, filter=0, height=35, interlace=0, offset=8, width=35> CRC OK
[.] <Chunk #01 gAMA size= 4, crc=0bfc6105 > CRC OK
[.] <Chunk #02 sRGB size= 1, crc=aece1ce9 > CRC OK
[.] <Chunk #03 cHRM size= 32, crc=9cba513c > CRC OK
[.] <Chunk #04 pHYs size= 9, crc=46c96b3e > CRC OK
[.] <Chunk #05 IDAT size= 213, crc=5f3f1ff9 > CRC OK
[.] <Chunk #06 tEXt size= 37, crc=8d62fd1a, keyword="date:create"> CRC OK
[.] <Chunk #07 tEXt size= 37, crc=fc3f45a6, keyword="date:modify"> CRC OK
[.] <Chunk #08 IEND size= 0, crc=ae426082 > CRC OK
# zpng --ascii --wide qr_rgb.png
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@ @@ @@@@@@@@@@ @@ @@ @@@@@@@@ @@
@@ @@@@@@@@@@ @@@@@@@@@@@@@@ @@ @@ @@@@@@@@@@ @@@@@@@@@@ @@
@@ @@ @@ @@ @@@@ @@@@ @@ @@@@ @@ @@ @@ @@
@@ @@ @@ @@ @@ @@@@@@@@ @@ @@ @@ @@ @@ @@
@@ @@ @@ @@ @@ @@@@@@@@ @@ @@@@ @@ @@ @@
@@ @@@@@@@@@@ @@@@ @@@@ @@ @@@@ @@@@@@@@ @@@@@@@@@@ @@
@@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ @@
@@@@@@@@@@@@@@@@@@@@ @@ @@ @@@@@@@@@@ @@ @@@@@@@@@@@@@@@@@@
@@ @@@@ @@ @@@@@@@@ @@ @@ @@@@@@@@ @@@@ @@ @@
@@@@ @@ @@@@@@ @@@@@@@@@@ @@ @@ @@ @@ @@@@@@ @@
@@ @@ @@ @@@@@@@@@@@@ @@ @@ @@@@ @@ @@ @@ @@
@@@@@@@@ @@ @@@@@@ @@@@ @@ @@@@@@ @@ @@@@@@ @@@@
@@ @@ @@ @@@@ @@ @@@@@@@@ @@ @@@@ @@ @@@@@@@@@@
@@@@@@ @@@@ @@ @@ @@ @@@@@@@@ @@ @@ @@@@@@@@ @@@@
@@ @@ @@ @@ @@ @@@@ @@@@ @@@@@@
@@ @@ @@@@ @@ @@ @@ @@@@@@@@ @@@@@@ @@ @@@@@@
@@@@@@ @@ @@@@ @@@@@@@@@@ @@ @@ @@ @@
@@@@@@@@@@ @@@@ @@@@ @@@@@@@@@@ @@ @@ @@
@@ @@ @@ @@@@@@@@@@ @@ @@@@@@ @@@@@@ @@ @@@@
@@@@ @@ @@@@ @@@@ @@ @@@@ @@@@ @@ @@@@ @@@@@@ @@
@@@@@@ @@ @@ @@@@@@@@ @@ @@@@@@@@@@@@ @@@@@@
@@@@ @@@@@@@@@@ @@@@ @@ @@@@@@@@ @@ @@@@@@ @@
@@ @@@@ @@ @@@@ @@ @@@@ @@@@@@ @@
@@ @@ @@ @@ @@ @@@@@@@@@@ @@ @@ @@ @@ @@@@
@@@@ @@ @@@@ @@ @@@@@@@@@@ @@ @@@@@@ @@
@@@@@@@@@@@@@@@@@@ @@ @@ @@ @@@@@@@@@@ @@@@@@ @@ @@@@@@
@@ @@@@@@@@ @@ @@ @@@@@@@@@@ @@ @@ @@@@@@@@@@
@@ @@@@@@@@@@ @@@@ @@@@ @@ @@@@ @@@@@@ @@ @@
@@ @@ @@ @@@@@@@@@@ @@ @@ @@@@@@ @@@@@@
@@ @@ @@ @@ @@@@@@ @@ @@ @@ @@ @@@@@@@@@@@@@@@@
@@ @@ @@ @@ @@@@ @@@@ @@ @@@@ @@@@ @@@@@@@@
@@ @@@@@@@@@@ @@ @@ @@@@@@@@@@ @@ @@@@@@@@@@@@ @@
@@ @@ @@ @@@@ @@ @@ @@@@@@ @@ @@@@@@ @@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# zpng --scanlines qr_rgb.png
#<ZPNG::ScanLine idx=0 offset=0 size=106 bpp=24 filter=1>
#<ZPNG::ScanLine idx=1 offset=106 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=2 offset=212 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=3 offset=318 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=4 offset=424 size=106 bpp=24 filter=2>
#<ZPNG::ScanLine idx=5 offset=530 size=106 bpp=24 filter=2>
#<ZPNG::ScanLine idx=6 offset=636 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=7 offset=742 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=8 offset=848 size=106 bpp=24 filter=1>
#<ZPNG::ScanLine idx=9 offset=954 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=10 offset=1060 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=11 offset=1166 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=12 offset=1272 size=106 bpp=24 filter=1>
#<ZPNG::ScanLine idx=13 offset=1378 size=106 bpp=24 filter=2>
#<ZPNG::ScanLine idx=14 offset=1484 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=15 offset=1590 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=16 offset=1696 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=17 offset=1802 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=18 offset=1908 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=19 offset=2014 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=20 offset=2120 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=21 offset=2226 size=106 bpp=24 filter=1>
#<ZPNG::ScanLine idx=22 offset=2332 size=106 bpp=24 filter=2>
#<ZPNG::ScanLine idx=23 offset=2438 size=106 bpp=24 filter=0>
#<ZPNG::ScanLine idx=24 offset=2544 size=106 bpp=24 filter=2>
#<ZPNG::ScanLine idx=25 offset=2650 size=106 bpp=24 filter=1>
#<ZPNG::ScanLine idx=26 offset=2756 size=106 bpp=24 filter=1>
#<ZPNG::ScanLine idx=27 offset=2862 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=28 offset=2968 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=29 offset=3074 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=30 offset=3180 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=31 offset=3286 size=106 bpp=24 filter=2>
#<ZPNG::ScanLine idx=32 offset=3392 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=33 offset=3498 size=106 bpp=24 filter=4>
#<ZPNG::ScanLine idx=34 offset=3604 size=106 bpp=24 filter=1>
# zpng --palette qr_plte_bw.png
<Chunk #02 PLTE size= 6, crc=55c2d37e >
color #0: ff ff ff |...|
color #1: 00 00 00 |...|
#!/usr/bin/env ruby
require 'zpng'
include ZPNG
img = Image.new(File.join(File.dirname(__FILE__),"http.png"))
puts "[.] original:"
puts img.to_s
puts
img.width.times do |x|
img[x,0] = (x % 2 == 0) ? Color::WHITE : Color::BLACK
end
puts "[.] modified:"
puts img.to_s
File.open("http-modified.png","wb") do |f|
f << img.export
end
#!/usr/bin/env ruby
require 'zpng'
include ZPNG
img = Image.new :width => 16, :height => 16
File.open("16x16.png","wb") do |f|
f << img.export
end
Released under the MIT License. See the LICENSE file for further details.