This is getting fucking ridiculous.
[zpng.git] / doc / index.html
blob14bfe042b927268a5f0068ec3b967402b61dd4e8
1 <html>
2 <head>
3 <title>ZPNG - Create PNG files from Common Lisp</title>
4 <style type="text/css">
5 a, a:visited { text-decoration: none }
6 a[href]:hover { text-decoration: underline }
7 pre { background: #DDD; padding: 0.25em }
8 p.download { color: red }
9 .transparent { background-image: url(background.gif) }
10 tt.code { background: #DDD }
11 </style>
12 </head>
14 <body>
16 <h2>ZPNG - Create PNG files from Common Lisp</h2>
18 <blockquote class='abstract'>
19 <h3>Abstract</h3>
21 <p>ZPNG is a Common Lisp library for creating PNG files. It
22 uses <a href='http://www.xach.com/lisp/salza2/'>Salza2</a> for
23 compression.
25 The current version is 1.1.3, released on July 9, 2008.
27 <p class='download'>Download shortcut:
29 <p><a href='http://www.xach.com/lisp/zpng.tgz'>http://www.xach.com/lisp/zpng.tgz</a>
31 </blockquote>
33 <h3>Contents</h3>
35 <ol>
36 <li> <a href='#sect-overview'>Overview and Limitations</a>
37 <li> <a href='#sect-examples'>Examples</a>
38 <li> <a href='#sect-dictionary'>Dictionary</a>
40 <ul>
42 <li>Common Functions
44 <ul>
45 <li> <a href='#samples-per-pixel'><tt>samples-per-pixel</tt></a>
46 <li> <a href='#width'><tt>width</tt></a>
47 <li> <a href='#height'><tt>height</tt></a>
48 <li> <a href='#rowstride'><tt>rowstride</tt></a>
49 <li> <a href='#color-type'><tt>color-type</tt></a>
50 </ul>
53 <li> In-memory PNGs
55 <ul>
56 <li> <a href='#png'><tt>png</tt></a>
57 <li> <a href='#image-data'><tt>image-data</tt></a>
58 <li> <a href='#data-array'><tt>data-array</tt></a>
59 <li> <a href='#copy-png'><tt>copy-png</tt></a>
60 <li> <a href='#png='><tt>png=</tt></a>
61 <li> <a href='#write-png'><tt>write-png</tt></a>
62 <li> <a href='#write-png-stream'><tt>write-png-stream</tt></a>
63 </ul>
65 <li> Streamed, row-at-a-time PNGs
67 <ul>
68 <li> <a href='#streamed-png'><tt>streamed-png</tt></a>
69 <li> <a href='#start-png'><tt>start-png</tt></a>
70 <li> <a href='#write-row'><tt>write-row</tt></a>
71 <li> <a href='#rows-written'><tt>rows-written</tt></a>
72 <li> <a href='#rows-left'><tt>rows-left</tt></a>
73 <li> <a href='#finish-png'><tt>finish-png</tt></a>
74 </ul>
76 <li> Errors
78 <ul>
79 <li> <a href='#zpng-error'><tt>zpng-error</tt></a>
80 <li> <a href='#invalid-size'><tt>invalid-size</tt></a>
81 <li> <a href='#invalid-size-width'><tt>invalid-size-width</tt></a>
82 <li> <a href='#invalid-size-height'><tt>invalid-size-height</tt></a>
83 <li> <a href='#invalid-row-length'><tt>invalid-row-length</tt></a>
84 <li> <a href='#insufficient-rows'><tt>insufficient-rows</tt></a>
85 <li> <a href='#too-many-rows'><tt>too-many-rows</tt></a>
86 </ul>
88 </ul>
90 <li> <a href='#sect-references'>References</a>
91 <li> <a href='#sect-feedback'>Feedback</a>
92 </ol>
94 <a name='sect-overview'><h3>Overview and Limitations</h3></a>
96 <p>ZPNG provides two interfaces creating PNG files. The first is through a
97 <a href='#png'><tt>PNG</tt></a> object, which holds all image sample
98 data and which may be written out to a file all at once. The second is
99 through a <a href='#streamed-png'><tt>STREAMED-PNG</tt></a> object,
100 which writes a single output row of the image at a time. By working
101 with only a single row at a time, images that are too big to fit in
102 memory may still be written out incrementally as a PNG file.
104 <p>The PNG file format has many options, and ZPNG supports only a
105 subset of them.
107 <ul>
108 <li> does not load PNG files
109 <li> supports only 8 bits per sample
110 <li> does not support filtering
111 <li> does not support indexed color
112 </ul>
115 <a name='sect-examples'><h3>Examples</h3></a>
118 <pre><div style='float: right' class='transparent'><img src='mandelbrot.png'
119 ></div>(defun draw-mandelbrot (file)
120 (let* ((png (make-instance '<a href='#png'>png</a>
121 :color-type :grayscale-alpha
122 :width 200
123 :height 200))
124 (image (<a href='#data-array'>data-array</a> png))
125 (max 255))
126 (dotimes (y 200 (<a href='#write-png'>write-png</a> png file))
127 (dotimes (x 200)
128 (let ((c (complex (- (/ x 100.0) 1.5) (- (/ y 100.0) 1.0)))
129 (z (complex 0.0 0.0))
130 (iteration 0))
131 (loop
132 (setf z (+ (* z z) c))
133 (incf iteration)
134 (cond ((< 4 (abs z))
135 (setf (aref image y x 1) iteration)
136 (return))
137 ((= iteration max)
138 (setf (aref image y x 1) 255)
139 (return)))))))))
140 </pre>
142 <a name='sect-dictionary'><h3>Dictionary</h3></a>
144 <p>The following symbols are exported from the ZPNG package.
148 <p><a name='samples-per-pixel'>[Function]</a><br>
149 <b>samples-per-pixel</b> <i>png</i> => <i>samples</i>
151 <blockquote>
152 Returns the number of octet samples that make up a single pixel.
154 <p><table cellpadding=0 cellspacing=5>
155 <tr>
156 <th>Image Color Type</th>
157 <th>Samples per Pixel</th>
158 </tr>
159 <tr>
160 <td>Grayscale</td><td align=center>1</td>
161 </tr>
162 <tr>
163 <td>Truecolor</td><td align=center>3</td>
164 </tr>
165 <tr>
166 <td>Grayscale with Alpha</td><td align=center>2</td>
167 </tr>
168 <tr>
169 <td>Truecolor with Alpha</td><td align=center>4</td>
170 </tr>
171 </table>
173 </blockquote>
176 <p><a name='width'><a name='height'>[Functions]</a></a><br>
177 <b>width</b> <i>png</i> => <i>width</i><br>
178 <b>height</b> <i>png</i> => <i>height</i>
180 <blockquote>
181 Returns the width or height of <i>png</i>.
182 </blockquote>
184 <p><a name='rowstride'>[Function]</a><br>
185 <b>rowstride</b> <i>png</i> => <i>rowstride</i>
187 <blockquote>
188 Returns the number of samples in a single row of <i>png</i>. It is
189 equivalent
190 to <tt class=code>(*&nbsp;(<a href='#width'>width</a>&nbsp;png)&nbsp;(<a href='#samples-per-pixel'>samples-per-pixel</a>&nbsp;png))</tt>.
191 </blockquote>
193 <p><a name='color-type'>[Function]</a><br>
194 <b>color-type</b> <i>png</i> => <i>color-type</i>
196 <blockquote>
197 Returns the color type of <i>png</i>, one of
198 of <tt>:grayscale</tt>, <tt>:truecolor</tt>,
199 <tt>:grayscale-alpha</tt>, or <tt>:truecolor-alpha</tt>.
200 </blockquote>
203 <p><a name='png'>[Class]</a><br>
204 <b>png</b>
206 <blockquote>
207 Instances of this class may be created directly. Supported initargs:
209 <ul>
211 <li> <tt>:width</tt> - required, the width of the image
213 <li> <tt>:height</tt> - required, the height of the image
215 <li> <tt>:color-type</tt> - optional, the color type of the image, one
216 of <tt>:grayscale</tt>, <tt>:truecolor</tt> (the
217 default), <tt>:grayscale-alpha</tt>, or <tt>:truecolor-alpha</tt>
219 <li> <tt>:image-data</tt> - optional, the sample data of the image. If
220 specified, this must be an octet vector with a length of
221 <i>width</i>&nbsp;&times;&nbsp;<i>height</i>&nbsp;&times;&nbsp;<i>samples-per-pixel</i>. If
222 not specified, an image data vector of the appropriate size will be
223 created automatically.
225 </ul>
227 </blockquote>
230 <p><a name='image-data'>[Function]</a><br>
231 <b>image-data</b> <i>png</i> => <i>octet-vector</i>
233 <blockquote>
234 Returns the image data of <i>png</i>. Samples are laid out from left
235 to right, top to bottom, so the first samples of data affect the
236 upper-left of the image and the final samples affect the lower-right.
238 <p><table cellpadding=0 cellspacing=5>
239 <tr>
240 <th>Image Color Type</th>
241 <th>Pixel Sample Layout</th>
242 </tr>
243 <tr>
244 <td>Grayscale</td><td>S|S|S...</td>
245 </tr>
246 <tr>
247 <td>Truecolor</td><td>RGB|RGB|RGB...</td>
248 </tr>
249 <tr>
250 <td>Grayscale with Alpha</td><td>SA|SA|SA...</td>
251 </tr>
252 <tr>
253 <td>Truecolor with Alpha</td><td>RGBA|RGBA|RGBA...</td>
254 </tr>
255 </table>
257 <p>Layout of the samples into pixels is done according to the image's
258 color type and is fully documented in
259 the <a href="http://www.w3.org/TR/PNG/">Portable Network Graphics
260 Specification.
261 </blockquote>
264 <p><a name='data-array'>[Function]</a><br>
265 <b>data-array</b> <i>png</i> => <i>data-array</i>
267 <blockquote>
268 Returns a multidimensional array representing the pixels
269 of <i>png</i>. The dimensions correspond to the height, width, and
270 pixel components, respectively. For example, to access the red
271 component at &lt;53,100&gt; of a truecolor PNG, you could use this:
273 <pre>
274 (aref (data-array png) 100 53 0)
275 </pre>
277 <p>Note the reversed order of the coordinate arguments; this is a
278 consequence of Common Lisp's row-major ordering of elements in a
279 multidimensional array and PNG's specified sample layout.
281 </blockquote>
284 <p><a name='copy-png'>[Function]</a><br>
285 <b>copy-png</b> <i>png</i> => <i>png-copy</i>
287 <blockquote>
288 Create a copy of <i>png</i>.
289 </blockquote>
292 <p><a name='png='>[Function]</a><br>
293 <b>png=</b> <i>png1</i> <i>png2</i> => <i>boolean</i>
295 <blockquote>
296 Returns true if png1 and png2 are equal. Equality is defined as having
297 the same dimensions, color type, and image data.
298 </blockquote>
301 <p><a name='write-png'>[Function]</a><br>
302 <b>write-png</b> <i>png</i> <i>file</i>
303 <tt>&amp;key</tt> (<i>if-exists</i> <tt>:supersede</tt>) => pathname
305 <blockquote>
306 Writes <i>png</i> to <i>file</i> and returns the truename
307 of <i>file</i>. <i>if-exists</i> is passed to the
308 underlying <tt>CL:OPEN</tt> call for opening the output file.
309 </blockquote>
312 <p><a name='write-png-stream'>[Function]</a><br>
313 <b>write-png-stream</b> <i>png</i> <i>stream</i> => |
315 <blockquote>
316 Writes <i>png</i> to <i>stream</i>, which should be an output stream
317 that can accept octets.
318 </blockquote>
321 <p><a name='streamed-png'>[Class]</a><br>
322 <b>streamed-png</b>
324 <blockquote>
325 Instances of this class may be created directly. Supports all the
326 initargs of the <a href='#png'><tt>PNG</tt></a> class
327 except <tt>:IMAGE-DATA</tt>.
329 <p>In contrast to <tt>PNG</TT> instances, <tt>STREAMED-PNG</tt>
330 instances do not keep all the image data in one large vector. Instead,
331 instances are used to write out the image data of a PNG file one row
332 at a time. The protocol for incrementally writing out via
333 a <tt>STREAMED-PNG</tt> involves these generic functions:
335 <ul>
336 <li> <a href='#row-data'><tt>ROW-DATA</tt></a>
337 <li> <a href='#start-png'><tt>START-PNG</tt></a>
338 <li> <a href='#write-row'><tt>WRITE-ROW</tt></a>
339 <li> <a href='#rows-written'><tt>ROWS-WRITTEN</tt></a>
340 <li> <a href='#rows-left'><tt>ROWS-LEFT</tt></a>
341 <li> <a href='#finish-png'><tt>FINISH-PNG</tt></a>
342 </ul>
344 </blockquote>
347 <p><a name='row-data'>[Function]</a><br>
348 <b>row-data</b> <i>streamed-png</i> => <i>octet-vector</i>
350 <blockquote>
351 Returns a vector suitable for passing
352 to <a href='#write-row'><tt>WRITE-ROW</tt></a>
353 for <i>streamed-png</i>; it has the appropriate number of entries for
354 the image width and color type of the png. The initial contents are
355 all zeroes. For a given streamed png, each call to <tt>row-data</tt>
356 will return the <i>same</i> vector, not a fresh one.
357 </blockquote>
360 <p><a name='start-png'>[Function]</a><br>
361 <b>start-png</b> <i>png</i> <i>stream</i> => <i>png</i>
363 <blockquote>
364 Writes PNG file header data to <i>stream</i>, which must be an output
365 stream that supports writing <tt>(unsigned-byte&nbsp;8)</tt> data. The
366 header data is taken from <i>png</i>, which must be
367 a <a href='#streamed-png'><tt>STREAMED-PNG</tt></a> instance.
368 </blockquote>
371 <p><a name='write-row'>[Function]</a><br>
372 <b>write-row</b> <i>row</i> <i>png</i>
373 <tt>&key</tt> (<i>start</i> 0) <i>end</i> => |
375 <blockquote>
376 Writes <i>row</i> to the output stream of <i>png</i>. <i>row</i> must
377 be an
378 <tt>(unsigned-byte&nbsp;8)</tt> vector with the appropriate number of
379 entries for <i>png</i>. <i>start</i> defaults to 0 and <i>end</i>
380 defaults to <i>start</i>
381 + <a href='#rowstride'><tt>ROWSTRIDE</tt></a>.
383 The difference between <i>end</i> and <i>start</i> should be equal to
384 <tt class=code>(<a href='#rowstride'>rowstride</a>&nbsp;png</i>)</tt>. <i>png</i>
385 must be a <a href='#streamed-png'><tt>STREAMED-PNG</tt></a> instance.
387 <p>If the row length, as defined by <i>start</i> and <i>end</i>, is
388 not the right size, an error of
389 type <a href='#invalid-row-length'><tt>INVALID-ROW-LENGTH</tt></a> is
390 signaled.
392 <p>If writing <i>row</i> would exceed the number of rows in the image
393 (as defined by <a href='#height'><tt>HEIGHT</tt></a>), an error of
394 type <a href='#too-many-rows'><tt>TOO-MANY-ROWS</tt></a> is signaled.
397 </blockquote>
400 <p><a name='rows-written'>[Function]</a><br>
401 <b>rows-written</b> <i>streamed-png</i> => <i>count</i>
403 <blockquote>
404 Returns the number of rows written to <i>streamed-png</i> so far.
405 </blockquote>
408 <p><a name='rows-left'>[Function]</a><br>
409 <b>rows-left</b> <i>streamed-png</i> => <i>count</i>
411 <blockquote>
412 Returns the number of rows left to write
413 to <i>streamed-png</i>. Equivalent to
414 <tt class=code>(- (<a href='#height'>height</a> png)
415 (<a href='#rows-written'>rows-written</a> png))</tt>.
417 </blockquote>
420 <p><a name='finish-png'>[Function]</a><br>
421 <b>finish-png</b> <i>streamed-png</i> => |
423 <blockquote>
424 Concludes writing PNG file data to the output stream
425 of <i>streamed-png</i>. The internal state of streamed-png is reset in
426 such a way that it can be re-used to write another PNG file, with the
427 same dimensions and color type parameters, using
428 another <a href='#start-png'><tt>START-PNG</tt></a>/<a href='#write-row'><tt>WRITE-ROW</tt></a>/<a href='#finish-png'><tt>FINISH-PNG</tt></a>
429 sequence.
431 <p>This function must be called only after
432 exactly <a href='#height'><tt>HEIGHT</tt></a> rows have been written
433 to <i>streamed-png</i>
434 via <a href='#write-row'><tt>WRITE-ROW</tt></a>. If too few rows have
435 been written to <i>streamed-png</i>, an error of
436 type <a href='#insufficient-rows'><tt>INSUFFICIENT-ROWS</tt></a> is
437 signaled.
438 </blockquote>
441 <p><a name='zpng-error'>[Condition]</a><br>
442 <b>zpng-error</b>
444 <blockquote>
445 All errors signaled by ZPNG are a subtype of <tt>ZPNG-ERROR</tt>,
446 which is a subtype of <tt>CL:ERROR</tt>.
447 </blockquote>
450 <p><a name='invalid-size'>[Condition]</a><br>
451 <b>invalid-size</b>
453 <blockquote>
454 A condition of this type is signaled when a PNG with invalid size is
455 created. Valid PNGs have positive width and height.
456 </blockquote>
459 <p><a name='invalid-size-width'>[Accessors]</a><br>
460 <b>invalid-size-width</b> <i>condition</i> => <i>width</i><br>
461 <b>invalid-size-height</b> <i>condition</i> => <i>height</i>
463 <blockquote>
464 These accessors provide the invalid size used for a PNG.
465 </blockquote>
468 <p><a name='invalid-row-length'>[Condition]</a><br>
469 <b>invalid-row-length</b>
471 <blockquote>
472 A condition of this type is signaled when a row with an incorrect size
473 is passed to <a href='#write-row'><tt>WRITE-ROW</tt></a>.
474 </blockquote>
477 <p><a name='insufficient-rows'>[Condition]</a><br>
478 <b>insufficient-rows</b>
480 <blockquote>
481 A condition of this type is signaled
482 from <a href='#finish-png'><tt>FINISH-PNG</tt></a> when it is called
483 before enough rows have been written
484 via <a href='#write-row'><tt>WRITE-ROW</tt></a>.
485 </blockquote>
487 <p><a name='too-many-rows'>[Condition]</a><br>
488 <b>too-many-rows</b>
490 <blockquote>
491 A condition of this type is signaled
492 from <a href='#write-row'><tt>WRITE-ROW</tt></a> if it is called more
493 times than is necessary for the given PNG.
494 </blockquote>
497 <a name='sect-references'><h3>References</h3></a>
499 <ul>
501 <li> W3C, <a href="http://www.w3.org/TR/PNG/">Portable Network
502 Graphics Specification, Second Edition</a>
504 <li>
505 Wikipedia, <a href='http://en.wikipedia.org/wiki/Mandelbrot_set'>Mandelbrot
506 set</a>
508 </ul>
511 <a name='sect-feedback'><h3>Feedback</h3></a>
513 <p>Please direct any questions, comments, bug reports, or other
514 feedback to <a href='mailto:xach@xach.com'>Zach Beane</a>.