1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
<TITLE>Applications: Image Converters (PNG: The Definitive Guide)</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<!-- http://www.w3.org/TR/REC-CSS2/box.html -->
<STYLE TYPE="text/css">
P { margin-bottom: 0em }
UL {
margin-bottom: 0em;
margin-top: 0em;
list-style: disc;
}
LI {
padding: 0px 0px 0px 0px;
margin: 0px 0px 0px 0px;
}
</STYLE>
<LINK REV="made" HREF="http://pobox.com/~newt/greg_contact.html">
<!-- Copyright (c) 1999 O'Reilly and Associates. -->
<!-- Copyright (c) 2002-2006 Greg Roelofs. -->
</HEAD>
<body bgcolor="#ffffff" text="#000000">
<hr> <!-- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -->
<a href="chapter04.html"><img width=24 height=13 border=0 align="left"
src="images/prev.png" alt="<-"></a>
<a href="chapter06.html"><img width=24 height=13 border=0 align="right"
src="images/next.png" alt="->"></a>
<div align="center">
<a href="chapter04.html"><font size="-1" color="#000000"
><b>PREVIOUS</b></font></a> <a
href="toc.html"><font size="-1" color="#000000"
><b>CONTENTS</b></font></a> <a
href="chapter06.html"><font size="-1" color="#000000"
><b>NEXT</b></font></a>
</div>
<hr> <!-- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -->
<h1 class="chapter">Chapter 5. Applications: Image Converters</h1>
<div class="htmltoc"><h4 class="tochead">Contents:</h4><p>
<a href="#png.ch05.div.1">5.1. pngcrush</a><br />
<a href="#png.ch05.div.2">5.2. pnmtopng</a><br />
<a href="#png.ch05.div.3">5.3. gif2png</a><br />
<a href="#png.ch05.div.4">5.4. Tiff2png</a><br />
<a href="#png.ch05.div.5">5.5. pngcheck</a><br />
<a href="#png.ch05.div.6">5.6. Other Conversion Programs</a><br />
</p></div>
<p>
<a name="INDEX-392" />
<a name="INDEX-393" />
Conversion to PNG from other image formats (or even from PNG) remains a popular
approach for the simple reason that other formats have traditionally been
better supported by applications. Even with good, current application support
for PNG, users typically have large archives of older images, at least some of
which may they desire to convert to PNG format.</p>
<p>Just as one would like to see certain basic PNG features supported in image
editors (which may be thought of as a special case of conversion utilities,
converting and optionally modifying a previously saved image file) one
would like certain basic PNG features supported in converters. These
include:</p>
<ul><li><p>Preservation of basic image types: RGB, grayscale, and palette-based</p></li><li><p>Option to convert ``truecolor'' images with fewer than 256 colors to
palette-based (or grayscale, if appropriate)</p></li><li><p>Preservation of simple transparency in palette images (e.g., when converting
from GIF), including the ability to reorder the palette so the transparent
entry comes first, which avoids wasting space in PNG's transparency chunk</p></li><li><p>Preservation of <em class="emphasis">unassociated</em> alpha transparency (e.g., when converting
from TIFF)</p></li><li><p>Preservation of gamma, chromaticity, sRGB, or full ICC profile information (see
<a href="chapter10.html">Chapter 10, "Gamma Correction and Precision Color"</a>, for details)</p></li><li><p>Option to preserve ``deep'' samples, such as from 12-bit JPEG or medical images
or 16-bit-per-sample TIFF images</p></li><li><p>Preservation of text information (e.g., from JPEG, GIF, and TIFF images)</p></li><li><p>Preservation of interlacing or ``progressiveness''</p></li><li><p>Option to scan for unused palette entries and eliminate any from the palette</p></li><li><p>Reasonable default compression settings: adaptive filtering turned on for all
image types except palette-based; ``medium'' <em class="emphasis">zlib</em> compression level (say,
between 3 and 7)</p></li><li><p>Option for maximal (slowest) compression</p></li></ul>
<p>
Clearly, different users have different needs, but fundamental things that
should be preserved when converting between image formats include the
basic pixel information, transparency, and text. Items in the preceding
list that involve optimization and compression of PNG images can be
dealt with after the initial conversion is complete, but restoring text
or transparency information that was lost in translation is tedious and
to be avoided if at all possible.</p>
<p>In the next few sections, we will look at a number of conversion utilities
in some detail. Most of these are command-line programs--not because we
want the reader to suffer,<a href="#FOOTNOTE-28">[28]</a>
but because dedicated converters such as these typically do the best job and
are often capable of batch (automated) conversions. I have also listed many
image viewers with conversion capabilities in
<a href="chapter03.html">Chapter 3, "Applications: Image Viewers"</a>
and several image editors in
<a href="chapter04.html">Chapter 4, "Applications: Image Editors"</a>;
thse are, by necessity, graphical and may be preferable for the casual user.</p><blockquote class="footnote">
<a name="FOOTNOTE-28" /><p>[28] For <em class="emphasis">real</em> suffering, write a book.</p>
</blockquote>
<div class="sect1"><a name="png.ch05.div.1" />
<h2 class="sect1">5.1. pngcrush</h2>
<p><a name="INDEX-394" />What may be the most useful conversion tool of all knows nothing of
any image format other than PNG; it converts PNGs into other
<a name="INDEX-395" />PNGs. pngcrush, by Glenn Randers-Pehrson, is a program for optimizing
PNG images--specifically, for reducing their size as much as
possible, although it can also perform simple housekeeping tasks such
as removing or replacing specific chunks,<a href="#FOOTNOTE-29">[29]</a>
or adding gamma-correction information or simple transparency. It is an
invaluable tool for use in conjunction with other converters and with
commercial image editors, which may not always produce optimal PNG files.</p><blockquote class="footnote">
<a name="FOOTNOTE-29" /><p>[29] PNG's fundamental chunk structure is described in <a href="chapter08.html">Chapter 8, "PNG Basics"</a>.</p>
</blockquote>
<p>pngcrush is currently available as a command-line, shareware program in DOS
and Linux x86 flavors. The DOS version works under Windows 95/98/NT and can
handle long filenames; it may also run in an OS/2 DOS box, but without
long-filename support. The current release, as of January 1999, is version
1.1.3 which has a home page at
<!--
<a href="http://www.netgsi.com/~glennrp/pngcrush/"
>http://www.netgsi.com/~glennrp/pngcrush/</a>.
-->
<a href="http://pmt.sourceforge.net/pngcrush/"
>http://pmt.sourceforge.net/pngcrush/</a>.
</p>
<p>The simplest pngcrush operation is a basic ``crush'' on a single
file, specifying the output filename:</p>
<blockquote><pre class="code">pngcrush foo.png foo-crushed.png</pre></blockquote>
<p>This results in output that looks something like the following:</p>
<blockquote><pre class="code">pngcrush 1.1.3, Copyright (C) 1998, Glenn Randers-Pehrson.
| This program was built with libpng version 1.0.3,
| Copyright (c) Guy Eric Schalnat, Group 42 Inc.,
| Copyright (c) 1996, 1997 Andreas Dilger,
| Copyright (c) 1998, 1999, Glenn Randers-Pehrson,
| and zlib version 1.1.3, Copyright (c) 1998,
| Jean-loup Gailly and Mark Adler.
foo.png IDAT length in input file = 148723
IDAT length with method 1 (fm 0 zl 4 zs 0)= 147533
IDAT length with method 2 (fm 1 zl 4 zs 0)= 124710
IDAT length with method 3 (fm 5 zl 4 zs 1)= 110589
IDAT length with method 9 (fm 5 zl 2 zs 2)= 880073
IDAT length with method 10 (fm 5 zl 9 zs 1)= 85820
best pngcrush method = 10 for foo-crushed.png (42.36% reduction)
overall result: 42.36% reduction, 62903 bytes</pre></blockquote>
<p><a name="INDEX-396" />pngcrush typically tries the five or six compression approaches that are, according
to its heuristics, the most likely to compress the best. This involves varying
the different filter and compression settings allowed by the PNG format
(described in <a href="chapter09.html">Chapter 9, "Compression and Filtering"</a>). If pngcrush finds a
method that produces a smaller file than the original, it saves the new file
with that approach. (A 42% reduction as shown in the previous output is typical only of cases in which the
original file was compressed particularly poorly.) Note that pngcrush
operates completely losslessly with respect to the image data;
the only loss of information it <em class="emphasis">intentionally</em>
allows is the explicit removal or replacement of chunks at the user's
direction (though a limitation in versions of the PNG reference
library prior to 1.0.6 also caused the accidental deletion of unknown,
safe-to-copy chunks). We'll come back to that shortly.</p>
<p>pngcrush also supports a truly brute-force approach that currently tests 102
different methods but may add more in the future. This rarely improves
compression by more than a tenth of a percent over the default approach, but
for busy sites looking to conserve bandwidth, saving even a dozen bytes may
be well worth the cost of a very lengthy--but one-time--pngcrush session.
The brute-force method is invoked with the <b class="emphasis-bold">-brute</b> option, logically
enough:</p>
<blockquote><pre class="code">pngcrush -brute foo.png foo-crushed.png</pre></blockquote>
<p>In general, a site optimizing its content will want to crush all of its PNG
images (by using batch-mode conversion), and pngcrush includes two options to
support batch conversion. The first allows
<?x-need 15?>one to specify a new extension for converted
images, which will be created in the same directory as the original:</p>
<blockquote><pre class="code">pngcrush -e -crushed.png foo.png foo2.png foo3.png foo4.png</pre></blockquote>
<p>This example crushes four images, <em class="emphasis">foo.png</em> through <em class="emphasis">foo4.png</em>,
giving them the extension <em class="emphasis">-crushed.png</em>; thus the output names are
<em class="emphasis">foo-crushed.png</em>, <em class="emphasis">foo2-crushed.png</em>, and so on. Such an approach
is handy for casual use, since an alphabetical directory listing will (usually)
list the original and crushed versions in pairs, allowing quick, after-the-fact
inspection of the changes in file sizes. But because it involves renaming
files, this is probably not the preferred approach for a web site. The
alternative is pngcrush's <b class="emphasis-bold">-d</b> option, which allows one to specify an
output directory in which to place the crushed images:</p>
<blockquote><pre class="code">pngcrush -d crushed_images foo.png foo2.png foo3.png foo4.png</pre></blockquote>
<p>This example crushes the same four images, but leaves their filenames unchanged.
The new versions will go in the <em class="emphasis">crushed_images</em> subdirectory, which
will be created if it does not already exist.</p>
<p>The <b class="emphasis-bold">-rem</b> option
allows one to remove PNG chunks. This is quite handy, and is often a great way
to trim a few dozen bytes from files (which can make a big difference in the
case of small web graphics), but it does require knowledge of PNG's
chunk names. The following example removes any timestamp chunks and both
compressed and uncompressed text chunks from <em class="emphasis">foo.png</em> and places the
result in the <em class="emphasis">crushed</em> subdirectory:</p>
<blockquote><pre class="code">pngcrush -d crushed -rem tIME -rem zTXt -rem tEXt -rem iTXt foo.png</pre></blockquote>
<p>Note that this approach is somewhat akin to doing surgery with a hatchet:
one has no control over specific instances of the listed chunks in the case
of those (like zTXt, tEXt, and iTXt) that may appear more than once. In
particular, the tEXt or iTXt chunk is where copyright info usually appears,
and that is usually not something one wants to remove.<a href="#FOOTNOTE-30">[30]</a>
</p><blockquote class="footnote">
<a name="FOOTNOTE-30" /><p>[30] Of course, if a copyright is also embedded in the image data itself, the text
version may be superfluous.</p>
</blockquote>
<p><a name="INDEX-397" />One last option is worth a quick look. pngcrush's <b class="emphasis-bold">-g</b> option allows
one to set the gamma value of the image, which in turn provides for
cross-platform consistency of the overall brightness of the image. <a href="chapter10.html">Chapter 10, "Gamma Correction and Precision Color"</a>
covers gamma and color correction in more detail, but the effect will be
familiar to any site that uses both Macintoshes and PCs: images that look
good on Macs tend to look too dark on PCs, and images that look good on PCs
tend to look too bright and washed out on Macs. The solution
<?x-need 10?>is to include information about the system on which the image was
created, and PNG's gAMA chunk is the simplest and most effective means
of doing so. Unfortunately, not all image editors support gamma in
PNG, and as you saw in the previous chapter, some of those that do
support it store the wrong value. A site that has just received a
batch of PNG images from its Mac-based design department might do
something like the following:</p>
<blockquote><pre class="code">pngcrush -d crushed -replace_gamma 0.65909 mac.png mac2.png mac3.png</pre></blockquote>
<p>For images from a PC-based design group, the corresponding command is:</p>
<blockquote><pre class="code">pngcrush -d crushed -replace_gamma 0.45455 pc.png pc2.png pc3.png</pre></blockquote>
<p>In addition to optimizing the sizes of the images, these examples
strip any existing gamma information out of the files, on the
assumption that the values are known to be wrong and replace it with
values that are appropriate for stock Macs (with a factory-default
``system gamma'' value of 1.8) or stock PCs. If it is known that the
images that have gamma information are correct, use the <b class="emphasis-bold">-g</b>
option instead; it will add a gAMA chunk only to those images that do
not already have one.</p>
<p>I should note that pngcrush is still a relatively new utility, and it
does have a number of rough edges yet. For example, if an output file
already exists, it will be overwritten without warning. There is also
no recursion, no support for wildcards other than what the operating
system provides (i.e., only under Unix), and no way to set a default
extension or directory for crushed files (say, via an environment variable).
The program's extended options also assume a fairly advanced knowledge of
PNG files--for example, the official names
of PNG chunks, in the case of the <b class="emphasis-bold">-rem</b> option, or the numerical
color types used internally by PNG, or the precise palette index of the
color to be made transparent, in the case of the <b class="emphasis-bold">-trns</b> option.<a href="#FOOTNOTE-31">[31]</a>
Nor is there yet support for counting colors in images and automatically
converting from, say, RGB to palette format, although this is planned for
a future version. But these are relatively minor user interface issues
that will undoubtedly improve as the application matures. As regards its primary
purpose of squeezing PNG images as tightly as possible, pngcrush is quite
capable, and is likely to become an indispensable addition to the toolchest of
any image-wrangler.
<a name="INDEX-398" /></p><blockquote class="footnote">
<a name="FOOTNOTE-31" /><p>[31] Newer versions of pngcrush will print the palette, including indices, when
given both the <b class="emphasis-bold">-n</b> (``no crush'') and <b class="emphasis-bold">-verbose</b> options.</p>
</blockquote>
</div>
</div>
<div class="sect1"><a name="png.ch05.div.2" />
<h2 class="sect1">5.2. pnmtopng</h2>
<p>
<a name="INDEX-399" />
Possibly the most complete conversion program in existence, at least with
respect to support for PNG features, is <em class="emphasis">pnmtopng</em>. In conjunction with
its inverse,
<?hypen-place ?><em class="emphasis">pngtopnm</em>,
<?x-need 10?>and the rest of the NetPBM suite,<a href="#FOOTNOTE-32">[32]</a>
it is capable of handling basic conversions to and from virtually any image
format. But pnmtopng really shines as a tool for adding and modifying PNG
chunk information, including such things as text annotations, palette
optimization, and support for adding or removing alpha (transparency) channels.</p><blockquote class="footnote">
<a name="FOOTNOTE-32" /><p>[32] NetPBM originated as the PBMplus package, last released in December
1991. Subsequent third-party contributions from the Internet were gathered together
and released as NetPBM in 1993 and early 1994, containing some 200 utilities
for converting and manipulating images. The package has lain dormant since
then, aside from the occasional appearance of utilities to support new image
formats like PNG, but further news on this front is expected in 1999.</p>
</blockquote>
<p>Currently, the latest version of pnmtopng is 2.37.2, released in March
1999; it can be found on the PNG home site,
<a href="http://www.libpng.org/pub/png/apps/pnmtopng.html">http://www.libpng.org/pub/png/apps/pnmtopng.html</a>, along
with pointers to the libraries on which it depends.</p>
<p>Written and maintained by Alexander Lehmann and Willem van Schaik with
contributions and fixes from others, pnmtopng is primarily a
Unix-based tool, which unfortunately limits its usefulness to a
minority of computer users. But other parts of the NetPBM suite have
been ported to OS/2 and Windows, and it is likely that a future
release of both pnmtopng and NetPBM will be more portable and may even
include ready-to-go executables.</p>
<p><a name="INDEX-400" />
<a name="INDEX-401" />To begin explaining some of pnmtopng's features, it is first necessary to
describe a little about the PBM format itself. If one wishes to
be able to convert any of 100 possible image formats into any other, there
are two options: write 10,000 individual converters to go directly from
format A to format B for all possible pairs of A and B; or write only 200
converters, 100 to go from each of the image formats into some intermediate
representation and another 100 to convert back from that intermediate format
into the 100 target formats. Once the intermediate format exists, one
need not stop at conversion programs; generic utilities to manipulate images
suddenly become possible--for example, quantization, smoothing, cropping,
contrast enhancement, and so on.
</p>
<p>PBMplus/NetPBM is that intermediate format. It was originally designed by
Jef Poskanzer and released as the PBMplus suite, with later ``interim''
packages
released as NetPBM by Bill Davidsen. Since there has never been another PBMplus
release, I will henceforth refer to the format as NetPBM, the name by which it
is now most commonly known. The format is quite simple: three lines of text
header--which may additionally include one or more comment lines--followed
by the uncompressed image data. The image data may be stored as either text
or binary values; the latter is more efficient and far more commonly used, but
the existence of the text format means that one can actually create images or
color palettes in an ordinary text editor. There are also three basic NetPBM
image flavors: bilevel (or black and white), which is referred to as a
<a name="INDEX-402" />
<a name="INDEX-403" />
<a name="INDEX-404" />
<a name="INDEX-405" /><em class="emphasis">portable bitmap</em> or PBM file; grayscale, called a <em class="emphasis">portable graymap</em>
or PGM; and truecolor (RGB), referred to as a <em class="emphasis">portable pixmap</em> or PPM
file. Programs that can deal with more than one flavor
<?x-need 10?>usually have ``PNM''
in their names; this stands for <em class="emphasis">portable anymap</em>. There is currently no
``real'' PNM format; it is a virtual format and a convenient catchall name.</p>
<p>One notable feature missing from the NetPBM format is provision for
alpha channels; this is a known limitation<a href="#FOOTNOTE-33">[33]</a>
with implications for converting between formats that support transparency,
such as PNG, GIF, and TIFF. pnmtopng gets around this to some extent by the
simple expedient of storing transparency information in a separate grayscale
file. Before we get into that, let's look at some simpler cases.</p><blockquote class="footnote">
<a name="FOOTNOTE-33" /><p>[33] Alpha support is a major reason behind the expected NetPBM revisions in 1999.</p>
</blockquote>
<p>pnmtopng is a command-line program, and, thanks to its Unix heritage, it is
designed to operate as part of a multicommand pipeline. Unix pipes are a
slick method of connecting the output of one program into the input of another;
in principle there is no limit to how long such a chain can be, although in
practice the amount of system resources that are available may constrain
things. Here is a simple example that converts a GIF image into PNG:
<a name="INDEX-406" />
<a name="INDEX-407" /></p>
<blockquote><pre class="code">giftopnm foo.gif | pnmtopng > foo.png</pre></blockquote>
<p>The file <em class="emphasis">foo.gif</em> is read by <em class="emphasis">giftopnm</em> (part of the NetPBM suite)
and converted to NetPBM format, then piped into the input of pnmtopng, which
converts the image to PNG format. Since there are no more programs to be run,
pnmtopng's output is redirected into a file--in this case, <em class="emphasis">foo.png</em>.</p>
<p>Observant readers will recall that GIF images are always palette-based, yet
I didn't say anything about palettes in describing the NetPBM format. In
fact, NetPBM has no concept of palettes; giftopnm usually converts GIF images
into PPM format (the RGB flavor). Fortunately, pnmtopng is smart enough to
count the colors in an image and automatically write a palette-based PNG
image if there are 256 or fewer colors. It will likewise detect if a color
image is actually composed only of gray values; in that case, it will write
either a grayscale PNG or a palette-based one, depending on which can be
written with the fewest bits. This automatic checking comes at a cost, however:
because it requires inspection of every pixel, it can be quite slow for large
images. pnmtopng therefore includes a <b class="emphasis-bold">-force</b> option to skip the
checking. With this option, the previous example would result in
a 24-bit truecolor PNG:</p>
<blockquote><pre class="code">giftopnm foo.gif | pnmtopng -force > foo24.png</pre></blockquote>
<?x-need 10?><p>Here are examples for two other popular image formats, TIFF and JPEG:
<a name="INDEX-408" />
<a name="INDEX-409" /></p>
<blockquote><pre class="code">tifftopnm foo.tiff | pnmtopng > foo-was-tiff.png
djpeg foo.jpg | pnmtopng > foo-was-jpeg.png</pre></blockquote>
<p>But these are all trivial conversions. Suppose I would like to convert an
existing NetPBM image into an interlaced PNG, including gamma information, a timestamp,
and some text--say, the author's name, the title of the image, its copyright,
and perhaps the date on which the original photograph was taken. The first
thing we need to do is create a small text file containing the text information.
pnmtopng treats the first word on any line that does not begin with a
blank (either a space or a tab character) as the keyword, with the actual
text following. The text may stretch over several lines, and keywords with
spaces in them must be quoted. Thus the following text file, containing four
keywords and their corresponding values, would suffice:</p>
<blockquote>
<pre class="code">Title The Incredible and Rarely Seen Foo
Author Greg Roelofs
Copyright This image is hereby placed in the
public domain by its author.
"Creation Time" 4 July 1976
is the date on which this particular Foo was photographed.</pre>
</blockquote>
<p>Note that leading blanks (or ``white space''), including any between the
keywords and subsequent text, will not be included in the PNG text chunks.
But any newlines (or ``carriage returns,'' loosely speaking) will be included
exactly as typed; thus, there will be one in the Copyright text chunk, right
before the word ``public,'' and another in the Creation Time
text chunk, immediately after ``1976.'' In addition, there is currently a
bug in pnmtopng: when all of the text corresponding to a keyword appears on
a line following the keyword--that is, the keyword is immediately followed
by a carriage return--the program will sometimes crash. The problem will
almost certainly be fixed by the time this book reaches print, but in the
meantime, it can be avoided by adding a space after the keyword.</p>
<p>So assuming the text file were named <em class="emphasis">comments.txt</em> (and contains no
keywords followed immediately by newlines), the following command would
create the PNG image with the specified text and other information:</p>
<blockquote><pre class="code">pnmtopng -interlace -gamma 0.65909 -text comments.txt \
-time 1998-10-25 21:00:00 foo.ppm > foo.png</pre></blockquote>
<p>The first option is self-explanatory: the PNG image will be interlaced.
For the <b class="emphasis-bold">-gamma</b> option, we've used a value that corresponds to a
typical Macintosh; we're imagining that the original image was scanned and
tweaked on a Mac before being converted to PPM format (<em class="emphasis">foo.ppm</em>) on
some other system. The <b class="emphasis-bold">-time</b> option requires a little more
explanation. First, note that it is distinct from the ``Creation Time''
text chunk we included; the <b class="emphasis-bold">-time</b> option will write the special PNG
tIME chunk, which represents the time the image was last modified. But the
last modification time is clearly the time the image was converted into
PNG format, so pnmtopng really should not require the user to specify the
time information explicitly. This is particularly true, given that PNG's
time chunk is supposed to be in Coordinated Universal Time, and most users
are unlikely to know how to convert to that.<a href="#FOOTNOTE-34">[34]</a>
With luck, this oversight will also be corrected in the next release of the
program.</p><blockquote class="footnote">
<a name="FOOTNOTE-34" /><p>[34] The example here corresponds to 1:00 p.m. in the US/Pacific time zone. But had
the conversion taken place at 1:00 p.m. on the previous day, it would have been
specified as 20:00:00 in Universal Time, thanks to the fact that daylight
saving time had not yet ended.</p>
</blockquote>
<p><a name="INDEX-410" />Transparency is one of PNG's major strengths, so let's take a look at some
of pnmtopng's options there. Suppose that we wish to vignette our treasured
foo image--that is, we would like to apply an oval mask to it that gradually
fades to complete transparency, in effect transforming our image from
rectangular to rounded. This is easily accomplished by creating the oval
mask as a grayscale (PGM) image, where white represents the regions that will
be completely opaque (i.e., the main subject matter of the image) and black
the outer, transparent regions. Then give the following command:</p>
<blockquote><pre class="code">pnmtopng -alpha ovalmask.pgm foo.ppm > foo.png</pre></blockquote>
<p>This will ordinarily create a 32-bit RGBA image--in other words, truecolor
with a full alpha channel. But if it happens that the combination of the
original RGB image and the mask produces at most 256 RGBA combinations,
pnmtopng is smart enough to detect that and write a palette-based image
with transparency information instead. Moreover, it will automatically arrange
the palette and transparency entries so that all of the completely opaque
colors are at the end of the palette; the corresponding transparency entries
may then be omitted, resulting in a smaller file.
</p>
<p>In some cases, the transparency mask contains only fully opaque and fully
transparent values, and it may happen (usually by design) that the parts of
the underlying image that correspond to the transparent region are all one
color, even though there may be thousands of colors in the opaque part.
pnmtopng will again detect this, creating a palette-based image with just
one transparency entry if possible; if there are too many colors, it will
instead write a full grayscale or RGB image with a single color marked
transparent. This results in a PNG file that's much more compact than
one with a full alpha channel.</p>
<p>Transparent images intended for display only on web browsers will always
have some sort of background specified as part of the web page, but for
images that may be rendered by a standalone viewer, it is often desirable
to include an explicit background color in the image. The <b class="emphasis-bold">-background</b>
option provides that capability; it accepts a color argument in almost any
format allowed by MIT's X Window System, including English text (assuming the
X color database file can be found). Thus, the following three commands
are equivalent (the <b class="emphasis-bold">-alpha ovalmask.pgm</b> option has been omitted
for brevity):</p>
<blockquote><pre class="code">pnmtopng -background rgbi:1.0/0.855/0.726 foo.ppm > foo.png
pnmtopng -background "peach puff" foo.ppm > foo.png
pnmtopng -background "#ffdab9" foo.ppm > foo.png</pre></blockquote>
<p>For most users, the second form is probably the most easily understood but the
least precise. Making it precise requires the finely honed ability to find
the X color-database file, which can be difficult when it exists and impossible
when it doesn't<a href="#FOOTNOTE-35">[35]</a>
(it is also explicitly platform-dependent; that is, the same color name is
allowed to have different RGB values on different machines).
Therefore, the first form is likely to be the most useful. It specifies
the RGB values of the background color as decimal fractions
between 0.0 and 1.0. The values are separated by forward slashes
(<b class="emphasis-bold">/</b>) and prefixed by <b class="emphasis-bold">rgbi:</b>. The third form is the old-style
hexadecimal format that is favored by programmers but almost no one else.
(It also happens to be the format used in the demo programs I present in
<a href="chapter13.html">Chapter 13, "Reading PNG Images"</a> and <a href="chapter14.html">Chapter 14, "Reading PNG Images Progressively"</a> on reading PNG images. Oh, the embarrassment.) The
hex value need not be placed in quotation marks on a command line, but within a shell script it
should be quoted, or the hash character (<b class="emphasis-bold">#</b>) will be treated as the beginning
of a comment.</p><blockquote class="footnote">
<a name="FOOTNOTE-35" /><p>[35] For the record, it lives in <em class="emphasis">/usr/openwin/lib/X11/rgb.txt</em> on Sun
systems, <em class="emphasis">/usr/X11R6/lib/X11/rgb.txt</em> on most Linux and FreeBSD
systems, and <em class="emphasis">/usr/lib/X11/rgb.txt</em> on ``generic'' Unix/X11 systems.</p>
</blockquote>
<p>pnmtopng also potentially supports the creation of 16-bit-per-sample images
(that is, 16-bit grayscale, 32-bit gray+alpha, 48-bit RGB or 64-bit RGBA),
but only with text (ASCII) NetPBM files, and only if the underlying NetPBM
library supports 16-bit images, which is not the default behavior. The
requirement to use ASCII format for the 16-bit NetPBM image files is a current
limitation of the NetPBM suite. As with transparency and palettes, pnmtopng
detects if 16-bit samples are really just scaled 8-bit samples; if so, it will
automatically convert the image back to 8-bit samples unless the <b class="emphasis-bold">-force</b>
option is given. It can also be instructed to convert true 16-bit samples to
8-bit with the <b class="emphasis-bold">-downsample</b> option.</p>
<p>Other supported features include chromaticity information, histograms, compressed
text, explicit single-color transparency, physical pixel dimensions, and
special compression options. Quantization of truecolor images to 256 or
fewer colors is not supported by pnmtopng itself, but it is a straightforward
part of the standard NetPBM package. For example, to quantize a 24-bit TIFF
image to the 256 best colors, dither the result, and save it as a palette-based
PNG, one can use:
<a name="INDEX-411" /></p>
<blockquote><pre class="code">tifftopnm foo.tiff | ppmquant -fs 256 | pnmtopng > foo.png</pre></blockquote>
<?x-need 10?><p>The <b class="emphasis-bold">-fs</b> option to ppmquant instructs it to use Floyd-Steinberg
dithering, which generally looks very nice but does require a fair amount of
computation. The <b class="emphasis-bold">256</b> parameter indicates the number of colors to be
used in the final version; any value may be used (web-savvy designers might
wish to use a smaller number of colors), but only values of 256 or
less will result in a palette-based PNG image. What about images with an
alpha channel? Unfortunately, those who wish to quantize 32-bit RGBA images
down to a 256-entry ``RGBA palette'' are stuck for now. The ppmquant algorithm
can easily be modified to support RGBA values in addition to ordinary RGB,
but until NetPBM itself is updated, there is no way to pipe transparency information
from one NetPBM utility into another.</p>
<p>For users of very large images, one other point is worth mentioning: pnmtopng
currently reads the entire image into memory buffers before doing anything
with it, which means that a 4000 × 4000 RGBA image would require 64 megabytes
of real and/or virtual memory just for the uncompressed image itself. But
all is not lost; in <a href="chapter15.html">Chapter 15, "Writing PNG Images"</a>, I present a very
simple-minded NetPBM-to-PNG converter, and one of its design goals was the
ability to convert images on the fly, requiring only a very small memory
footprint. (Of course, this only works if the PNG image is not
interlaced.) The demo program also has a <b class="emphasis-bold">-time</b> option that
automatically records the current time in the proper format, as well as one
or two other potentially handy features.
<a name="INDEX-412" /></p>
</div>
<div class="sect1"><a name="png.ch05.div.3" />
<h2 class="sect1">5.3. gif2png</h2>
<p><a name="INDEX-413" />
<a name="INDEX-414" />For simple batch conversion of GIF images into PNGs, pnmtopng is not only
overkill but also somewhat tricky to automate. Such a task is more readily
handled by <em class="emphasis">gif2png</em>, a special-purpose conversion program written by
Alexander Lehmann. Besides the raw image pixels, there are three GIF
features that translate directly into PNG features: transparency, text
(comments), and interlacing. gif2png handles the first two automatically;
only interlacing is not detected and automatically applied to the output
image, although the program does include a <b class="emphasis-bold">-i</b> option to force
interlacing.</p>
<p>The simplest usage of gif2png is to give it the name of a GIF image:</p>
<blockquote><pre class="code">gif2png foo.gif</pre></blockquote>
<p>The program will convert the image to a noninterlaced PNG, preserving
any transparency, comments, and ``graphic control'' or ``application extension''
information. It will also add its own text chunk with the Software keyword,
and it will automatically change the file extension from <em class="emphasis">.gif</em>
to <em class="emphasis">.png</em>. There is one important caveat, however: the current version,
gif2png 0.6, does not check for an existing file of the same name and will
overwrite any such file without warning.</p>
<p>Because gif2png renames the files it converts without user input, it can
be used to convert a whole directory of GIF files in a single command.
Under Unix, where the shell expands wildcard filenames (``globbing''),
this is as simple as:</p>
<blockquote><pre class="code">gif2png *.gif</pre></blockquote>
<p>On other operating systems, the filenames must be specified explicitly:</p>
<blockquote><pre class="code">gif2png a.gif b.gif c.gif d.gif e.gif foo.gif foo2.gif</pre></blockquote>
<p>To prevent gif2png from adding a Software text chunk to the output image(s),
use the <b class="emphasis-bold">-s</b> option:</p>
<blockquote><pre class="code">gif2png -s foo.gif</pre></blockquote>
<p>To do the same conversion but to an interlaced PNG, include the <b class="emphasis-bold">-i</b>
option:</p>
<blockquote><pre class="code">gif2png -s -i foo.gif
gif2png -si foo.gif</pre></blockquote>
<p><a name="INDEX-415" />gif2png does have a few drawbacks, as might be expected given its pre-1.0
version number. In addition to the problem of overwriting existing files,
gif2png's conversion of GIF transparency information is less than ideal; although
it gets the job done, the program copies over the GIF palette without
modification, which can result in useless transparency entries in the PNG
file. For example, a 256-color GIF image whose last palette entry is the
transparent one would result in a 256-entry transparency chunk in the PNG
file, where one entry would suffice; in other words, it can waste up to 255
bytes in the output file. gif2png is also rather verbose and provides no
option to keep it quiet; in fact, its progress meter (a simple percentage
value, updated repeatedly) is supposed to be enabled only when the <b class="emphasis-bold">-p</b>
option is given, but it actually is on by default and can only be turned
<em class="emphasis">off</em> with <b class="emphasis-bold">-p</b>.</p>
<p>Despite all this, the program is quite stable and useful. It even converts
GIF comments from IBM codepage 437 to PNG's Latin-1 format, and it will
convert animated GIFs into multiple single-image PNGs. A planned option
that would have automatically deleted the GIF input images after conversion
was never implemented, nor was the capability of converting GIF Plain Text
Extensions into PNG gIFt chunks. But these are minor issues; in fact, the
gIFt chunk was officially declared Bad (that is, deprecated) in October 1998,
so its lack of support in gif2png turned out to be prescient. Indeed, the
only major problem with the program is the fact that it reads GIFs in the
first place. It is therefore (according to Unisys) subject to the LZW
<a name="INDEX-416" />patent and its associated licensing issues. Unisys initially claimed that
freeware GIF programs would be granted a free LZW license, but that later
changed, which was directly responsible for the cessation of further
development on gif2png.</p>
<p>The gif2png source code and ready-to-go binaries for Linux
can be found at <a href="http://www.catb.org/~esr/gif2png/"
>http://www.catb.org/~esr/gif2png/</a>. (Older binaries for
DOS, OS/2, Amiga, and Macintosh may still exist elsewhere on the Web.)
A graphical port written by Nigel Stewart for 32-bit Windows, called The
Exorcist, supports drag and drop and is available from its own home page:
<!--
<a href="http://www.eisa.net.au/~nigels/Exorcist/Exorcist.html"
>http://www.eisa.net.au/~nigels/Exorcist/Exorcist.html</a>.
-->
<a href="http://www.nigels.com/exorcist/Exorcist.html"
>http://www.nigels.com/exorcist/Exorcist.html</a>.
Version 1.1 is the latest release.
<a name="INDEX-417" />
<a name="INDEX-418" />
</p>
</div>
<div class="sect1"><a name="png.ch05.div.4" />
<h2 class="sect1">5.4. Tiff2png</h2>
<p><a name="INDEX-419" />
<a name="INDEX-420" />The corresponding special-purpose conversion program for TIFF images was
written by Willem van Schaik and is called, predictably, <em class="emphasis">Tiff2png</em>.
By a strange coincidence, its latest version is also 0.6, but the program
is perhaps slightly less robust than gif2png. This is primarily due to the
fact that the TIFF format is hugely complex, supporting multiple forms of
text annotations, both gamma and color correction, several flavors of
transparency, many different sample depths, and numerous other options that
might conceivably be carried over into a PNG image with a little effort (or,
more likely, a lot of it).</p>
<p>Tiff2png's main features as a conversion program are its support for TIFF
sample depths up to 16 bits and its support for transparency and alpha
channels. Unlike gif2png, Tiff2png requires an explicit output filename
and is therefore somewhat less convenient for batch conversions:</p>
<blockquote><pre class="code">tiff2png foo.tiff foo.png</pre></blockquote>
<p>It is also completely quiet by default, although it supports a <b class="emphasis-bold">-v</b>
option to turn on its verbose mode:</p>
<blockquote><pre class="code">tiff2png -v foo.tiff foo.png
Tiff2png: foo.tiff
TIFF Directory at offset 0x10008
Image Width: 128 Image Length: 128
Resolution: 72, 72 pixels/inch
Bits/Sample: 8
Compression Scheme: None
Photometric Interpretation: RGB color
Extra Samples: 1<assoc-alpha>
Samples/Pixel: 4
Rows/Strip: 16
Planar Configuration: single image plane
Tiff2png: 128x128x32 image
Tiff2png: 8 bits/sample, 4 samples/pixel
Tiff2png: maxval=255
Tiff2png: color-type = truecolor + alpha
Tiff2png: bit-depth = 8</pre></blockquote>
<?x-need 10?><p>Unfortunately, Tiff2png does not distinguish between associated (premultiplied)
alpha and unassociated alpha. The latter is the only form supported by PNG,
but Tiff2png will happily store an associated alpha channel without conversion,
as in the previous example.</p>
<p><a name="INDEX-421" />
<a name="INDEX-422" />The program also appears not to handle Intel-format
(``little-endian'': see the section entitled "Implementation" in
<a href="chapter07.html">Chapter 7, "History of the Portable Network Graphics Format"</a>) TIFF images with 16-bit samples correctly, instead storing
the samples as is--which effectively means they are inverted, given
that PNG samples must be stored in ``big-endian'' format. But lacking
any such sample images, I was unable to verify this.</p>
<p>At any rate, Tiff2png is capable of converting at least some TIFF images with
alpha transparency correctly, which gives it an advantage over the current
NetPBM suite and pnmtopng. Although TIFF is subject to the same LZW licensing
issues GIF is, it supports several other compression methods (including no
compression) and is therefore less of a problem for program authors. In
Tiff2png's case, all TIFF manipulations are handled via Sam Leffler's free
<a name="INDEX-423" /><b class="emphasis-bold">libtiff</b> library, which means Tiff2png itself can be updated at will
without worrying about the sorts of legal issues that plagued gif2png.
Source code for Tiff2png can be found on the PNG home site,
<a href="http://www.libpng.org/pub/png/apps/tiff2png.html">http://www.libpng.org/pub/png/apps/tiff2png.html</a>,
but there are presently no prebuilt executables.
<a name="INDEX-424" />
<a name="INDEX-425" />
</p>
</div>
<div class="sect1"><a name="png.ch05.div.5" />
<h2 class="sect1">5.5. pngcheck</h2>
<p>
<a name="INDEX-426" />
<a name="INDEX-427" />
<a name="INDEX-428" />
Finally, we should take a look at an extremely useful PNG utility that is not
usually considered a conversion tool: <em class="emphasis">pngcheck</em>. pngcheck prints the
chunks in a PNG file, along with their contents, in many cases; one can loosely
think of it as a utility that ``converts PNG images to text,'' although it
does so in such a way that they could never be converted back to PNG format.
(In particular, it provides no way to print the actual pixel data, although
it can print just about everything else.)</p>
<a name="INDEX-428.01-new" />
<p>Originally written by Alexander Lehmann as a simple tool to check PNG
images for corruption, such as might occur if the file were
transferred in text mode, pngcheck was subsequently extended by
Andreas Dilger, Greg Roelofs, and others, evolving into a nearly
complete PNG syntax checker and content dumper. The latest versions
(1.99-grr1 is current as of this writing) even include partial support
for MNG files, the multi-image PNG extension described in
<a href="chapter12.html">Chapter 12, "Multiple-Image Network Graphics"</a> (<em class="emphasis">Multiple-Image Network Graphics</em>). pngcheck is
most often used to understand why a particular image is larger than
expected--perhaps a 16-color image was saved in 24-bit RGB format
instead of palette format, or a truecolor image was saved with minimal
compression and no filtering. But it can also be used simply to test
PNG files
<?x-need 10?>and print their dimensions, image types, and approximate compression
<a name="INDEX-429" />ratios.<a href="#FOOTNOTE-36">[36]</a></p>
<blockquote class="footnote">
<a name="FOOTNOTE-36" /><p>[36] The compression ratio is computed by dividing the total file size
by the nominal size of the uncompressed IDAT data, which means the presence
of ancillary information or even a required palette can produce negative
compression ratios--i.e., ``expansion''--in small images. In other words,
don't take it too seriously.</p>
</blockquote>
<p>The most basic use of pngcheck involves giving it one or more filenames and
no options, like so:</p>
<blockquote><pre class="code">pngcheck foo.png foo2.png foo3.png</pre></blockquote>
<p>This results in output similar to the following, except that here the lines
have been wrapped to fit the page:</p>
<blockquote><pre class="code">No errors detected in
foo.png (578x802, 24-bit RGB, interlaced, 54.7%).
No errors detected in
foo2.png (32x32, 4-bit colormap, interlaced, 36.1%).
No errors detected in
foo3.png (32x32, 64-bit RGB+alpha, non-interlaced, 58.1%).</pre></blockquote>
<p>An image that has been corrupted in some way might cause an error message
such as the following:</p>
<blockquote><pre class="code">foo4.png: File is CORRUPTED by text conversion.
foo4.png: Chunk name 00 0d 49 48 doesn't conform to naming rules.</pre></blockquote>
<p>But pngcheck is most useful for seeing what's inside a PNG image. The
<b class="emphasis-bold">-v</b> option, for <em class="emphasis">verbose</em> mode, prints the name of each chunk
within the file, along with some basic information wherever appropriate. Because
it can be a tad lengthy, it is often a good idea to pipe the program's
verbose output through a paging filter such as <em class="emphasis">more</em>. The following
example works on both Unix-based systems and DOS, OS/2, and Windows command
lines:</p>
<blockquote><pre class="code">pngcheck -v imgcomp.png | more
File: imgcomp.png (34163 bytes)
chunk IHDR at offset 0x0000c, length 13
640 x 480 image, 32-bit RGB+alpha, non-interlaced
chunk gAMA at offset 0x00025, length 4: 0.45455
chunk IDAT at offset 0x00035, length 8192
zlib: deflated, 32K window, default compression
chunk IDAT at offset 0x02041, length 8192
chunk IDAT at offset 0x0404d, length 8192
chunk IDAT at offset 0x06059, length 8192
chunk IDAT at offset 0x08065, length 1274
chunk IEND at offset 0x0856b, length 0
No errors detected in imgcomp.png (97.2% compression).</pre></blockquote>
<p>In this example, we see a fairly basic PNG file, a truecolor image with an
alpha channel, composed of only four chunk types: the required IHDR, IDAT,
and IEND chunks (described in <a href="chapter08.html">Chapter 8, "PNG Basics"</a>), plus the optional but highly
recommended gamma-correction chunk, gAMA (<a href="chapter10.html">Chapter 10, "Gamma Correction and Precision Color"</a>). Because the image
primarily consists of solid-colored regions and simple gradients, it compressed
unusually well; this probably indicates that dynamic filtering was used, but
there is no way to be certain, given the preceding information.
</p>
<a name="INDEX-429.01-new" />
<p>However, pngcheck can optionally use the zlib compression library in
order to look <em class="emphasis">inside</em> the compressed image data. In this case, it supports
a <b class="emphasis-bold">-vv</b> option (``very verbose'') that prints out all of the preceding information
plus filtering information. The filter output can be extremely long; for
just the first IDAT chunk in the preceding example, it looks like this:</p>
<blockquote><pre class="code"> chunk IDAT at offset 0x00035, length 8192
zlib: deflated, 32K window, default compression
zlib line filters (0 none, 1 sub, 2 up, 3 avg, 4 paeth):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 2 2 1 2 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 4 4 4 4 4 4 4 4 4 4 4 4 1 4 1 4 1 4 2 4
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 4 4 4 2
(200 out of 480)</pre></blockquote>
<p>The details are too complex to cover right now, but filtering and compression
are discussed in <a href="chapter09.html">Chapter 9, "Compression and Filtering"</a>. All that matters here is that different filters
have been used for different rows in the image, indicating that some sort of
dynamic filtering was applied (which is generally good). Unfiltered images,
on the other hand, will have all zeros for the filter numbers, and statically
filtered images will use only a single filter type. In most cases, that means
the image is not compressed as well as it could be. One major exception,
however, is palette-based images; they rarely respond well to filtering, and
most programs don't try.</p>
<p>pngcheck also supports more specific types of output. Its <b class="emphasis-bold">-p</b> option,
for example, is another rather verbose case; it prints the contents of the
palette and optional transparency chunks for colormapped images.<a href="#FOOTNOTE-37">[37]</a>
This can be useful in conjunction with a program such as pngcrush, for example,
when one wishes to specify a particular color as transparent, but more commonly
it is used to check whether the transparency chunk is full of needless opaque
values. Consider the following example:</p><blockquote class="footnote">
<a name="FOOTNOTE-37" /><p>[37] It will also print the contents of the optional histogram and suggested-palette
chunks; see <a href="chapter11.html">Chapter 11, "PNG Options and Extensions"</a>, for details.</p>
</blockquote>
<blockquote><pre class="code">pngcheck -p foo5.png
File: foo5.png (146 bytes)
PLTE chunk: 4 palette entries
0: ( 0,255, 0) = (0x00,0xff,0x00)
1: (255, 0, 0) = (0xff,0x00,0x00)
2: (255,255, 0) = (0xff,0xff,0x00)
3: ( 0, 0,255) = (0x00,0x00,0xff)
tRNS chunk: 3 transparency entries
0: 255 = 0xff
1: 255 = 0xff
2: 0 = 0x00
No errors detected in foo5.png (32x32, 2-bit colormap, non-interlaced,
43.0%).</pre></blockquote>
<p>Here we have a four-color image: bright green, red, yellow, and blue. The
colors of the palette are listed as RGB triplets in both decimal
and hexadecimal (base 16) for convenience. The palette itself is unremarkable;
what is more interesting is the transparency chunk, tRNS. It includes three
entries, but the first two have the value 255, which indicates that the
corresponding palette entries should be treated as completely opaque. But
all palette entries are considered opaque unless explicitly given a
non-opaque transparency value--in other words, any transparency entries with
the value 255 are redundant and represent wasted space. In this case, the only
non-opaque entry corresponds to the third color, yellow; a smart
PNG-writing program would have reordered the palette so that yellow was the
first entry, thus shaving two bytes off the file. It is not uncommon to be
able to save 100 or more bytes in this manner, which can represent 10% to 20%
of the file size for small web graphics.<a href="#FOOTNOTE-38">[38]</a>
In rare cases, it may be worthwhile to waste a few transparency entries
so that the most common pixels in the image are all at the beginning of the
palette (i.e., so they all have index values near zero); with filtering
enabled, the compression engine may be able to make up the difference and
then some. But as of early 1999, filtering has yet to be demonstrated
effective on essentially any kind of palette-based image, so the possibility
of recovering wasted transparency entries with improved compression is a
rather tenuous one.</p>
<blockquote class="footnote">
<a name="FOOTNOTE-38" /><p>[38] One of the images used on the VRML98 web site had 211 transparency entries,
of which 210 were unnecessary.</p>
</blockquote>
<p>The other type of verbose pngcheck output is more useful to ordinary
users, not just content developers trying to optimize things. The <b class="emphasis-bold">-t</b>
option prints not only text chunks' keywords but also their contents:</p>
<blockquote><pre class="code">pngcheck -t ct1n0g04.png
File: ct1n0g04.png (796 bytes)
Title:PngSuite
Author:Willem A.J. van Schaik
(gwillem@ntuvax.ntu.ac.sg)
Copyright:Copyright Willem van Schaik, Singapore 1995
Description:A compilation of a set of images created to test the
various color-types of the PNG format. Included are
black&white, color, paletted, with alpha channel, with
transparency formats. All bit-depths allowed according
to the spec are present.
Software:Created on a NeXTstation color using "pnmtopng".
Disclaimer:Freeware.
No errors detected in
ct1n0g04.png (32x32, 4-bit grayscale, non-interlaced, -55.5%).</pre></blockquote>
<p>This example, using one of Willem van Schaik's test images from the PNG Suite,
contains six text chunks with keywords Title, Author,
Copyright, Description, Software, and Disclaimer.
The content of each chunk immediately follows the keyword and colon; this is
not the most readable approach, but the information is available and usually
understandable with only a little squinting. One deficiency of the current
version is that it does not display the contents of compressed text chunks
(zTXt), even when using the zlib compression library. This is promised to be
fixed in a future version, however.</p>
<p>The latest version of pngcheck can be found at the PNG home site,
<a href="http://www.libpng.org/pub/png/apps/pngcheck.html">http://www.libpng.org/pub/png/apps/pngcheck.html</a>.
<a name="INDEX-430" />
<a name="INDEX-431" />
<a name="INDEX-432" />
</p>
</div>
<div class="sect1"><a name="png.ch05.div.6" />
<h2 class="sect1">5.6. Other Conversion Programs</h2>
<p>The converters we've discussed so far barely scratch the surface of
what is available. If one includes image editors and viewers that can
convert images in addition to dedicated conversion tools, there are
well over one hundred applications capable of converting to and from
the PNG format.<a href="#FOOTNOTE-38b"><font color="#006600">[38b]</font></a>
Many of these were listed in the previous two chapters
and are well worth considering, particularly for users who may be
uncomfortable dealing with command-line programs.</p>
<!-- GRR POST-1999 UPDATE -->
<font color="#006600">
<blockquote class="footnote">
<a name="FOOTNOTE-38b" />
<p>[38b] As of mid-2003, the number has more than doubled; the
<a href="http://www.libpng.org/pub/png/pngapcv.html"><font color="#006600">PNG
home site</font></a> lists all of them. Perhaps not surprisingly, however,
the five discussed above are still among the best.</p>
</blockquote>
</font>
<!-- END GRR POST-1999 UPDATE -->
<p>Here is a list of some of the other dedicated (or nearly dedicated) image
converters that support PNG. The most recent version as of January 1999 is
given wherever possible.</p>
<dl>
<dt><b><em class="emphasis">ColourEdit</em></b></dt><dd><p><a name="INDEX-433" />Version of April 3, 1997, Julian Highfield. Available as
an OpenDoc part for Mac 68k/PPC (mostly tested with OpenDoc 1.1 and Mac OS
System 7.1.2); read/write support for PNGs.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.stile.lboro.ac.uk/~cojch/ColourEdit/">http://www.stile.lboro.ac.uk/~cojch/ColourEdit/</a></pre></blockquote><dl>
<dt><b><em class="emphasis">Creator</em></b></dt><dd><p><a name="INDEX-434" />Version 3.22, John Kortink. Available for Acorn RISC OS;
read/write support for PNGs; no alpha or gamma support.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://web.inter.nl.net/users/J.Kortink/indexsw.htm">http://web.inter.nl.net/users/J.Kortink/indexsw.htm</a></pre></blockquote><dl>
<dt><b><em class="emphasis">dicom2</em></b></dt><dd><p><a name="INDEX-435" />Version 1.8, Sébastien Barré. Available for Windows
9x/NT, Linux x86, SunOS/Solaris SPARC; write-only support for PNGs; supports
conversion of 12-bit medical formats to 16-bit grayscale PNGs.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.hds.utc.fr/~barre/medical/dicom2/">http://www.hds.utc.fr/~barre/medical/dicom2/</a></pre></blockquote><dl>
<dt><b><em class="emphasis">Ghostscript</em></b></dt><dd><p><a name="INDEX-436" />Version 5.50, Aladdin Enterprises. Available for Unix,
VMS, OS/2, Windows 9x/NT, and Mac 68k/PPC; older versions available for
Windows 3.x, DOS, Amiga, Atari, and possibly Acorn RISC OS; write-only support
for PNGs.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.cs.wisc.edu/~ghost/">http://www.cs.wisc.edu/~ghost/</a></pre></blockquote><dl>
<dt><b><em class="emphasis">gj2png</em></b></dt><dd><p><a name="INDEX-437" />Version of February 13, 1997, Neil Aggarwal. Available for any
platform supporting Java 1.1 or later; write-only support for PNGs.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.anet-dfw.com/~neil/gjFrame.html">http://www.anet-dfw.com/~neil/gjFrame.html</a></pre></blockquote><dl>
<dt><b><em class="emphasis">Icons Control 95</em></b></dt><dd><p><a name="INDEX-438" />Version 7.02, Chris Doan. Available for Windows
9x/NT; read-only support for PNGs (converts various image formats to
Windows <em class="emphasis">.ico</em> format).</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://members.aol.com/doanc/icnctrl.html">http://members.aol.com/doanc/icnctrl.html</a></pre></blockquote><dl>
<dt><b><em class="emphasis">Image Arithmetic</em></b></dt><dd><p><a name="INDEX-439" />Version 2.2a, Richard van Paasen. Available for
Windows 9x/NT; read/write support for PNGs.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://huizen.dds.nl/~buddha/imgart.html">http://huizen.dds.nl/~buddha/imgart.html</a></pre></blockquote><dl>
<dt><b><em class="emphasis">LatinByrd</em></b></dt><dd><p><a name="INDEX-440" />Version III v6, Stefan Schneider Software. Available for
NeXTStep/OpenStep on 68k/x86/HP-PA/SPARC; write-only support for PNGs; can
quantize 32-bit RGBA TIFF images to 8-bit RGBA-palette PNGs.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://members.ping.at/stefan/LatinByrdProductInfo.html">http://members.ping.at/stefan/LatinByrdProductInfo.html</a></pre></blockquote><dl>
<dt><b><em class="emphasis">PicCon</em></b></dt><dd><p><a name="INDEX-441" />Version 2.50, Morten Eriksen. Available for Amiga; read-only;
requires a PNG datatype such as those from Cloanto or Andreas Kleinert.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.aminet.org/pub/aminet/gfx/conv/PicCon250.lha">http://www.aminet.org/pub/aminet/gfx/conv/PicCon250.lha</a>
<a href="http://www.aminet.org/pub/aminet/util/dtype/PNG_dt.lha">http://www.aminet.org/pub/aminet/util/dtype/PNG_dt.lha</a>
<a href="http://www.aminet.org/pub/aminet/util/dtype/akPNG-dt.lha">http://www.aminet.org/pub/aminet/util/dtype/akPNG-dt.lha</a>
<a href="http://home.t-online.de/home/Andreas_Kleinert/support.htm">http://home.t-online.de/home/Andreas_Kleinert/support.htm</a></pre></blockquote><dl>
<dt><b><em class="emphasis">PNG-Box</em></b></dt><dd><p><a name="INDEX-442" />Version 3.25, Andreas Kleinert. Available for Amiga 68k/PPC;
write-only support for PNGs; supports interlacing and single-color transparency.
PNG-Box is a graphical ``any to PNG'' conversion utility that uses Andreas's own
SuperView Library for its image support instead of datatypes.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.amigaworld.com/support/png-box/">http://www.amigaworld.com/support/png-box/</a>
<a href="http://home.t-online.de/home/Andreas_Kleinert/support.htm">http://home.t-online.de/home/Andreas_Kleinert/support.htm</a>
<a href="http://www.aminet.org/pub/aminet/gfx/conv/PNG-Box.lha">http://www.aminet.org/pub/aminet/gfx/conv/PNG-Box.lha</a></pre></blockquote><dl>
<dt><b><em class="emphasis">!Png2Spr</em></b></dt><dd><p><a name="INDEX-443" />Version 1.14, Tom Tanner. Available for Acorn RISC OS;
read-only support for PNGs (converts to Acorn sprite format).</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.argonet.co.uk/users/ttehtann/">http://www.argonet.co.uk/users/ttehtann/</a></pre></blockquote><dl>
<dt><b><em class="emphasis">ptot</em></b></dt><dd><p><a name="INDEX-444" />Version of March 10, 1995, Lee Daniel Crocker. Available as
portable source code (does <em class="emphasis">not</em> require libpng or zlib);
read-only support for PNGs (converts to TIFF); full gamma support (writes
TIFF TransferFunction tag); full alpha support for true alpha channels (no
palette-alpha or ``cheap transparency'' support).</p></dd>
</dl>
<blockquote><pre class="code"><a href="ftp://swrinde.nde.swri.edu/pub/png/applications/ptot.tar.gz">ftp://swrinde.nde.swri.edu/pub/png/applications/ptot.tar.gz</a></pre></blockquote><dl>
<dt><b><em class="emphasis">SmartSaver</em></b></dt><dd><p><a name="INDEX-445" />Version 3.0, Ulead Systems. Available for 32-bit Windows;
read/write support for PNGs; full alpha support, including at least single-color
palette transparency (not clear whether full RGBA-palette translucency is
supported); reportedly cannot write 1-bit (bilevel) images.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.webutilities.com/ssaver/noslip.htm">http://www.webutilities.com/ssaver/noslip.htm</a></pre></blockquote><dl>
<dt><b><em class="emphasis">Spr2Png</em></b></dt><dd><p><a name="INDEX-446" />Version 0.04b, Darren Salt. Available for Acorn RISC OS;
write-only support for PNGs; full alpha support via secondary sprite that is
used as a transparency mask or alpha channel; supports interlacing and
background color. An older version was reported
<?x-need 10?>to produce streaks in
conversions of newer (post-RPC) sprites, but this appears to be fixed in the
current release.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.youmustbejoking.demon.co.uk/progs.html#spr2png">http://www.youmustbejoking.demon.co.uk/progs.html#spr2png</a></pre></blockquote><dl>
<dt><b><em class="emphasis">ThumbNailer</em></b></dt><dd><p><a name="INDEX-447" />Version 5.2, Smaller Animals Software. Available for
32-bit Windows; read/write support for PNGs; supports transparency, background
color, and text; claims full gamma support.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://www.smalleranimals.com/thumb.htm">http://www.smalleranimals.com/thumb.htm</a></pre></blockquote><dl>
<dt><b><em class="emphasis">Ultraconv</em></b></dt><dd><p><a name="INDEX-448" />Version 3.0p1, Felix Schwarz. Available for Amiga 68k/PPC;
read/write support for PNGs (natively since version 1.6, or via a datatype for
earlier versions); no alpha or gamma support.</p></dd>
</dl>
<blockquote><pre class="code"><a href="http://home.pages.de/~uconv/">http://home.pages.de/~uconv/</a></pre></blockquote><p>New conversion utilities and updated information on the ones listed here can
be found at the <em class="emphasis">Image-Conversion Applications with PNG Support</em> web page
at the PNG home site, <a href="http://www.libpng.org/pub/png/pngapcv.html">http://www.libpng.org/pub/png/pngapcv.html</a>.
This URL is expected to be stable for years, but of course there are no
guarantees on the World Wide Web! Use a search engine to look for the title
string or for one of the more oddly named utilities listed if the link
should ever break.
<a name="INDEX-449" /></p>
</div>
<hr> <!-- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -->
<a href="chapter04.html"><img width=24 height=13 border=0 align="left"
src="images/prev.png" alt="<-"></a>
<a href="chapter06.html"><img width=24 height=13 border=0 align="right"
src="images/next.png" alt="->"></a>
<div align="center">
<a href="chapter04.html"><font size="-1" color="#000000"
><b>PREVIOUS</b></font></a> <a
href="toc.html"><font size="-1" color="#000000"
><b>CONTENTS</b></font></a> <a
href="chapter06.html"><font size="-1" color="#000000"
><b>NEXT</b></font></a>
</div>
<hr> <!-- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -->
</body></html>
|