home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 November / Chip_2004-11_cd1.bin / software / optipng / DESIGN.txt < prev    next >
Text File  |  2003-06-11  |  12KB  |  281 lines

  1.  
  2. OptiPNG - Design decisions and rationale
  3. ========================================
  4.  
  5. Everyone is welcome to contribute to the development of OptiPNG.
  6. This document provides useful information to the potential
  7. contributors, but many general advices given here may be followed
  8. by any programmer.
  9.  
  10.  
  11. Quality
  12. -------
  13.  
  14. Priority has been given to the following quality factors, in
  15. decreasing order of importance:
  16.  
  17. 1. Correctness.
  18.    The most important goal is to produce PNG files that comply
  19.    to the PNG specification. The code is written with great care,
  20.    and it is tested extensively.
  21.    Bug reports may be sent to <cosmin@cs.toronto.edu>
  22.  
  23. 2. Efficiency.
  24.    OptiPNG is designed to be fast. It needs to run a series of
  25.    brute-force trials, and the biggest amount of time is spent
  26.    during zlib compression and decompression, and during I/O.
  27.    This amount of time is reduced to a minimum:
  28.  
  29.    - No auxiliary I/O (i.e. no temporary files) is involved in
  30.      the trials. Instead, the standard libpng I/O routines are
  31.      redirected using the png_set_read_fn, png_set_write_fn
  32.      functions, to a customized function optipng_read_write_data
  33.      that gathers the necessary statistics, and writes the chunk
  34.      data to a file only in the final optimization step.
  35.  
  36.    - There is a single decompression step per file.
  37.  
  38.    - The output file is recompressed only if the trials indicate
  39.      that the file size will decrease.
  40.  
  41.    - While it is still possible to further reduce the amount of
  42.      time spent during trials (e.g. by estimating the compressed
  43.      size without actually producing the compressed zlib stream),
  44.      this cannot be achieved without breaking the encapsulation
  45.      of the zlib library. Since correctness can be at risk, this
  46.      aspect of efficiency has not been considered.
  47.  
  48. 3. Readability and maintainability.
  49. ["Premature optimization is the root of all evil." - D. E. Knuth]
  50.  
  51.    OptiPNG is not a simple application, even though the code is
  52.    clear and well commented. It may be possible to optimize the
  53.    code even more, and sacrifice some readability, by inlining
  54.    functions manually, eliminating the overhead of the structured
  55.    exception handling, etc. There is a strong word of caution
  56.    against this, because the time spent in OptiPNG is minimal,
  57.    and such gain is insignificant. No visible extra performance
  58.    will be achieved, and readability will have much to suffer.
  59.  
  60.    There is a particular issue characteristic to some PNG
  61.    processing applications, which should be avoided:
  62.  
  63.    It is customary for the libpng-dependent applications to check
  64.    at compile time if certain features are supported. If some
  65.    feature is not supported by the particular version and build
  66.    of libpng which exists in the system, the program logic is
  67.    split in two or more branches, increasing the difficulty of
  68.    comprehending and maintaining it. For example:
  69.  
  70. #if PNG_FLOATING_POINT_SUPPORTED
  71.    implement a certain application feature using the libpng
  72.    floating point routines
  73. #elif PNG_FIXED_POINT_SUPPORTED
  74.    implement the same feature using the libpng fixed point
  75.    routines
  76. #else
  77.    implement the same feature using hand-crafted code, or do not
  78.    implement it at all, crippling the application
  79. #endif
  80.  
  81.    In this case, the maintainability has much to suffer, and the
  82.    only gain is an easier build process. Two pieces of code that
  83.    are expected to do the same thing are a source of problems,
  84.    especially when the person who modifies them is not completely
  85.    aware of the situation.
  86.    It is much less painful to simply _require_ a certain libpng
  87.    feature:
  88.  
  89. #ifndef PNG_FIXED_POINT_SUPPORTED
  90. #error This program requires libpng with fixed point processing
  91. #endif
  92.  
  93.    The disadvantage of the latter approach is possibly a more
  94.    inconvenient build process, in which libpng may have to be
  95.    rebuilt and linked statically. This is much smaller, though,
  96.    and a bloat of roughly 100K in the executable is less
  97.    problematic, compared to having a crippled product, or a
  98.    product of lower quality.
  99.  
  100. 4. Functionality.
  101.    OptiPNG serves its primary goal: to optimize the size of the
  102.    given PNG files. Additional features can be added (e.g. error
  103.    recovery, or basic metadata editing at the chunk level), as
  104.    long as the level of the other quality factors, especially of
  105.    those with a higher priority, is preserved.
  106.    The ability to read external formats such as PNM, GIF, BMP, or
  107.    even JPEG and JP2 has been considered. It has not been decided
  108.    yet whether to implement this by hand-crafted code, or by
  109.    using external code such as the JasPer library. Again, all the
  110.    other quality factors must not be ignored.
  111.  
  112. 5. Portability.
  113.    - Language and standard library:
  114.      The program is written in pure ANSI/ISO (Standard) C.
  115.      If Standard C is not enough to implement some potentially
  116.      useful feature (e.g. directory traversal), it may be
  117.      necessary to reduce the level of portability to POSIX.
  118.      Most of today's platforms, including Windows, offer some
  119.      degree of POSIX functionality.
  120.  
  121.    - Machine:
  122.      The program is designed to run on any 32-bit machine.
  123.      Porting the program to a 16-bit machine is feasible, but
  124.      this should be done without sacrificing simplicity.
  125.      Given the nature of the PNG optimization task, the program
  126.      should not be run on old and slow machines, or on machines
  127.      with limited memory.
  128.  
  129.    - External dependencies/libraries:
  130.      Portability is one of the most important factors when
  131.      developing software libraries, because it is difficult or
  132.      impossible to control the applications that use established
  133.      features. On the other hand, applications that are at the
  134.      end of the dependency tree, such as OptiPNG, may take more
  135.      liberal decisions for the benefit of other quality factors.
  136.      In this case, the readability and maintainability are given
  137.      a higher priority over portability.
  138.  
  139.  
  140.  
  141. Usage
  142. -----
  143.  
  144. The program usage is typical to the category of command-line
  145. applications. There are some peculiarities, however, which are
  146. enumerated below.
  147.  
  148. * Input and output file specification.
  149.   Given the nature of this task, it is difficult for OptiPNG to
  150.   use the standard input and act as a program filter.
  151.   We considered the following alternatives:
  152.  
  153.   1. Explicit specification of the input files, which will be
  154.      overwritten by the optimized output files.
  155.         optipng input1.png input2.png input3.png
  156.      This behavior is similar to that of compress, gzip and other
  157.      Unix utilities. At the user's option, the input is preserved
  158.      in backup files.
  159.      This approach is more natural to batch processing. It is
  160.      easy, for example, to run OptiPNG in a WWW directory and
  161.      optimize all the PNG files, leaving everything else in
  162.      place.
  163.      Another advantage resides in a higher processing speed, when
  164.      the input file is already optimized. Instead of being copied
  165.      to an identical output file, it is just left in place.
  166.  
  167.   2. Explicit specification of the input and output files:
  168.         optipng input.png output.png
  169.      This may be more useful for experimentation purposes, but it
  170.      is more onerous for the regular user. Running the program in
  171.      batch mode is still possible, but that would require an
  172.      alternate mode, such as:
  173.         optipng -multi input1.png input2.png input3.png
  174.         optipng input1.png input2.png input3.png -dir outdir/
  175.      The disadvantages of this approach are the inconsistency
  176.      between the two modes, and the difficulty to run the
  177.      optimization in-place.
  178.  
  179.   The first alternative serves the purpose better. Given that
  180.   OptiPNG transforms the input losslessly, even the accidental
  181.   omission of the backup option by the user does not lead to
  182.   data loss.
  183.  
  184. * Option specification.
  185.   The options are preceded by a single dash '-' and are
  186.   case-insensitive. Single-letter options cannot be contracted;
  187.   e.g. "optipng -k -q" cannot be contracted to "optipng -kq".
  188.   There is no need to use a double dash to specify a long option,
  189.   e.g. -q, -quiet and --quiet are equivalent. Double-dashed
  190.   option specification is used mainly as a work around problems
  191.   of compatibility in programs that used option contraction in
  192.   the older versions. Even if newer programs use double-dashed
  193.   option specification, with or without allowing contractions,
  194.   this is not necessarily good style.
  195.   On the other hand, multiple dashes are accepted by OptiPNG.
  196.  
  197. On a side note: while case sensitivity is useful in C, mainly to
  198. resolve issues raised by macro-processing, it is a mixed blessing
  199. in the Unix file system. If two names of two different files are
  200. distinguished only by one or more capital letters, these names
  201. still say and mean the same thing. No good directory organization
  202. should have two such files in the same directory.
  203. From this point of view, the Windows approach where the letter
  204. case is retained, but the access is case-independent, is better.
  205. At least we are lucky that email addresses are case-insensitive...
  206.  
  207.  
  208.  
  209. File recovery
  210. -------------
  211.  
  212. A regular PNG decoder may choose to stop the decoding process
  213. whenever it detects problems with the input. On the other hand,
  214. at the user's option, OptiPNG can ignore non-fatal errors and
  215. replace the bad input with a corrected output. Currently, OptiPNG
  216. accepts files that have bad CRCs in non-critical chunks, and
  217. files that end unexpectedly (they have incomplete chunks, or they
  218. do not have the IEND chunk), provided that they have IDAT and all
  219. the other critical chunks are in good condition.
  220. The error recovery is provided via structured exception handling
  221. (see below).
  222.  
  223.  
  224.  
  225. Compiler optimizations
  226. ----------------------
  227.  
  228. It is essential for this program to run as fast as possible.
  229. Here are some advices on how to adjust the compiler parameters in
  230. order to obtain the best speed results, and still to maintain a
  231. small size of the executable.
  232.  
  233. - Compile the zlib library using the most aggressive set of
  234.   optimizations, such as "gcc -O3". Loop unrolling may also be
  235.   enabled. Most of the time is spent by this code, and it is
  236.   important to optimize it to the maximum extent possible.
  237.  
  238. - Compile the libpng library and the OptiPNG source code using
  239.   a set of optimizations that do not sacrifice the code size,
  240.   such as "gcc -O2". The speed of the OptiPNG program is
  241.   determined by the speed of the compression and decompression
  242.   routines (zlib), and the amount of time spent doing other tasks
  243.   is insignificant, so this code needs not be inlined. Besides,
  244.   too much inlining may increase the chance of cache penalty,
  245.   with a negative effect on program execution.
  246.  
  247. - Remove the libpng features that are unnecessary for OptiPNG.
  248.   This is possible by #defining PNG_NO_XXX macros when compiling
  249.   libpng. Here are a few examples:
  250.     PNG_NO_FLOATING_POINT_SUPPORTED    // not needed for now
  251.     PNG_NO_MNG_FEATURES            // no MNG support for now
  252.     PNG_NO_SETJMP_SUPPORTED        // see "Exception handling"
  253.     PNG_NO_READ_TRANSFORMS
  254.     PNG_NO_WRITE_TRANSFORMS
  255.  
  256.  
  257.  
  258. Exception handling
  259. ------------------
  260.  
  261. It is unfortunate that C does not provide an exception handling
  262. system, and the standard alternatives (returned error codes or
  263. the setjmp mechanism) are many times unsatisfactory.
  264. OptiPNG uses CEXCEPT, an ultra-thin abstraction layer that
  265. implements structured exception handling on top of the setjmp
  266. mechanism.
  267.  
  268. Essentially, the CEXCEPT exception handling system defines macros
  269. such as Throw, Try, Catch, which are used by OptiPNG. The
  270. multi-layered approach to throwing, catching and re-throwing
  271. exceptions allows the program to continue with the next file,
  272. even if fatal errors occur inside libpng. By using CEXCEPT, the
  273. source code is very clean, and the performance overload is
  274. insignificant.
  275.  
  276. There are many issues pertaining to how the CEXCEPT macros work,
  277. and they can be read inside the "cexcept.h" file. If OptiPNG or
  278. portions of it are ported to C++, it is strongly recommended to
  279. use the native C++ exception handling instead.
  280.  
  281.