To print a row on the head, I have to send a stream of 832 bits via HDAT line. I am considering only a graphic data, i.e. printer won't generate any fonts for itself (at least for now). So for purpose of printing any color image in any format, some preprocessing on the host must be undertaken. Steps to do:
- 1. Resize the image to 832 pixels wide.
- 2. Reduce the color palette to grayscale.
- 3. Reduce image depth further to 4 shades i.e. 2 bits per pixel.
- 4. Apply dithering.
- 5. Output the raw byte stream.
- 6. For debugging purposes convert the resulting byte stream to C header, so the test image could be embedded in the source code and later on the flash memory.
Surprisingly the task was not as easy as I thought. It turns out, that the topic is quite complicated. For example look at those pages listed below, how many detailed information they contain:
The last one may give you idea what tool I am using. It is a standard command line Swiss army knife for graphics manipulation available (often by default) on any *nix system. BTW my system is a Ubuntu 14.04, 64bit running on i5 and i7. After lots of tweaking (3 evenings or more) I came up with satisfactory solution:
1. Generate a "color palette". In my case only 4 shades : black, white and two grays:
convert -size 1x4 gradient:black ~/gradient_levels.png
2a. Perform steps 1-5 in one go, and output the result in form of viewable PNG image (for easy inspection):
convert IMG_7245.JPG -resize 832 -colorspace sRGB -set colorspace RGB -colorspace Gray -dither FloydSteinberg -remap ~/gradient_levels.png -depth 2 ~/franek.png
2b. Or alternatively output in raw format (notice the output image extension):
convert IMG_7245.JPG -resize 832 -colorspace sRGB -set colorspace RGB -colorspace Gray -dither FloydSteinberg -remap ~/gradient_levels.png -depth 2 ~/franek.gray
3. Make a *.h file (huge):
xxd -i ~/franek.gray > /home/iwasz/workspace/test07/src/franek.h
Resulting *.h file can be quite huge. Look at this for example. Every byte contains 4 pixels, each 2 bits wide. Black ones has value of 0x0, dark gray is 0x1, light gray is 0x2 and white is 0x3. So draft algorithm may look like that :
for each line
for k = 0; k < number of colors - 1 (i.e. 3); ++k
for each 2 bit pixel (color)
if color <= k
set corresponding bit in monochrome array to 1;
transfer monochrome array;
issue the DST signal;
In other words I spit the DST signal duration (let it be D ms) to 3 durations. First I turn on all black pixels, turn on the heat and wait D/3 ms. Then I turn on dark gray ones (black are still on) and after turning on the heat I wait another D/3 ms. Finally I add light gray pixels to the ones already switched on and repeat the heating for D/3 ms. This coarse description is implemented here.