Use RLE bitmap compression
This commit is contained in:
parent
5cebe379c8
commit
606c5f43af
44
autistdraw.c
44
autistdraw.c
|
@ -272,8 +272,26 @@ send_get_bitmap_response (client_t *client, app_context_t *app)
|
||||||
msg_writer_u64 (&writer, app->bitmap_w);
|
msg_writer_u64 (&writer, app->bitmap_w);
|
||||||
msg_writer_u64 (&writer, app->bitmap_h);
|
msg_writer_u64 (&writer, app->bitmap_h);
|
||||||
|
|
||||||
msg_writer_blob (&writer, app->bitmap,
|
// Simple RLE compression
|
||||||
app->bitmap_w * app->bitmap_h * sizeof *app->bitmap);
|
size_t size = app->bitmap_w * app->bitmap_h;
|
||||||
|
uint8_t last_value = 0, count = 0;
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
uint8_t value = app->bitmap[i];
|
||||||
|
if ((count && value != last_value) || count == 0xFF)
|
||||||
|
{
|
||||||
|
msg_writer_u8 (&writer, count);
|
||||||
|
msg_writer_u8 (&writer, last_value);
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
last_value = value;
|
||||||
|
}
|
||||||
|
if (count)
|
||||||
|
{
|
||||||
|
msg_writer_u8 (&writer, count);
|
||||||
|
msg_writer_u8 (&writer, last_value);
|
||||||
|
}
|
||||||
|
|
||||||
flush_writer_to_client (&writer, client);
|
flush_writer_to_client (&writer, client);
|
||||||
}
|
}
|
||||||
|
@ -970,17 +988,27 @@ on_server_get_bitmap (app_context_t *app, struct msg_unpacker *unpacker)
|
||||||
|| !msg_unpacker_u64 (unpacker, &h))
|
|| !msg_unpacker_u64 (unpacker, &h))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: employ at least some RLE encoding
|
size_t size = w * h;
|
||||||
size_t size = w * h * sizeof *app->bitmap;
|
|
||||||
if ((h && w > SIZE_MAX / h) || w > SIZE_MAX || h > SIZE_MAX)
|
if ((h && w > SIZE_MAX / h) || w > SIZE_MAX || h > SIZE_MAX)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const void *data;
|
uint8_t *bitmap = xcalloc (size, sizeof *app->bitmap);
|
||||||
if (!msg_unpacker_blob (unpacker, &data, size))
|
|
||||||
return;
|
// RLE decompression
|
||||||
|
size_t i = 0;
|
||||||
|
uint8_t len, value;
|
||||||
|
while (msg_unpacker_u8 (unpacker, &len)
|
||||||
|
&& msg_unpacker_u8 (unpacker, &value))
|
||||||
|
{
|
||||||
|
// Don't allow overflow
|
||||||
|
if (i + len > size || i + len < i)
|
||||||
|
break;
|
||||||
|
for (size_t x = 0; x < len; x++)
|
||||||
|
bitmap[i++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
free (app->bitmap);
|
free (app->bitmap);
|
||||||
app->bitmap = memcpy (xcalloc (1, size), data, size);
|
app->bitmap = bitmap;
|
||||||
app->bitmap_x = x;
|
app->bitmap_x = x;
|
||||||
app->bitmap_y = y;
|
app->bitmap_y = y;
|
||||||
app->bitmap_w = w;
|
app->bitmap_w = w;
|
||||||
|
|
16
utils.c
16
utils.c
|
@ -382,16 +382,6 @@ msg_unpacker_get_available (struct msg_unpacker *self)
|
||||||
return self->len - self->offset;
|
return self->len - self->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
msg_unpacker_blob (struct msg_unpacker *self, const void **data, size_t len)
|
|
||||||
{
|
|
||||||
if (self->len - self->offset < len)
|
|
||||||
return false;
|
|
||||||
*data = self->data + self->offset;
|
|
||||||
self->offset += len;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define UNPACKER_INT_BEGIN \
|
#define UNPACKER_INT_BEGIN \
|
||||||
if (self->len - self->offset < sizeof *value) \
|
if (self->len - self->offset < sizeof *value) \
|
||||||
return false; \
|
return false; \
|
||||||
|
@ -445,12 +435,6 @@ msg_writer_init (struct msg_writer *self)
|
||||||
str_append_data (&self->buf, "\x00\x00\x00\x00" "\x00\x00\x00\x00", 8);
|
str_append_data (&self->buf, "\x00\x00\x00\x00" "\x00\x00\x00\x00", 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
msg_writer_blob (struct msg_writer *self, const void *data, size_t len)
|
|
||||||
{
|
|
||||||
str_append_data (&self->buf, data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
msg_writer_u8 (struct msg_writer *self, uint8_t x)
|
msg_writer_u8 (struct msg_writer *self, uint8_t x)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue