diff options
author | Alexander Larsson <alexl@redhat.com> | 2010-04-05 23:37:48 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-04-05 23:37:48 +0200 |
commit | 91a2ddf0d319e8a770e1b92ba1412206409bec04 (patch) | |
tree | 902322d9827f4683a04e9b7bea1323b639992ac4 | |
parent | 795534ade844b01805326367cc7ee4e3a7e3bfbf (diff) |
Send png images
-rw-r--r-- | client.html | 20 | ||||
-rw-r--r-- | daemon.c | 371 |
2 files changed, 217 insertions, 174 deletions
diff --git a/client.html b/client.html index e31422e..2637ad7 100644 --- a/client.html +++ b/client.html @@ -66,6 +66,22 @@ function handleLoad(event) i = 0; while (i < cmd.length) { switch (cmd[i]) { + case 'i': + i++; + x = base64_16(cmd, i); + i = i + 3; + y = base64_16(cmd, i); + i = i + 3; + size = base64_32(cmd, i); + i = i + 6; + url = cmd.slice(i, i + size); + i = i + size; + var img = new Image(); + img.src = url + context.drawImage(img, x, y); + + break; + case 'b': i++; sx = base64_16(cmd, i); @@ -80,7 +96,9 @@ function handleLoad(event) i = i + 3; dy = base64_16(cmd, i); i = i + 3; - context.drawImage(canvas, sx, sy, w, h, dx, dy, w, h) + context.drawImage(canvas, sx, sy, w, h, dx, dy, w, h); + + break; case 'r': i++; @@ -100,6 +100,200 @@ send_copyrect (GOutputStream *out, int sx, int sy, int w, int h, int dx, int dy NULL, NULL, NULL); } +/* 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; +} + +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; +} + +static unsigned long +crc(unsigned char *buf, int len) +{ + return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL; +} + +#define BASE 65521 /* largest prime smaller than 65536 */ +static unsigned long +update_adler32(unsigned long adler, unsigned char *buf, int len) +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int n; + + for (n = 0; n < len; n++) { + s1 = (s1 + buf[n]) % BASE; + s2 = (s2 + s1) % BASE; + } + return (s2 << 16) + s1; +} + +char * +to_png_rgb (int w, int h, int stride, guint32 *data) +{ + guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10}; + guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R', + /* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0, + /* bpp: */ 8, /* color type: */ 2, + 0, 0, 0}; + guchar idat_start[8] = { /* len: */0, 0, 0, 0, 'I', 'D', 'A', 'T' }; + guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82}; + gsize data_size, row_size; + char row_header[6]; + guint8 *png, *p, *p_row, *p_idat; + guint32 *row; + unsigned long adler; + guint32 pixel; + gsize png_size; + int x, y; + char *url, *url_base64; + gint state = 0, outlen; + gint save = 0; + + *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w); + *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h); + *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4)); + + row_size = 1 + w * 3; + row_header[0] = 0; + row_header[1] = row_size & 0xff; + row_header[2] = (row_size >> 8) & 0xff; + row_header[3] = ~row_header[1]; + row_header[4] = ~row_header[2]; + row_header[5] = 0; + + data_size = 2 + (6 + w * 3) * h + 4; + + *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size); + + png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend); + png = g_malloc (png_size); + + p = png; + memcpy (p, header, sizeof(header)); + p += sizeof(header); + memcpy (p, ihdr, sizeof(ihdr)); + p += sizeof(ihdr); + memcpy (p, idat_start, sizeof(idat_start)); + p += sizeof(idat_start); + + /* IDAT data: + + zlib header: 0x78, 0x01 , + h * scanline: row_header[] + width * r,g,b + checksum: adler32 + */ + + p_idat = p - 4; + + /* zlib header */ + *p++ = 0x78; + *p++ = 0x01; + + adler = 1; + + /* scanline data */ + for (y = 0; y < h; y++) { + if (y == h - 1) + row_header[0] = 1; /* final block */ + memcpy (p, row_header, sizeof(row_header)); + p += sizeof(row_header); + p_row = p - 1; + row = data; + data += stride; + for (x = 0; x < w; x++) { + pixel = *row++; + *p++ = (pixel >> 16) & 0xff; /* red */ + *p++ = (pixel >> 8) & 0xff; /* green */ + *p++ = (pixel >> 0) & 0xff; /* blue */ + } + adler = update_adler32(adler, p_row, p - p_row); + } + + /* adler32 */ + *(guint32 *)p = GUINT32_TO_BE(adler); + p += 4; + *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat)); + p += 4; + + memcpy (p, iend, sizeof(iend)); + p += sizeof(iend); + + g_assert(p - png == png_size); + + url = g_malloc (strlen("data:image/png;base64,") + + ((png_size / 3 + 1) * 4 + 4) + 1); + strcpy (url, "data:image/png;base64,"); + + url_base64 = url + strlen("data:image/png;base64,"); + outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save); + outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save); + url_base64[outlen] = 0; + + g_free (png); + + return url; +} + +static void +send_image_rgb (GOutputStream *out, int x, int y, + int w, int h, int stride, guint32 *data) +{ + char buf[13]; + gsize len; + char *url; + + buf[0] = 'i'; + base64_uint16(x, &buf[1]); + base64_uint16(y, &buf[4]); + + url = to_png_rgb (w, h, stride, data); + len = strlen (url); + base64_uint32(len, &buf[7]); + + g_output_stream_write_all (out, buf, 13, + NULL, NULL, NULL); + + g_output_stream_write_all (out, url, len, + NULL, NULL, NULL); + + g_free (url); +} + + static void send_boundary (GOutputStream *out) @@ -128,6 +322,7 @@ send_draw_ops (GOutputStream *out) GOutputStream *cout; char *header; int i; + guint32 pixel[4] = {0xffffff, 0xff0000, 0xff00ff, 0x00ff00}; header = "HTTP/1.1 200 OK\r\n" @@ -154,6 +349,9 @@ send_draw_ops (GOutputStream *out) send_copyrect (cout, 15, 15, 800, 40, 20, 15); + send_image_rgb (cout, 30, 30, + 2, 2, 2, pixel); + i ++; flush (cout); @@ -293,185 +491,12 @@ handler (GThreadedSocketService *service, return res; } -/* 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; -} - -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; -} - -static unsigned long -crc(unsigned char *buf, int len) -{ - return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL; -} - -#define BASE 65521 /* largest prime smaller than 65536 */ -static unsigned long -update_adler32(unsigned long adler, unsigned char *buf, int len) -{ - unsigned long s1 = adler & 0xffff; - unsigned long s2 = (adler >> 16) & 0xffff; - int n; - - for (n = 0; n < len; n++) { - s1 = (s1 + buf[n]) % BASE; - s2 = (s2 + s1) % BASE; - } - return (s2 << 16) + s1; -} - -char * -to_png_rgb (int w, int h, int stride, guint32 *data) -{ - guchar header[] = {137, 80, 78, 71, 13, 10, 26, 10}; - guchar ihdr[13+12] = {0, 0, 0, 13, 'I', 'H', 'D', 'R', - /* w: */ 0, 0, 0, 0, /* h: */ 0,0,0,0, - /* bpp: */ 8, /* color type: */ 2, - 0, 0, 0}; - guchar idat_start[8] = { /* len: */0, 0, 0, 0, 'I', 'D', 'A', 'T' }; - guchar iend[12] = {0, 0, 0, 0, 'I', 'E', 'N', 'D', 0xae, 0x42, 0x60, 0x82}; - gsize data_size, row_size; - char row_header[6]; - guint8 *png, *p, *p_row, *p_idat; - guint32 *row; - unsigned long adler; - guint32 pixel; - gsize png_size; - int x, y; - char *url, *url_base64; - gint state = 0, outlen; - gint save = 0; - - *(guint32 *)&ihdr[8] = GUINT32_TO_BE(w); - *(guint32 *)&ihdr[12] = GUINT32_TO_BE(h); - *(guint32 *)&ihdr[21] = GUINT32_TO_BE(crc(&ihdr[4], 13 + 4)); - - row_size = 1 + w * 3; - row_header[0] = 0; - row_header[1] = row_size & 0xff; - row_header[2] = (row_size >> 8) & 0xff; - row_header[3] = ~row_header[1]; - row_header[4] = ~row_header[2]; - row_header[5] = 0; - - data_size = 2 + (6 + w * 3) * h + 4; - - *(guint32 *)&idat_start[0] = GUINT32_TO_BE(data_size); - - png_size = sizeof(header) + sizeof(ihdr) + 12 + data_size + sizeof(iend); - png = g_malloc (png_size); - - p = png; - memcpy (p, header, sizeof(header)); - p += sizeof(header); - memcpy (p, ihdr, sizeof(ihdr)); - p += sizeof(ihdr); - memcpy (p, idat_start, sizeof(idat_start)); - p += sizeof(idat_start); - - /* IDAT data: - - zlib header: 0x78, 0x01 , - h * scanline: row_header[] + width * r,g,b - checksum: adler32 - */ - - p_idat = p - 4; - - /* zlib header */ - *p++ = 0x78; - *p++ = 0x01; - - adler = 1; - - /* scanline data */ - for (y = 0; y < h; y++) { - if (y == h - 1) - row_header[0] = 1; /* final block */ - memcpy (p, row_header, sizeof(row_header)); - p += sizeof(row_header); - p_row = p - 1; - row = data; - data += stride; - for (x = 0; x < w; x++) { - pixel = *row++; - *p++ = (pixel >> 16) & 0xff; /* red */ - *p++ = (pixel >> 8) & 0xff; /* green */ - *p++ = (pixel >> 0) & 0xff; /* blue */ - } - adler = update_adler32(adler, p_row, p - p_row); - } - - /* adler32 */ - *(guint32 *)p = GUINT32_TO_BE(adler); - p += 4; - *(guint32 *)p = GUINT32_TO_BE(crc(p_idat, p - p_idat)); - p += 4; - - memcpy (p, iend, sizeof(iend)); - p += sizeof(iend); - - g_assert(p - png == png_size); - - url = g_malloc (strlen("data:image/png;base64,") + - ((png_size / 3 + 1) * 4 + 4) + 1); - strcpy (url, "data:image/png;base64,"); - - url_base64 = url + strlen("data:image/png;base64,"); - outlen = g_base64_encode_step (png, png_size, FALSE, url_base64, &state, &save); - outlen += g_base64_encode_close (FALSE, url_base64 + outlen, &state, &save); - url_base64[outlen] = 0; - - g_free (png); - - return url; -} - int main (int argc, char *argv[]) { GSocketService *service; GOptionContext *context; GError *error = NULL; - guint32 pixel[4] = {0xffffff, 0xff0000, 0xff00ff, 0x00ff00}; - char *data; - - data = to_png_rgb (2, 2, 2, pixel); - g_print ("%s\n", data); g_type_init (); g_thread_init (NULL); |