Created 06/12/2019 at 06:00PM
After numerous failed attempts to create a compressed bitmap that the device would accept, I finally managed to get the SpaceMouse Enterprise to display a custom bitmap.
I started off by attempting to recompress the bitmap data that I had successfully decompressed. I knew that the compression type must be some form that gzip used, since that was the program that I was using to do the decompression. Unfortunately, every attempt to recompress the data ended up with a completely different compressed stream.
I had a further look at gzip and found that it used the deflate compression method, which uses the zlib library on Linux. Zlib comes with some example code, which I managed to compile into a simple compressor/decompressor. Still, I had no luck with that either.
Reading through the zlib documentation, I discovered that there are extended commands, deflateInit2 and inflateInit2 that take extra arguments. One of these is windowBits, which switches compression and decompression to using raw deflate, which has no header. Since the compressed bitmap data does not seem to have a header, this seemed promising.
Another parameter is the zlib strategy. There is an option of Z_FIXED, which disabled dynamic huffman codes. The zlib documentation states that this allows for simpler decoding, and since I assume that there is probably a relatively simple microcontroller on the SpaceMouse doing the decompression, it makes sense that the algorithm used is simple too.
I altered the zlib example code to use the new commands and attempted to decompress and then recompress the captured stream. They matched. Well, the first bytes at least, but it showed that I was on the right track.
I took some relatively simple bitmaps drawn in Gimp, saved them as 16-bit RGB, then ran them through a Python script to convert them to BGR. I then compressed them with zlib using the new settings and attached this compressed data to the original 512 header bytes that I had captured with Wireshark. Success. The bitmap displayed.
There was still a problem however. The device was becoming confused when I uploaded an image. Either the image did not get drawn completely, and parts of the previous image were left showing, or else it would draw okay, but then lock up or corrupt the device.
It seemed as though the device was expecting a certain length of compressed data, and was either stopping short because it thought it had read everything, or else it was waiting for more data which was corrupting the device. This led me to suspect that the header contained some value telling the device how big the compressed payload was.
Fortunately, it was not difficult to find. Bytes 0x02 and 0x03 are a little-endian 16-bit value that matches the size of the compressed bitmap. Provided that these bytes are modified in the header, the bitmaps seem to work okay. Phew.
I tried with a few more example bitmaps just for good measure, and managed to get some nice images showing on the screen. Not every image can be displayed, however, since the 16-bit value means that the compressed data cannot be larger than 65535 bytes, and some bitmaps will compress much larger than this, at least with the zlib settings required for the SpaceMouse.