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