summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2010-04-07 23:12:36 +0200
committerAlexander Larsson <alexl@redhat.com>2010-04-07 23:12:36 +0200
commit746b8a34f630bf876a71737d48951c7dc28de515 (patch)
treeedf04f1566adaedc43a4ed03a4eb966f7dbff604
parent982dab2099434ca9cb00e478cde5569da352719e (diff)
Add png rgba support
-rw-r--r--daemon.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/daemon.c b/daemon.c
index 1b03212..24bdca4 100644
--- a/daemon.c
+++ b/daemon.c
@@ -368,6 +368,114 @@ to_png_rgb (int w, int h, int stride, guint32 *data)
return url;
}
+char *
+to_png_rgba (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: */ 6,
+ 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 * 4;
+ 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 * 4) * 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,a
+ 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 */
+ *p++ = (pixel >> 24) & 0xff; /* alpha */
+ }
+ 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)
@@ -393,7 +501,30 @@ send_image_rgb (GOutputStream *out, int x, int y,
g_free (url);
}
+static void
+send_image_rgba (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_rgba (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)
@@ -423,6 +554,7 @@ send_draw_ops (GOutputStream *out)
char *header;
int i;
guint32 pixel[4] = {0xffffff, 0xff0000, 0xff00ff, 0x00ff00};
+ guint32 pixela[4] = {0xffffffff, 0x80ffffff, 0x40ffffff, 0x20ffffff};
header =
"HTTP/1.1 200 OK\r\n"
@@ -444,6 +576,8 @@ send_draw_ops (GOutputStream *out)
send_select_surface(cout, 1);
send_rgb (cout, 0x00ff00);
send_rect (cout, 0, 0, 25, 25);
+ send_image_rgba (cout, 0, 0,
+ 2, 2, 2, pixela);
send_select_surface(cout, 0);
while (1)