summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2010-04-05 23:37:48 +0200
committerAlexander Larsson <alexl@redhat.com>2010-04-05 23:37:48 +0200
commit91a2ddf0d319e8a770e1b92ba1412206409bec04 (patch)
tree902322d9827f4683a04e9b7bea1323b639992ac4
parent795534ade844b01805326367cc7ee4e3a7e3bfbf (diff)
Send png images
-rw-r--r--client.html20
-rw-r--r--daemon.c371
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++;
diff --git a/daemon.c b/daemon.c
index ad4687f..126c270 100644
--- a/daemon.c
+++ b/daemon.c
@@ -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);