From 4f98d10caab142931c21c9608fd1151600e527cc Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 29 Sep 2017 06:52:53 +0530 Subject: [PATCH] Remove the requirement to specify sizes for PNG files --- graphics-protocol.asciidoc | 12 +++++------- kitty/graphics.c | 24 +++++++++++++++++------- kitty_tests/graphics.py | 4 ++-- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/graphics-protocol.asciidoc b/graphics-protocol.asciidoc index 38afbf922..f36000cd5 100644 --- a/graphics-protocol.asciidoc +++ b/graphics-protocol.asciidoc @@ -79,17 +79,15 @@ bytes. === PNG data -In this format any PNG image can be transmitted directly. The size of the PNG data -**must** be specified in the control data. For example: +In this format any PNG image can be transmitted directly. For example: ``` -_Gf=100,S=4897;\ +_Gf=100;\ ``` -Here the size (in bytes) of the PNG file is specified using the `S` key and the -PNG format is specified using the `f` key. The pixel data must therefore be -`S=4897` bytes. +The PNG format is specified using the `f=100` key. The width and height of +the image will be read from the PNG data itself. === Compression @@ -127,7 +125,7 @@ and can take the values: First let us consider the local client techniques (files and shared memory). Some examples: ``` -_Gf=100,S=3567,t=f;\ +_Gf=100,t=f;\ ``` Here we tell the terminal emulator to read PNG data from the specified file of diff --git a/kitty/graphics.c b/kitty/graphics.c index 96c8b3f4c..a88198941 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -281,6 +281,7 @@ add_trim_predicate(Image *img) { static bool handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) { #define ABRT(code, ...) { set_add_response(#code, __VA_ARGS__); self->loading_image = 0; return false; } +#define MAX_DATA_SZ (4 * 100000000) bool existing, init_img = true; Image *img; unsigned char tt = g->transmission_type ? g->transmission_type : 'd'; @@ -302,10 +303,9 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_ img->width = g->data_width; img->height = g->data_height; switch(fmt) { case PNG: - if (!g->data_sz) ABRT(EINVAL, "Must provide a data size with the PNG format"); - if (g->data_sz > 4 * 100000000) ABRT(EINVAL, "PNG data size too large"); + if (g->data_sz > MAX_DATA_SZ) ABRT(EINVAL, "PNG data size too large"); img->load_data.is_4byte_aligned = true; - img->load_data.data_sz = g->data_sz; + img->load_data.data_sz = g->data_sz ? g->data_sz : 1024 * 100; break; case RGB: case RGBA: @@ -319,9 +319,12 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_ if (tt == 'd') { if (g->more) self->loading_image = img->internal_id; img->load_data.buf_capacity = img->load_data.data_sz + (g->compressed ? 1024 : 10); // compression header - img->load_data.buf = malloc(img->load_data.buf_capacity + 4); - if (img->load_data.buf == NULL) fatal("Out of memory while allocating image load data buffer"); + img->load_data.buf = malloc(img->load_data.buf_capacity); img->load_data.buf_used = 0; + if (img->load_data.buf == NULL) { + ABRT(ENOMEM, "Out of memory"); + img->load_data.buf_capacity = 0; img->load_data.buf_used = 0; + } } } else { img = img_by_internal_id(self, self->loading_image); @@ -334,8 +337,14 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_ static char fname[2056] = {0}; switch(tt) { case 'd': // direct - if (g->payload_sz >= img->load_data.buf_capacity - img->load_data.buf_used) { - ABRT(EFBIG, "Too much data transmitted"); + if (img->load_data.buf_capacity - img->load_data.buf_used < g->payload_sz) { + if (img->load_data.buf_used + g->payload_sz > MAX_DATA_SZ || fmt != PNG) ABRT(EFBIG, "Too much data"); + img->load_data.buf_capacity = MIN(2 * img->load_data.buf_capacity, MAX_DATA_SZ); + img->load_data.buf = realloc(img->load_data.buf, img->load_data.buf_capacity); + if (img->load_data.buf == NULL) { + ABRT(ENOMEM, "Out of memory"); + img->load_data.buf_capacity = 0; img->load_data.buf_used = 0; + } } memcpy(img->load_data.buf + img->load_data.buf_used, payload, g->payload_sz); img->load_data.buf_used += g->payload_sz; @@ -409,6 +418,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_ } } return img->data_loaded; +#undef MAX_DATA_SZ #undef ABRT } diff --git a/kitty_tests/graphics.py b/kitty_tests/graphics.py index db30fd9a8..ef8fd92d1 100644 --- a/kitty_tests/graphics.py +++ b/kitty_tests/graphics.py @@ -133,10 +133,10 @@ class TestGraphics(BaseTest): for mode in 'RGBA RGB P'.split(): data = png(mode) - sl(data, f=100, S=len(data), expecting_data=rgba_data) + sl(data, f=100, expecting_data=rgba_data) img = img.convert('L') rgba_data = img.convert('RGBA').tobytes() data = png('L') - sl(data, f=100, S=len(data), expecting_data=rgba_data) + sl(data, f=100, expecting_data=rgba_data) self.ae(l(b'a' * 20, f=100, S=20).partition(':')[0], 'EBADPNG')