## Example of Writing Indexed PNG Using PNGJ + Clojure

From: andrew cooke <andrew@...>

Date: Sat, 28 Apr 2012 15:46:42 -0300

Throwing this out there because pngj is a nice little library, but the
examples are fairly opaque and it assumes you know PNG internals.

I'll describe the code (below) and then give a summary.  You may not need the
code to understand how to use the library, so feel free to skip to the
numbered list...

OK, first the code: The function "print-png-indexed" takes an output stream
and returns two functions.

The second function is used to convert each pixel in the image (originally
HSL) into an index.  This palette of colours that this index references is the
"colours" atom in "print-png-indexed".

Once the first function takes a set of nested lists of index values (orginally
these would have been pixels, but they will have been converted by the second
function - I hope you are following!) and writes them to the output stream,
using the pngj library (after first writing the palette).

You don't have to understand all the above to use this, I hope.  What is
important is the process:

1 - change pixels to indices, building up a colour-index map as you go.

2 - start up the pngj library, with ImageInfo and PngWriter

3 - use the colour-index map to populate a PngChunkPLTE instance.

4 - write the PngChunkPLTE palette via the image metadata.

5 - write the indices via the ImageLine.

Andrew

(defn print-png-indexed [os]
(let [colours (atom {})]
[(fn [size rows]
; 8 bits, no alpha, no grayscale, indexed
(let [info (ImageInfo. size size 8 Boolean/FALSE Boolean/FALSE Boolean/TRUE)
writer (PngWriter. os info)
line (ImageLine. info)
palette (PngChunkPLTE. info)]
(.setNentries palette (count @colours))
(doseq [rgb (keys @colours)]
(let [[r g b] rgb]
(.setEntry palette (@colours rgb) r g b)))
(@colours rgb)))]))