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