Merge to XFA: Kill FXSYS_mem{cpy,cmp,set.move}{32,8}.
[pdfium.git] / core / src / fxcodec / lbmp / fx_bmp.cpp
1 // Copyright 2014 PDFium Authors. All rights reserved.\r
2 // Use of this source code is governed by a BSD-style license that can be\r
3 // found in the LICENSE file.\r
4 \r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com\r
6 \r
7 #include "fx_bmp.h"\r
8 FX_DWORD _GetDWord_LSBFirst(uint8_t* p)\r
9 {\r
10     return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);\r
11 }\r
12 FX_WORD _GetWord_LSBFirst(uint8_t* p)\r
13 {\r
14     return p[0] | (p[1] << 8);\r
15 }\r
16 void _SetDWord_LSBFirst(uint8_t* p, FX_DWORD v)\r
17 {\r
18     p[0] = (uint8_t)v;\r
19     p[1] = (uint8_t)(v >> 8);\r
20     p[2] = (uint8_t)(v >> 16);\r
21     p[3] = (uint8_t)(v >> 24);\r
22 }\r
23 void _SetWord_LSBFirst(uint8_t* p, FX_WORD v)\r
24 {\r
25     p[0] = (uint8_t)v;\r
26     p[1] = (uint8_t)(v >> 8);\r
27 }\r
28 void _bmp_error(bmp_decompress_struct_p bmp_ptr, const FX_CHAR* err_msg)\r
29 {\r
30     if(bmp_ptr != NULL && bmp_ptr->_bmp_error_fn != NULL) {\r
31         bmp_ptr->_bmp_error_fn(bmp_ptr, err_msg);\r
32     }\r
33 }\r
34 bmp_decompress_struct_p _bmp_create_decompress()\r
35 {\r
36     bmp_decompress_struct_p bmp_ptr = FX_Alloc(bmp_decompress_struct, 1);\r
37     if(bmp_ptr == NULL) {\r
38         return NULL;\r
39     }\r
40     FXSYS_memset(bmp_ptr, 0, sizeof(bmp_decompress_struct));\r
41     bmp_ptr->decode_status = BMP_D_STATUS_HEADER;\r
42     bmp_ptr->bmp_header_ptr = FX_Alloc(BmpFileHeader, 1);\r
43     return bmp_ptr;\r
44 }\r
45 void _bmp_destroy_decompress(bmp_decompress_struct_pp bmp_ptr_ptr)\r
46 {\r
47     if(bmp_ptr_ptr == NULL || *bmp_ptr_ptr == NULL) {\r
48         return;\r
49     }\r
50     bmp_decompress_struct_p bmp_ptr = *bmp_ptr_ptr;\r
51     *bmp_ptr_ptr = NULL;\r
52     if(bmp_ptr->out_row_buffer != NULL) {\r
53         FX_Free(bmp_ptr->out_row_buffer);\r
54     }\r
55     if(bmp_ptr->pal_ptr != NULL) {\r
56         FX_Free(bmp_ptr->pal_ptr);\r
57     }\r
58     if(bmp_ptr->bmp_header_ptr != NULL) {\r
59         FX_Free(bmp_ptr->bmp_header_ptr);\r
60     }\r
61     FX_Free(bmp_ptr);\r
62 }\r
63 int32_t _bmp_read_header(bmp_decompress_struct_p bmp_ptr)\r
64 {\r
65     if(bmp_ptr == NULL) {\r
66         return 0;\r
67     }\r
68     FX_DWORD skip_size_org = bmp_ptr->skip_size;\r
69     if(bmp_ptr->decode_status == BMP_D_STATUS_HEADER) {\r
70         ASSERT(sizeof(BmpFileHeader) == 14);\r
71         BmpFileHeader* bmp_header_ptr = NULL;\r
72         if(_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_header_ptr, 14) == NULL) {\r
73             return 2;\r
74         }\r
75         bmp_ptr->bmp_header_ptr->bfType = _GetWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfType);\r
76         bmp_ptr->bmp_header_ptr->bfOffBits = _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfOffBits);\r
77         bmp_ptr->data_size = _GetDWord_LSBFirst((uint8_t*)&bmp_header_ptr->bfSize);\r
78         if(bmp_ptr->bmp_header_ptr->bfType != BMP_SIGNATURE) {\r
79             _bmp_error(bmp_ptr, "Not A Bmp Image");\r
80             return 0;\r
81         }\r
82         if(bmp_ptr->avail_in < sizeof(FX_DWORD)) {\r
83             bmp_ptr->skip_size = skip_size_org;\r
84             return 2;\r
85         }\r
86         bmp_ptr->img_ifh_size = _GetDWord_LSBFirst(bmp_ptr->next_in + bmp_ptr->skip_size);\r
87         bmp_ptr->pal_type = 0;\r
88         ASSERT(sizeof(BmpCoreHeader) == 12);\r
89         ASSERT(sizeof(BmpInfoHeader) == 40);\r
90         switch(bmp_ptr->img_ifh_size) {\r
91             case FX_MIN(12, sizeof(BmpCoreHeader)): {\r
92                     bmp_ptr->pal_type = 1;\r
93                     BmpCoreHeaderPtr bmp_core_header_ptr = NULL;\r
94                     if(_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_core_header_ptr, bmp_ptr->img_ifh_size) == NULL) {\r
95                         bmp_ptr->skip_size = skip_size_org;\r
96                         return 2;\r
97                     }\r
98                     bmp_ptr->width = (FX_DWORD)_GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcWidth);\r
99                     bmp_ptr->height = (FX_DWORD)_GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcHeight);\r
100                     bmp_ptr->bitCounts = _GetWord_LSBFirst((uint8_t*)&bmp_core_header_ptr->bcBitCount);\r
101                     bmp_ptr->compress_flag = BMP_RGB;\r
102                     bmp_ptr->imgTB_flag = FALSE;\r
103                 }\r
104                 break;\r
105             case FX_MIN(40, sizeof(BmpInfoHeader)): {\r
106                     BmpInfoHeaderPtr bmp_info_header_ptr = NULL;\r
107                     if(_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, bmp_ptr->img_ifh_size) == NULL) {\r
108                         bmp_ptr->skip_size = skip_size_org;\r
109                         return 2;\r
110                     }\r
111                     bmp_ptr->width = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);\r
112                     bmp_ptr->height = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);\r
113                     bmp_ptr->bitCounts = _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);\r
114                     bmp_ptr->compress_flag = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression);\r
115                     bmp_ptr->color_used = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed);\r
116                     bmp_ptr->dpi_x = (int32_t)_GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);\r
117                     bmp_ptr->dpi_y = (int32_t)_GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);\r
118                     if(bmp_ptr->height < 0) {\r
119                         bmp_ptr->height = -bmp_ptr->height;\r
120                         bmp_ptr->imgTB_flag = TRUE;\r
121                     }\r
122                 }\r
123                 break;\r
124             default: {\r
125                     if(bmp_ptr->img_ifh_size > FX_MIN(40, sizeof(BmpInfoHeader))) {\r
126                         BmpInfoHeaderPtr bmp_info_header_ptr = NULL;\r
127                         if(_bmp_read_data(bmp_ptr, (uint8_t**)&bmp_info_header_ptr, bmp_ptr->img_ifh_size) == NULL) {\r
128                             bmp_ptr->skip_size = skip_size_org;\r
129                             return 2;\r
130                         }\r
131                         FX_WORD biPlanes;\r
132                         bmp_ptr->width = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biWidth);\r
133                         bmp_ptr->height = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biHeight);\r
134                         bmp_ptr->bitCounts = _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biBitCount);\r
135                         bmp_ptr->compress_flag = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biCompression);\r
136                         bmp_ptr->color_used = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biClrUsed);\r
137                         biPlanes = _GetWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biPlanes);\r
138                         bmp_ptr->dpi_x = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biXPelsPerMeter);\r
139                         bmp_ptr->dpi_y = _GetDWord_LSBFirst((uint8_t*)&bmp_info_header_ptr->biYPelsPerMeter);\r
140                         if(bmp_ptr->height < 0) {\r
141                             bmp_ptr->height = -bmp_ptr->height;\r
142                             bmp_ptr->imgTB_flag = TRUE;\r
143                         }\r
144                         if(bmp_ptr->compress_flag == BMP_RGB &&\r
145                                 biPlanes == 1 &&\r
146                                 bmp_ptr->color_used == 0) {\r
147                             break;\r
148                         }\r
149                     }\r
150                     _bmp_error(bmp_ptr, "Unsupported Bmp File");\r
151                     return 0;\r
152                 }\r
153         }\r
154         ASSERT(bmp_ptr->width > 0);\r
155         ASSERT(bmp_ptr->compress_flag <= BMP_BITFIELDS);\r
156         switch(bmp_ptr->bitCounts) {\r
157             case 1:\r
158             case 4:\r
159             case 8:\r
160             case 16:\r
161             case 24: {\r
162                     if(bmp_ptr->color_used > ((FX_DWORD)1) << bmp_ptr->bitCounts) {\r
163                         _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
164                         return 0;\r
165                     }\r
166                 }\r
167             case 32: {\r
168                     if(bmp_ptr->width <= 0 || bmp_ptr->compress_flag > BMP_BITFIELDS) {\r
169                         _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
170                         return 0;\r
171                     }\r
172                 }\r
173                 break;\r
174             default:\r
175                 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
176                 return 0;\r
177         }\r
178         bmp_ptr->src_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, bmp_ptr->bitCounts);\r
179         switch(bmp_ptr->bitCounts) {\r
180             case 1:\r
181             case 4:\r
182             case 8:\r
183                 bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 8);\r
184                 bmp_ptr->components = 1;\r
185                 break;\r
186             case 16:\r
187             case 24:\r
188                 bmp_ptr->out_row_bytes = BMP_WIDTHBYTES(bmp_ptr->width, 24);\r
189                 bmp_ptr->components = 3;\r
190                 break;\r
191             case 32:\r
192                 bmp_ptr->out_row_bytes = bmp_ptr->src_row_bytes;\r
193                 bmp_ptr->components = 4;\r
194                 break;\r
195         }\r
196         if(bmp_ptr->out_row_buffer != NULL) {\r
197             FX_Free(bmp_ptr->out_row_buffer);\r
198             bmp_ptr->out_row_buffer = NULL;\r
199         }\r
200         bmp_ptr->out_row_buffer = FX_Alloc(uint8_t, bmp_ptr->out_row_bytes);\r
201         BMP_PTR_NOT_NULL(bmp_ptr->out_row_buffer, bmp_ptr);\r
202         FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);\r
203         _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_PAL);\r
204     }\r
205     if (bmp_ptr->decode_status == BMP_D_STATUS_PAL) {\r
206         skip_size_org = bmp_ptr->skip_size;\r
207 #ifdef BMP_SUPPORT_BITFIELD\r
208         if(bmp_ptr->compress_flag == BMP_BITFIELDS) {\r
209             if(bmp_ptr->bitCounts != 16 && bmp_ptr->bitCounts != 32) {\r
210                 _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
211                 return 0;\r
212             }\r
213             FX_DWORD* mask;\r
214             if(_bmp_read_data(bmp_ptr, (uint8_t**)&mask, 3 * sizeof(FX_DWORD)) == NULL) {\r
215                 bmp_ptr->skip_size = skip_size_org;\r
216                 return 2;\r
217             }\r
218             bmp_ptr->mask_red   = _GetDWord_LSBFirst((uint8_t*)&mask[0]);\r
219             bmp_ptr->mask_green = _GetDWord_LSBFirst((uint8_t*)&mask[1]);\r
220             bmp_ptr->mask_blue  = _GetDWord_LSBFirst((uint8_t*)&mask[2]);\r
221             if(bmp_ptr->mask_red & bmp_ptr->mask_green ||\r
222                     bmp_ptr->mask_red & bmp_ptr->mask_blue ||\r
223                     bmp_ptr->mask_green & bmp_ptr->mask_blue) {\r
224                 _bmp_error(bmp_ptr, "The Bitfield Bmp File Is Corrupt");\r
225                 return 0;\r
226             }\r
227             if(bmp_ptr->bmp_header_ptr->bfOffBits < 26 + bmp_ptr->img_ifh_size) {\r
228                 bmp_ptr->bmp_header_ptr->bfOffBits = 26 + bmp_ptr->img_ifh_size;\r
229             }\r
230             _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE);\r
231             return 1;\r
232         } else if(bmp_ptr->bitCounts == 16) {\r
233             bmp_ptr->mask_red   = 0x7C00;\r
234             bmp_ptr->mask_green = 0x03E0;\r
235             bmp_ptr->mask_blue  = 0x001F;\r
236         }\r
237 #else\r
238         if(bmp_ptr->compress_flag == BMP_BITFIELDS || bmp_ptr->bitCounts == 16) {\r
239             _bmp_error(bmp_ptr, "Unsupported Bitfield Bmp File");\r
240             return 0;\r
241         }\r
242 #endif\r
243         bmp_ptr->pal_num = 0;\r
244         if(bmp_ptr->bitCounts < 16) {\r
245             bmp_ptr->pal_num = 1 << bmp_ptr->bitCounts;\r
246             if(bmp_ptr->color_used != 0) {\r
247                 bmp_ptr->pal_num = bmp_ptr->color_used;\r
248             }\r
249             uint8_t* src_pal_ptr = NULL;\r
250             FX_DWORD src_pal_size = bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4);\r
251             if(_bmp_read_data(bmp_ptr, (uint8_t**)&src_pal_ptr, src_pal_size) == NULL) {\r
252                 bmp_ptr->skip_size = skip_size_org;\r
253                 return 2;\r
254             }\r
255             if(bmp_ptr->pal_ptr != NULL) {\r
256                 FX_Free(bmp_ptr->pal_ptr);\r
257                 bmp_ptr->pal_ptr = NULL;\r
258             }\r
259             bmp_ptr->pal_ptr = FX_Alloc(FX_DWORD, bmp_ptr->pal_num);\r
260             BMP_PTR_NOT_NULL(bmp_ptr->pal_ptr, bmp_ptr);\r
261             int32_t src_pal_index = 0;\r
262             if(bmp_ptr->pal_type == BMP_PAL_OLD) {\r
263                 while(src_pal_index < bmp_ptr->pal_num) {\r
264                     bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE(0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);\r
265                     src_pal_ptr += 3;\r
266                 }\r
267             } else {\r
268                 while(src_pal_index < bmp_ptr->pal_num) {\r
269                     bmp_ptr->pal_ptr[src_pal_index++] = BMP_PAL_ENCODE(src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);\r
270                     src_pal_ptr += 4;\r
271                 }\r
272             }\r
273         }\r
274         if(bmp_ptr->bmp_header_ptr->bfOffBits < 14 + bmp_ptr->img_ifh_size + bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4)) {\r
275             bmp_ptr->bmp_header_ptr->bfOffBits = 14 + bmp_ptr->img_ifh_size + bmp_ptr->pal_num * (bmp_ptr->pal_type ? 3 : 4);\r
276         }\r
277         _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA_PRE);\r
278     }\r
279     return 1;\r
280 }\r
281 int32_t _bmp_decode_image(bmp_decompress_struct_p bmp_ptr)\r
282 {\r
283     if(bmp_ptr->decode_status == BMP_D_STATUS_DATA_PRE) {\r
284         bmp_ptr->avail_in = 0;\r
285         if(!bmp_ptr->_bmp_get_data_position_fn(bmp_ptr, bmp_ptr->bmp_header_ptr->bfOffBits)) {\r
286             bmp_ptr->decode_status = BMP_D_STATUS_TAIL;\r
287             _bmp_error(bmp_ptr, "The Bmp File Is Corrupt, Unexpected Stream Offset");\r
288             return 0;\r
289         }\r
290         bmp_ptr->row_num = 0;\r
291         _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);\r
292     }\r
293     if(bmp_ptr->decode_status == BMP_D_STATUS_DATA) {\r
294         switch(bmp_ptr->compress_flag) {\r
295             case BMP_RGB:\r
296             case BMP_BITFIELDS:\r
297                 return _bmp_decode_rgb(bmp_ptr);\r
298             case BMP_RLE8:\r
299                 return _bmp_decode_rle8(bmp_ptr);\r
300             case BMP_RLE4:\r
301                 return _bmp_decode_rle4(bmp_ptr);\r
302         }\r
303     }\r
304     _bmp_error(bmp_ptr, "Any Uncontrol Error");\r
305     return 0;\r
306 }\r
307 int32_t _bmp_decode_rgb(bmp_decompress_struct_p bmp_ptr)\r
308 {\r
309     uint8_t* row_buf = bmp_ptr->out_row_buffer;\r
310     uint8_t* des_buf = NULL;\r
311     while (bmp_ptr->row_num < bmp_ptr->height) {\r
312         if(_bmp_read_data(bmp_ptr, &des_buf, bmp_ptr->src_row_bytes) == NULL) {\r
313             return 2;\r
314         }\r
315         _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);\r
316         switch(bmp_ptr->bitCounts) {\r
317             case 1: {\r
318                     for (int32_t col = 0; col < bmp_ptr->width; col++) {\r
319                         *row_buf++ = des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;\r
320                     }\r
321                 }\r
322                 break;\r
323             case 4: {\r
324                     for (int32_t col = 0; col < bmp_ptr->width; col++) {\r
325                         *row_buf++ = (col & 0x01) ?\r
326                                      (des_buf[col >> 1] & 0x0F) :\r
327                                      ((des_buf[col >> 1] & 0xF0) >> 4);\r
328                     }\r
329                 }\r
330                 break;\r
331 #ifdef BMP_SUPPORT_BITFIELD\r
332             case 16: {\r
333                     FX_WORD* buf = (FX_WORD*)des_buf;\r
334                     uint8_t blue_bits = 0;\r
335                     uint8_t green_bits = 0;\r
336                     uint8_t red_bits = 0;\r
337                     for(int32_t i = 0; i < 16; i++) {\r
338                         if((bmp_ptr->mask_blue >> i) & 0x01) {\r
339                             blue_bits++;\r
340                         }\r
341                         if((bmp_ptr->mask_green >> i) & 0x01) {\r
342                             green_bits++;\r
343                         }\r
344                         if((bmp_ptr->mask_red >> i) & 0x01) {\r
345                             red_bits++;\r
346                         }\r
347                     }\r
348                     green_bits += blue_bits;\r
349                     red_bits += green_bits;\r
350                     blue_bits = 8 - blue_bits;\r
351                     green_bits -= 8;\r
352                     red_bits -= 8;\r
353                     for (int32_t col = 0; col < bmp_ptr->width; col++) {\r
354                         *buf = _GetWord_LSBFirst((uint8_t*)buf);\r
355                         *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_blue) << blue_bits);\r
356                         *row_buf++ = (uint8_t)((*buf & bmp_ptr->mask_green) >> green_bits);\r
357                         *row_buf++ = (uint8_t)((*buf++ & bmp_ptr->mask_red) >> red_bits);\r
358                     }\r
359                 }\r
360                 break;\r
361 #endif\r
362             case 8:\r
363             case 24:\r
364             case 32:\r
365                 FXSYS_memcpy(bmp_ptr->out_row_buffer, des_buf, bmp_ptr->src_row_bytes);\r
366                 break;\r
367         }\r
368         row_buf = bmp_ptr->out_row_buffer;\r
369         bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
370                                  bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
371                                  bmp_ptr->out_row_buffer);\r
372     }\r
373     _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);\r
374     return 1;\r
375 }\r
376 int32_t _bmp_decode_rle8(bmp_decompress_struct_p bmp_ptr)\r
377 {\r
378     uint8_t* first_byte_ptr = NULL;\r
379     uint8_t* second_byte_ptr = NULL;\r
380     bmp_ptr->col_num = 0;\r
381     while(TRUE) {\r
382         FX_DWORD skip_size_org = bmp_ptr->skip_size;\r
383         if(_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {\r
384             return 2;\r
385         }\r
386         switch(*first_byte_ptr) {\r
387             case RLE_MARKER: {\r
388                     if(_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {\r
389                         bmp_ptr->skip_size = skip_size_org;\r
390                         return 2;\r
391                     }\r
392                     switch(*first_byte_ptr) {\r
393                         case RLE_EOL: {\r
394                                 if(bmp_ptr->row_num >= bmp_ptr->height) {\r
395                                     _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);\r
396                                     _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
397                                     return 0;\r
398                                 }\r
399                                 bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
400                                                          bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
401                                                          bmp_ptr->out_row_buffer);\r
402                                 bmp_ptr->col_num = 0;\r
403                                 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);\r
404                                 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);\r
405                                 continue;\r
406                             }\r
407                         case RLE_EOI: {\r
408                                 if(bmp_ptr->row_num < bmp_ptr->height) {\r
409                                     bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
410                                                              bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
411                                                              bmp_ptr->out_row_buffer);\r
412                                 }\r
413                                 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);\r
414                                 return 1;\r
415                             }\r
416                         case RLE_DELTA: {\r
417                                 uint8_t* delta_ptr;\r
418                                 if(_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) {\r
419                                     bmp_ptr->skip_size = skip_size_org;\r
420                                     return 2;\r
421                                 }\r
422                                 bmp_ptr->col_num += (int32_t)delta_ptr[0];\r
423                                 int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1];\r
424                                 if(bmp_ptr->col_num >= bmp_ptr->out_row_bytes || bmp_row_num_next >= bmp_ptr->height) {\r
425                                     _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported");\r
426                                     return 0;\r
427                                 }\r
428                                 while(bmp_ptr->row_num < bmp_row_num_next) {\r
429                                     FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);\r
430                                     bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
431                                                              bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
432                                                              bmp_ptr->out_row_buffer);\r
433                                 }\r
434                             }\r
435                             break;\r
436                         default: {\r
437                                 if((int32_t)(*first_byte_ptr) > bmp_ptr->src_row_bytes - bmp_ptr->col_num) {\r
438                                     _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
439                                     return 0;\r
440                                 }\r
441                                 if(_bmp_read_data(bmp_ptr, &second_byte_ptr,\r
442                                                   *first_byte_ptr & 1 ? *first_byte_ptr + 1 : *first_byte_ptr) == NULL) {\r
443                                     bmp_ptr->skip_size = skip_size_org;\r
444                                     return 2;\r
445                                 }\r
446                                 FXSYS_memcpy(bmp_ptr->out_row_buffer + bmp_ptr->col_num, second_byte_ptr, *first_byte_ptr);\r
447                                 bmp_ptr->col_num += (int32_t)(*first_byte_ptr);\r
448                             }\r
449                     }\r
450                 }\r
451                 break;\r
452             default: {\r
453                     if(_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) {\r
454                         bmp_ptr->skip_size = skip_size_org;\r
455                         return 2;\r
456                     }\r
457                     if((int32_t)(*first_byte_ptr) > bmp_ptr->src_row_bytes - bmp_ptr->col_num) {\r
458                         _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
459                         return 0;\r
460                     }\r
461                     FXSYS_memset(bmp_ptr->out_row_buffer + bmp_ptr->col_num, *second_byte_ptr, *first_byte_ptr);\r
462                     bmp_ptr->col_num += (int32_t)(*first_byte_ptr);\r
463                 }\r
464         }\r
465     }\r
466     _bmp_error(bmp_ptr, "Any Uncontrol Error");\r
467     return 0;\r
468 }\r
469 int32_t _bmp_decode_rle4(bmp_decompress_struct_p bmp_ptr)\r
470 {\r
471     uint8_t* first_byte_ptr = NULL;\r
472     uint8_t* second_byte_ptr = NULL;\r
473     bmp_ptr->col_num = 0;\r
474     while (TRUE) {\r
475         FX_DWORD skip_size_org = bmp_ptr->skip_size;\r
476         if(_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {\r
477             return 2;\r
478         }\r
479         switch(*first_byte_ptr) {\r
480             case RLE_MARKER: {\r
481                     if(_bmp_read_data(bmp_ptr, &first_byte_ptr, 1) == NULL) {\r
482                         bmp_ptr->skip_size = skip_size_org;\r
483                         return 2;\r
484                     }\r
485                     switch(*first_byte_ptr) {\r
486                         case RLE_EOL: {\r
487                                 if(bmp_ptr->row_num >= bmp_ptr->height) {\r
488                                     _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);\r
489                                     _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
490                                     return 0;\r
491                                 }\r
492                                 bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
493                                                          bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
494                                                          bmp_ptr->out_row_buffer);\r
495                                 bmp_ptr->col_num = 0;\r
496                                 FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);\r
497                                 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_DATA);\r
498                                 continue;\r
499                             }\r
500                         case RLE_EOI: {\r
501                                 if(bmp_ptr->row_num < bmp_ptr->height) {\r
502                                     bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
503                                                              bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
504                                                              bmp_ptr->out_row_buffer);\r
505                                 }\r
506                                 _bmp_save_decoding_status(bmp_ptr, BMP_D_STATUS_TAIL);\r
507                                 return 1;\r
508                             }\r
509                         case RLE_DELTA: {\r
510                                 uint8_t* delta_ptr;\r
511                                 if(_bmp_read_data(bmp_ptr, &delta_ptr, 2) == NULL) {\r
512                                     bmp_ptr->skip_size = skip_size_org;\r
513                                     return 2;\r
514                                 }\r
515                                 bmp_ptr->col_num += (int32_t)delta_ptr[0];\r
516                                 int32_t bmp_row_num_next = bmp_ptr->row_num + (int32_t)delta_ptr[1];\r
517                                 if(bmp_ptr->col_num >= bmp_ptr->out_row_bytes || bmp_row_num_next >= bmp_ptr->height) {\r
518                                     _bmp_error(bmp_ptr, "The Bmp File Is Corrupt Or Not Supported");\r
519                                     return 0;\r
520                                 }\r
521                                 while(bmp_ptr->row_num < bmp_row_num_next) {\r
522                                     FXSYS_memset(bmp_ptr->out_row_buffer, 0, bmp_ptr->out_row_bytes);\r
523                                     bmp_ptr->_bmp_get_row_fn(bmp_ptr,\r
524                                                              bmp_ptr->imgTB_flag ? bmp_ptr->row_num++ : (bmp_ptr->height - 1 - bmp_ptr->row_num++),\r
525                                                              bmp_ptr->out_row_buffer);\r
526                                 }\r
527                             }\r
528                             break;\r
529                         default: {\r
530                                 uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1);\r
531                                 if((int32_t)*first_byte_ptr >= bmp_ptr->out_row_bytes - bmp_ptr->col_num) {\r
532                                     if(size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {\r
533                                         _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
534                                         return 0;\r
535                                     }\r
536                                     *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;\r
537                                 }\r
538                                 if(_bmp_read_data(bmp_ptr, &second_byte_ptr, size & 1 ? size + 1 : size) == NULL) {\r
539                                     bmp_ptr->skip_size = skip_size_org;\r
540                                     return 2;\r
541                                 }\r
542                                 for (uint8_t i = 0; i < *first_byte_ptr; i++) {\r
543                                     if(i & 0x01) {\r
544                                         *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = (*second_byte_ptr++ & 0x0F);\r
545                                     } else {\r
546                                         *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = ((*second_byte_ptr & 0xF0) >> 4);\r
547                                     }\r
548                                 }\r
549                             }\r
550                     }\r
551                 }\r
552                 break;\r
553             default: {\r
554                     if(_bmp_read_data(bmp_ptr, &second_byte_ptr, 1) == NULL) {\r
555                         bmp_ptr->skip_size = skip_size_org;\r
556                         return 2;\r
557                     }\r
558                     if((int32_t)*first_byte_ptr > bmp_ptr->out_row_bytes - bmp_ptr->col_num) {\r
559                         uint8_t size = (uint8_t)(((FX_WORD)(*first_byte_ptr) + 1) >> 1);\r
560                         if(size + (bmp_ptr->col_num >> 1) > bmp_ptr->src_row_bytes) {\r
561                             _bmp_error(bmp_ptr, "The Bmp File Is Corrupt");\r
562                             return 0;\r
563                         }\r
564                         *first_byte_ptr = bmp_ptr->out_row_bytes - bmp_ptr->col_num - 1;\r
565                     }\r
566                     for (uint8_t i = 0; i < *first_byte_ptr; i++) {\r
567                         if(i & 0x01) {\r
568                             *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = (*second_byte_ptr & 0x0F);\r
569                         } else {\r
570                             *(bmp_ptr->out_row_buffer + bmp_ptr->col_num++) = ((*second_byte_ptr & 0xF0) >> 4);\r
571                         }\r
572                     }\r
573                 }\r
574         }\r
575     }\r
576     _bmp_error(bmp_ptr, "Any Uncontrol Error");\r
577     return 0;\r
578 }\r
579 uint8_t* _bmp_read_data(bmp_decompress_struct_p bmp_ptr, uint8_t** des_buf_pp, FX_DWORD data_size)\r
580 {\r
581     if(bmp_ptr == NULL ||\r
582             bmp_ptr->avail_in < bmp_ptr->skip_size + data_size) {\r
583         return NULL;\r
584     }\r
585     *des_buf_pp = bmp_ptr->next_in + bmp_ptr->skip_size;\r
586     bmp_ptr->skip_size += data_size;\r
587     return *des_buf_pp;\r
588 }\r
589 void _bmp_save_decoding_status(bmp_decompress_struct_p bmp_ptr, int32_t status)\r
590 {\r
591     bmp_ptr->decode_status = status;\r
592     bmp_ptr->next_in += bmp_ptr->skip_size;\r
593     bmp_ptr->avail_in -= bmp_ptr->skip_size;\r
594     bmp_ptr->skip_size = 0;\r
595 }\r
596 void _bmp_input_buffer(bmp_decompress_struct_p bmp_ptr, uint8_t* src_buf, FX_DWORD src_size)\r
597 {\r
598     bmp_ptr->next_in = src_buf;\r
599     bmp_ptr->avail_in = src_size;\r
600     bmp_ptr->skip_size = 0;\r
601 }\r
602 FX_DWORD _bmp_get_avail_input(bmp_decompress_struct_p bmp_ptr, uint8_t** avial_buf_ptr)\r
603 {\r
604     if(avial_buf_ptr != NULL) {\r
605         *avial_buf_ptr = NULL;\r
606         if(bmp_ptr->avail_in > 0) {\r
607             *avial_buf_ptr = bmp_ptr->next_in;\r
608         }\r
609     }\r
610     return bmp_ptr->avail_in;\r
611 }\r
612 bmp_compress_struct_p _bmp_create_compress()\r
613 {\r
614     bmp_compress_struct_p bmp_ptr;\r
615     bmp_ptr = FX_Alloc(bmp_compress_struct, 1);\r
616     if (bmp_ptr) {\r
617         FXSYS_memset(bmp_ptr, 0, sizeof(bmp_compress_struct));\r
618     }\r
619     return bmp_ptr;\r
620 }\r
621 void _bmp_destroy_compress(bmp_compress_struct_p bmp_ptr)\r
622 {\r
623     if (bmp_ptr) {\r
624         if (bmp_ptr->src_free && bmp_ptr->src_buf) {\r
625             FX_Free(bmp_ptr->src_buf);\r
626         }\r
627         FX_Free(bmp_ptr);\r
628     }\r
629 }\r
630 static void WriteFileHeader(BmpFileHeaderPtr head_ptr, uint8_t* dst_buf)\r
631 {\r
632     FX_DWORD offset;\r
633     offset = 0;\r
634     _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfType);\r
635     offset += 2;\r
636     _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfSize);\r
637     offset += 4;\r
638     _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved1);\r
639     offset += 2;\r
640     _SetWord_LSBFirst(&dst_buf[offset], head_ptr->bfReserved2);\r
641     offset += 2;\r
642     _SetDWord_LSBFirst(&dst_buf[offset], head_ptr->bfOffBits);\r
643     offset += 4;\r
644 }\r
645 static void WriteInfoHeader(BmpInfoHeaderPtr info_head_ptr, uint8_t* dst_buf)\r
646 {\r
647     FX_DWORD offset;\r
648     offset = sizeof(BmpFileHeader);\r
649     _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSize);\r
650     offset += 4;\r
651     _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biWidth);\r
652     offset += 4;\r
653     _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biHeight);\r
654     offset += 4;\r
655     _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biPlanes);\r
656     offset += 2;\r
657     _SetWord_LSBFirst(&dst_buf[offset], info_head_ptr->biBitCount);\r
658     offset += 2;\r
659     _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biCompression);\r
660     offset += 4;\r
661     _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biSizeImage);\r
662     offset += 4;\r
663     _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biXPelsPerMeter);\r
664     offset += 4;\r
665     _SetDWord_LSBFirst(&dst_buf[offset], (FX_DWORD)info_head_ptr->biYPelsPerMeter);\r
666     offset += 4;\r
667     _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrUsed);\r
668     offset += 4;\r
669     _SetDWord_LSBFirst(&dst_buf[offset], info_head_ptr->biClrImportant);\r
670     offset += 4;\r
671 }\r
672 #ifdef BMP_SUPPORT_BITFIELD\r
673 static void _bmp_encode_bitfields(bmp_compress_struct_p bmp_ptr, uint8_t*& dst_buf, FX_DWORD& dst_size)\r
674 {\r
675     if (bmp_ptr->info_header.biBitCount != 16 && bmp_ptr->info_header.biBitCount != 32) {\r
676         return;\r
677     }\r
678     FX_DWORD size, dst_pos, i;\r
679     size = bmp_ptr->src_pitch * bmp_ptr->src_row * bmp_ptr->info_header.biBitCount / 16;\r
680     dst_pos = bmp_ptr->file_header.bfOffBits;\r
681     dst_size += size;\r
682     dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);\r
683     if (dst_buf == NULL) {\r
684         return;\r
685     }\r
686     FXSYS_memset(&dst_buf[dst_pos], 0, size);\r
687     FX_DWORD            mask_red;\r
688     FX_DWORD            mask_green;\r
689     FX_DWORD            mask_blue;\r
690     mask_red    = 0x7C00;\r
691     mask_green = 0x03E0;\r
692     mask_blue   = 0x001F;\r
693     if (bmp_ptr->info_header.biCompression == BMP_BITFIELDS) {\r
694         if (bmp_ptr->bit_type == BMP_BIT_565) {\r
695             mask_red    = 0xF800;\r
696             mask_green = 0x07E0;\r
697             mask_blue   = 0x001F;\r
698         }\r
699         if (bmp_ptr->info_header.biBitCount == 32) {\r
700             mask_red    = 0xFF0000;\r
701             mask_green = 0x00FF00;\r
702             mask_blue   = 0x0000FF;\r
703         }\r
704         _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_red);\r
705         dst_pos += 4;\r
706         _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_green);\r
707         dst_pos += 4;\r
708         _SetDWord_LSBFirst(&dst_buf[dst_pos], mask_blue);\r
709         dst_pos += 4;\r
710         bmp_ptr->file_header.bfOffBits = dst_pos;\r
711     }\r
712     uint8_t blue_bits = 0;\r
713     uint8_t green_bits = 0;\r
714     uint8_t red_bits = 0;\r
715     for(i = 0; i < bmp_ptr->info_header.biBitCount; i++) {\r
716         if((mask_blue >> i) & 0x01) {\r
717             blue_bits++;\r
718         }\r
719         if((mask_green >> i) & 0x01) {\r
720             green_bits++;\r
721         }\r
722         if((mask_red >> i) & 0x01) {\r
723             red_bits++;\r
724         }\r
725     }\r
726     green_bits += blue_bits;\r
727     red_bits += green_bits;\r
728     blue_bits = 8 - blue_bits;\r
729     green_bits -= 8;\r
730     red_bits -= 8;\r
731     i = 0;\r
732     for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--, i = 0) {\r
733         while (i < bmp_ptr->src_width * bmp_ptr->src_bpp / 8) {\r
734             uint8_t b = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];\r
735             uint8_t g = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];\r
736             uint8_t r = bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch + i++];\r
737             if (bmp_ptr->src_bpp == 32) {\r
738                 i++;\r
739             }\r
740             FX_DWORD pix_val = 0;\r
741             pix_val |= (b >> blue_bits) & mask_blue;\r
742             pix_val |= (g << green_bits) & mask_green;\r
743             pix_val |= (r << red_bits) & mask_red;\r
744             if (bmp_ptr->info_header.biBitCount == 16) {\r
745                 _SetWord_LSBFirst(&dst_buf[dst_pos], (FX_WORD)pix_val);\r
746                 dst_pos += 2;\r
747             } else {\r
748                 _SetDWord_LSBFirst(&dst_buf[dst_pos], pix_val);\r
749                 dst_pos += 4;\r
750             }\r
751         }\r
752     }\r
753     dst_size = dst_pos;\r
754 }\r
755 #endif\r
756 static void _bmp_encode_rgb(bmp_compress_struct_p bmp_ptr, uint8_t*& dst_buf, FX_DWORD& dst_size)\r
757 {\r
758     if (bmp_ptr->info_header.biBitCount == 16) {\r
759 #ifdef BMP_SUPPORT_BITFIELD\r
760         _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size);\r
761 #endif\r
762         return;\r
763     }\r
764     FX_DWORD size, dst_pos;\r
765     FX_DWORD dst_pitch = (bmp_ptr->src_width * bmp_ptr->info_header.biBitCount + 31) / 32 * 4;\r
766     size = dst_pitch * bmp_ptr->src_row;\r
767     dst_pos = bmp_ptr->file_header.bfOffBits;\r
768     dst_size += size;\r
769     dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);\r
770     if (dst_buf == NULL) {\r
771         return;\r
772     }\r
773     FXSYS_memset(&dst_buf[dst_pos], 0, size);\r
774     for (int32_t row_num = bmp_ptr->src_row - 1; row_num > -1; row_num--) {\r
775         FXSYS_memcpy(&dst_buf[dst_pos], &bmp_ptr->src_buf[row_num * bmp_ptr->src_pitch], bmp_ptr->src_pitch);\r
776         dst_pos += dst_pitch;\r
777     }\r
778     dst_size = dst_pos;\r
779 }\r
780 static uint8_t _bmp_rle8_search(const uint8_t* buf, int32_t len)\r
781 {\r
782     uint8_t num;\r
783     num = 1;\r
784     while (num < len) {\r
785         if (buf[num - 1] != buf[num] || num == 0xFF) {\r
786             break;\r
787         }\r
788         num++;\r
789     }\r
790     return num;\r
791 }\r
792 static void _bmp_encode_rle8(bmp_compress_struct_p bmp_ptr, uint8_t*& dst_buf, FX_DWORD& dst_size)\r
793 {\r
794     FX_DWORD size, dst_pos, index;\r
795     uint8_t rle[2] = {0};\r
796     size = bmp_ptr->src_pitch * bmp_ptr->src_row * 2;\r
797     dst_pos = bmp_ptr->file_header.bfOffBits;\r
798     dst_size += size;\r
799     dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);\r
800     if (dst_buf == NULL) {\r
801         return;\r
802     }\r
803     FXSYS_memset(&dst_buf[dst_pos], 0, size);\r
804     for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1; ) {\r
805         index = row_num * bmp_ptr->src_pitch;\r
806         rle[0] = _bmp_rle8_search(&bmp_ptr->src_buf[index + i], size - index - i);\r
807         rle[1] = bmp_ptr->src_buf[index + i];\r
808         if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) {\r
809             rle[0] = uint8_t(bmp_ptr->src_pitch - i);\r
810             if (rle[0]) {\r
811                 dst_buf[dst_pos++] = rle[0];\r
812                 dst_buf[dst_pos++] = rle[1];\r
813             }\r
814             dst_buf[dst_pos++] = RLE_MARKER;\r
815             dst_buf[dst_pos++] = RLE_EOL;\r
816             i = 0;\r
817             row_num--;\r
818         } else {\r
819             i += rle[0];\r
820             dst_buf[dst_pos++] = rle[0];\r
821             dst_buf[dst_pos++] = rle[1];\r
822         }\r
823     }\r
824     dst_buf[dst_pos++] = RLE_MARKER;\r
825     dst_buf[dst_pos++] = RLE_EOI;\r
826     dst_size = dst_pos;\r
827 }\r
828 static uint8_t _bmp_rle4_search(const uint8_t* buf, int32_t len)\r
829 {\r
830     uint8_t num;\r
831     num = 2;\r
832     while (num < len) {\r
833         if (buf[num - 2] != buf[num] || num == 0xFF) {\r
834             break;\r
835         }\r
836         num++;\r
837     }\r
838     return num;\r
839 }\r
840 static void _bmp_encode_rle4(bmp_compress_struct_p bmp_ptr, uint8_t*& dst_buf, FX_DWORD& dst_size)\r
841 {\r
842     FX_DWORD size, dst_pos, index;\r
843     uint8_t rle[2] = {0};\r
844     size = bmp_ptr->src_pitch * bmp_ptr->src_row;\r
845     dst_pos = bmp_ptr->file_header.bfOffBits;\r
846     dst_size += size;\r
847     dst_buf = FX_Realloc(uint8_t, dst_buf, dst_size);\r
848     if (dst_buf == NULL) {\r
849         return;\r
850     }\r
851     FXSYS_memset(&dst_buf[dst_pos], 0, size);\r
852     for (int32_t row_num = bmp_ptr->src_row - 1, i = 0; row_num > -1; rle[1] = 0) {\r
853         index = row_num * bmp_ptr->src_pitch;\r
854         rle[0] = _bmp_rle4_search(&bmp_ptr->src_buf[index + i], size - index - i);\r
855         rle[1] |= (bmp_ptr->src_buf[index + i] & 0x0f) << 4;\r
856         rle[1] |= bmp_ptr->src_buf[index + i + 1] & 0x0f;\r
857         if (i + rle[0] >= (int32_t)bmp_ptr->src_pitch) {\r
858             rle[0] = uint8_t(bmp_ptr->src_pitch - i);\r
859             if (rle[0]) {\r
860                 dst_buf[dst_pos++] = rle[0];\r
861                 dst_buf[dst_pos++] = rle[1];\r
862             }\r
863             dst_buf[dst_pos++] = RLE_MARKER;\r
864             dst_buf[dst_pos++] = RLE_EOL;\r
865             i = 0;\r
866             row_num--;\r
867         } else {\r
868             i += rle[0];\r
869             dst_buf[dst_pos++] = rle[0];\r
870             dst_buf[dst_pos++] = rle[1];\r
871         }\r
872     }\r
873     dst_buf[dst_pos++] = RLE_MARKER;\r
874     dst_buf[dst_pos++] = RLE_EOI;\r
875     dst_size = dst_pos;\r
876 }\r
877 FX_BOOL _bmp_encode_image( bmp_compress_struct_p bmp_ptr, uint8_t*& dst_buf, FX_DWORD& dst_size )\r
878 {\r
879     FX_DWORD head_size = sizeof(BmpFileHeader) + sizeof(BmpInfoHeader);\r
880     FX_DWORD pal_size = sizeof(FX_DWORD) * bmp_ptr->pal_num;\r
881     if (bmp_ptr->info_header.biClrUsed > 0 && bmp_ptr->info_header.biClrUsed < bmp_ptr->pal_num) {\r
882         pal_size = sizeof(FX_DWORD) * bmp_ptr->info_header.biClrUsed;\r
883     }\r
884     dst_size = head_size + sizeof(FX_DWORD) * bmp_ptr->pal_num;\r
885     dst_buf = FX_TryAlloc(uint8_t, dst_size);\r
886     if (dst_buf == NULL) {\r
887         return FALSE;\r
888     }\r
889     FXSYS_memset(dst_buf, 0, dst_size);\r
890     bmp_ptr->file_header.bfOffBits = head_size;\r
891     if (bmp_ptr->pal_ptr && pal_size) {\r
892         FXSYS_memcpy(&dst_buf[head_size], bmp_ptr->pal_ptr, pal_size);\r
893         bmp_ptr->file_header.bfOffBits += pal_size;\r
894     }\r
895     WriteInfoHeader(&bmp_ptr->info_header, dst_buf);\r
896     switch(bmp_ptr->info_header.biCompression) {\r
897         case BMP_RGB:\r
898             _bmp_encode_rgb(bmp_ptr, dst_buf, dst_size);\r
899             break;\r
900         case BMP_BITFIELDS:\r
901 #ifdef BMP_SUPPORT_BITFIELD\r
902             _bmp_encode_bitfields(bmp_ptr, dst_buf, dst_size);\r
903 #endif\r
904             break;\r
905         case BMP_RLE8:\r
906             _bmp_encode_rle8(bmp_ptr, dst_buf, dst_size);\r
907             break;\r
908         case BMP_RLE4:\r
909             _bmp_encode_rle4(bmp_ptr, dst_buf, dst_size);\r
910             break;\r
911         default:\r
912             ;\r
913     }\r
914     bmp_ptr->file_header.bfSize = dst_size;\r
915     WriteFileHeader(&bmp_ptr->file_header, dst_buf);\r
916     return TRUE;\r
917 }\r