diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index 913aab8063..37841a6921 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -1069,13 +1069,8 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image uint32_t out_len = compressed->decompressed_size; uint32_t input_len = compressed->compressed_size; LV_UNUSED(input_len); + LV_UNUSED(out_len); - /** - * @todo - * FIXME, RLE compressed image needs extra memory because decompression operates on - * pixel unit not byte unit. Should optimize RLE decompress to not write to extra memory. - */ - dsc->header.h += 1; lv_draw_buf_t * decompressed = lv_draw_buf_create(dsc->header.w, dsc->header.h, dsc->header.cf, dsc->header.stride); if(decompressed == NULL) { @@ -1083,13 +1078,6 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image return LV_RESULT_INVALID; } - dsc->header.h -= 1; /*Change it back*/ - if(decompressed->data_size < out_len) { - LV_LOG_WARN("decompressed size mismatch: %" LV_PRIu32 ", %" LV_PRIu32, decompressed->data_size, out_len); - lv_draw_buf_destroy(decompressed); - return LV_RESULT_INVALID; - } - img_data = decompressed->data; if(compressed->method == LV_IMAGE_COMPRESS_RLE) { diff --git a/src/libs/rle/lv_rle.c b/src/libs/rle/lv_rle.c index f19660b8bb..e715b7cc17 100644 --- a/src/libs/rle/lv_rle.c +++ b/src/libs/rle/lv_rle.c @@ -58,8 +58,12 @@ uint32_t lv_rle_decompress(const uint8_t * input, return 0; wr_len += bytes; - if(wr_len > output_buff_len) - return 0; + if(wr_len > output_buff_len) { + if(wr_len > output_buff_len + blk_size) + return 0; /* Error */ + lv_memcpy(output, input, output_buff_len - (wr_len - bytes)); + return output_buff_len; + } lv_memcpy(output, input, bytes); output += bytes; @@ -71,8 +75,17 @@ uint32_t lv_rle_decompress(const uint8_t * input, return 0; wr_len += blk_size * ctrl_byte; - if(wr_len > output_buff_len) - return 0; + if(wr_len > output_buff_len) { + if(wr_len > output_buff_len + blk_size) + return 0; /* Error happened */ + + /* Skip the last pixel, which could overflow output buffer.*/ + for(uint32_t i = 0; i < ctrl_byte - 1; i++) { + lv_memcpy(output, input, blk_size); + output += blk_size; + } + return output_buff_len; + } if(blk_size == 1) { /* optimize the most common case. */