1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
/**
* @file lv_rle.c
*/
/*********************
* INCLUDES
*********************/
#include "../../stdlib/lv_string.h"
#include "lv_rle.h"
#if LV_USE_RLE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
uint32_t lv_rle_decompress(const uint8_t * input,
uint32_t input_buff_len, uint8_t * output,
uint32_t output_buff_len, uint8_t blk_size)
{
uint32_t ctrl_byte;
uint32_t rd_len = 0;
uint32_t wr_len = 0;
while(rd_len < input_buff_len) {
ctrl_byte = input[0];
rd_len++;
input++;
if(rd_len > input_buff_len)
return 0;
if(ctrl_byte & 0x80) {
/* copy directly from input to output */
uint32_t bytes = blk_size * (ctrl_byte & 0x7f);
rd_len += bytes;
if(rd_len > input_buff_len)
return 0;
wr_len += bytes;
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;
input += bytes;
}
else {
rd_len += blk_size;
if(rd_len > input_buff_len)
return 0;
wr_len += blk_size * ctrl_byte;
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. */
lv_memset(output, input[0], ctrl_byte);
output += ctrl_byte;
}
else {
for(uint32_t i = 0; i < ctrl_byte; i++) {
lv_memcpy(output, input, blk_size);
output += blk_size;
}
}
input += blk_size;
}
}
return wr_len;
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_RLE*/
|