#+TITLE: C ECL SDL2 PNG #+AUTHOR: screwtape I want to twiddle 8 bit png channels. I want to perform arbitrary (nonlinear) functions on pixels, but am not interested in reading or writing unknown png chunks or interlacing etc. * Install dependencies #+begin_src sh pkg_add sdl2 sdl2_image ecl feh #+end_src reimagine this for your package manager; it's probably similar. (apt install) * Get the lisp and test empty png #+begin_src sh mkdir png-test && cd png-test printf "/users/screwtape/common-lisp/png-pixels.lisp\n" | nc sdf.org 70 > png-pixels.lisp printf "/users/screwtape/common-lisp/png-pixel-make.lisp\n" | nc sdf.org 70 > png-pixel-make.lisp printf "/users/screwtape/common-lisp/png-pixel-test.lisp\n" | nc sdf.org 70 > png-pixel-test.lisp printf "/users/screwtape/common-lisp/empty.png\n" | nc sdf.org 70 > empty.png #+end_src * Start ECL #+begin_src sh ecl #+end_src * Do eet #+begin_src lisp (load #p"png-pixel-make.lisp") (load #p"png-pixels.fas") (load #p"png-pixel-test.lisp") (ext:system "feh empty.png & feh noisy.png") (si:quit) #+end_src * Whys and wherefores Because I want access to uint8 pixel colors, but not arbitrary png functionality, I will use SDL2_image, which wraps libpng [and its zlib dep] to load and save them as SDL2_Surface structs. Then, I will read and write the pixels of the surface, and save it. The PNG is assumed sRGB color. ** Some things I decided not to do SDL2 normally expects you to be blitting (efficiently copying rectangles of pixels between) two surfaces, with a blend rule. This is useful for mixing images by their alphas or moving and overlaying them in an animation, but implies the alpha channel is already set, and does not really imply pixel level control. Further, it's slow if you are using accelerated graphics (because accelerated graphics involves silly memcopies for common usage). Another thing I am not doing is using libpng directly, since I am only interested in loading, reading and writing pixels, and saving. These behaviours are exposed by SDL2_image and the many various png re/configs are mostly out of sight. A third thing that I could do instead is write a little scriptfu for GIMP's tinyscheme image editing engine. GIMP is a titanically large dependency, and I have the feeling that its functionality has gotten monotonically worse since its 1997 inception ("what if we used embedded tinyscheme to compose scriptable reuseable high level image operations"). I'm not confident that all GIMP's developers know that that's the point. Fourthly, several obvious optimizations are missing here: Between each pixel access, control returns to ECL. This is compounded by not taking the time to compile png-pixel-test.lisp to a fas file.