+#include <string.h>
+#include <stdint.h>
+#include <arpa/inet.h>
+#include <zlib.h>
+
+#include "png.h"
+
+/* Table of CRCs of all 8-bit messages. */
+static unsigned long crc_table[256];
+
+/* Flag: has the table been computed? Initially false. */
+static int crc_table_computed = 0;
+
+/* Make the table for a fast CRC. */
+static void make_crc_table(void)
+{
+ unsigned long c;
+ int n, k;
+
+ for (n = 0; n < 256; n++) {
+ c = (unsigned long) n;
+ for (k = 0; k < 8; k++) {
+ if (c & 1)
+ c = 0xedb88320L ^ (c >> 1);
+ else
+ c = c >> 1;
+ }
+ crc_table[n] = c;
+ }
+ crc_table_computed = 1;
+}
+
+/* Update a running CRC with the bytes buf[0..len-1]--the CRC
+ should be initialized to all 1's, and the transmitted value
+ is the 1's complement of the final running CRC (see the
+ crc() routine below). */
+
+static unsigned long update_crc(unsigned long crc, unsigned char *buf,
+ int len)
+{
+ unsigned long c = crc;
+ int n;
+
+ if (!crc_table_computed)
+ make_crc_table();
+ for (n = 0; n < len; n++) {
+ c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
+ }
+ return c;
+}
+
+/* Return the CRC of the bytes buf[0..len-1]. */
+static unsigned long crc(unsigned char *buf, int len)
+{
+ return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
+}
+
+unsigned char *lcd2png(unsigned char *lcd, int *len)
+{
+ unsigned char screen_conv[320*234*3];
+ unsigned char lut[256][3];
+ unsigned char *image;
+ unsigned char *outpos;
+ static const unsigned char png[] = {137, 80, 78, 71, 13, 10, 26, 10};
+ static unsigned char ihdr[] = {'I', 'H', 'D', 'R',
+ 0x00, 0x00, 0x01, 0x40, /* 320 - Width */
+ 0x00, 0x00, 0x00, 0xea, /* 234 - Height */
+ 0x08, /* Bit depth */
+ 0x02, /* RGB Truecolor, Colour type */
+ 0x00, /* Deflate, Compression method */
+ 0x00, /* None, Filter method */
+ 0x00 /* No interlace, Interlace method */
+ };
+ static unsigned char idat[] = {'I', 'D', 'A', 'T'};
+ static unsigned char iend[] = {'I', 'E', 'N', 'D'};
+ uint32_t l;
+ int i;
+ int toalloc = 0;
+
+ for(i = 0; i < 256; i++) {
+ lut[i][0] = ((i >> 6) * 0x55);
+ lut[i][1] = ((((i >> 3) & 7) * 0x49) >> 1);
+ lut[i][2] = (((i & 7) * 0x49) >> 1);
+ }
+
+ for(i = 0; i < sizeof(screen_conv); i += 3) {
+ screen_conv[i] = lut[lcd[i/3]][0];
+ screen_conv[i+1] = lut[lcd[i/3]][1];
+ screen_conv[i+2] = lut[lcd[i/3]][2];
+ }
+
+ image = malloc(320*234*2); /* TODO: FIXME! */
+ outpos = image;
+ memcpy(outpos, png, sizeof(png));
+ outpos += sizeof(png);
+
+ l = htonl(sizeof(ihdr) - 4); /* "IHDR" is not counted */
+ memcpy(outpos, &l, sizeof(l));
+ outpos += sizeof(l);
+ memcpy(outpos, ihdr, sizeof(ihdr));
+ outpos += sizeof(ihdr);
+ l = crc(ihdr, sizeof(ihdr));
+ memcpy(outpos, &l, sizeof(l));
+ outpos += sizeof(l);
+
+ l = htonl(sizeof(iend) - 4); /* "IEND" is not counted */
+ memcpy(outpos, &l, sizeof(l));
+ outpos += sizeof(l);
+ memcpy(outpos, iend, sizeof(iend));
+ outpos += sizeof(iend);
+ l = crc(iend, sizeof(iend));
+ memcpy(outpos, &l, sizeof(l));
+ outpos += sizeof(l);
+
+ *len = (int)(outpos - image);
+ return image;
+}