• 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 #include <limits>
11 
12 #include "core/fxcrt/fx_system.h"
13 #include "third_party/base/logging.h"
14 #include "third_party/base/ptr_util.h"
15 
16 static_assert(sizeof(BmpFileHeader) == 14,
17               "BmpFileHeader should have a size of 14");
18 
19 namespace {
20 
21 const size_t kBmpCoreHeaderSize = 12;
22 const size_t kBmpInfoHeaderSize = 40;
23 
HalfRoundUp(uint8_t value)24 uint8_t HalfRoundUp(uint8_t value) {
25   uint16_t value16 = value;
26   return static_cast<uint8_t>((value16 + 1) / 2);
27 }
28 
29 }  // namespace
30 
BMPDecompressor()31 BMPDecompressor::BMPDecompressor()
32     : context_ptr(nullptr),
33       next_in(nullptr),
34       header_offset(0),
35       width(0),
36       height(0),
37       compress_flag(0),
38       components(0),
39       src_row_bytes(0),
40       out_row_bytes(0),
41       bitCounts(0),
42       color_used(0),
43       imgTB_flag(false),
44       pal_num(0),
45       pal_type(0),
46       data_size(0),
47       img_data_offset(0),
48       img_ifh_size(0),
49       row_num(0),
50       col_num(0),
51       dpi_x(0),
52       dpi_y(0),
53       mask_red(0),
54       mask_green(0),
55       mask_blue(0),
56       avail_in(0),
57       skip_size(0),
58       decode_status(BMP_D_STATUS_HEADER) {}
59 
~BMPDecompressor()60 BMPDecompressor::~BMPDecompressor() {}
61 
Error()62 void BMPDecompressor::Error() {
63   longjmp(jmpbuf, 1);
64 }
65 
ReadScanline(uint32_t row_num,const std::vector<uint8_t> & row_buf)66 void BMPDecompressor::ReadScanline(uint32_t row_num,
67                                    const std::vector<uint8_t>& row_buf) {
68   auto* p = reinterpret_cast<CBmpContext*>(context_ptr);
69   p->m_pDelegate->BmpReadScanline(row_num, row_buf);
70 }
71 
GetDataPosition(uint32_t rcd_pos)72 bool BMPDecompressor::GetDataPosition(uint32_t rcd_pos) {
73   auto* p = reinterpret_cast<CBmpContext*>(context_ptr);
74   return p->m_pDelegate->BmpInputImagePositionBuf(rcd_pos);
75 }
76 
ReadHeader()77 int32_t BMPDecompressor::ReadHeader() {
78   uint32_t skip_size_org = skip_size;
79   if (decode_status == BMP_D_STATUS_HEADER) {
80     BmpFileHeader* pBmp_header = nullptr;
81     if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_header),
82                   sizeof(BmpFileHeader))) {
83       return 2;
84     }
85 
86     pBmp_header->bfType =
87         FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&pBmp_header->bfType));
88     pBmp_header->bfOffBits = FXDWORD_GET_LSBFIRST(
89         reinterpret_cast<uint8_t*>(&pBmp_header->bfOffBits));
90     data_size =
91         FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&pBmp_header->bfSize));
92     if (pBmp_header->bfType != BMP_SIGNATURE) {
93       Error();
94       NOTREACHED();
95     }
96     if (avail_in < sizeof(uint32_t)) {
97       skip_size = skip_size_org;
98       return 2;
99     }
100     img_ifh_size =
101         FXDWORD_GET_LSBFIRST(static_cast<uint8_t*>(next_in + skip_size));
102     pal_type = 0;
103     static_assert(sizeof(BmpCoreHeader) == kBmpCoreHeaderSize,
104                   "BmpCoreHeader has wrong size");
105     static_assert(sizeof(BmpInfoHeader) == kBmpInfoHeaderSize,
106                   "BmpInfoHeader has wrong size");
107     switch (img_ifh_size) {
108       case kBmpCoreHeaderSize: {
109         pal_type = 1;
110         BmpCoreHeader* pBmp_core_header = nullptr;
111         if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_core_header),
112                       img_ifh_size)) {
113           skip_size = skip_size_org;
114           return 2;
115         }
116         width = FXWORD_GET_LSBFIRST(
117             reinterpret_cast<uint8_t*>(&pBmp_core_header->bcWidth));
118         height = FXWORD_GET_LSBFIRST(
119             reinterpret_cast<uint8_t*>(&pBmp_core_header->bcHeight));
120         bitCounts = FXWORD_GET_LSBFIRST(
121             reinterpret_cast<uint8_t*>(&pBmp_core_header->bcBitCount));
122         compress_flag = BMP_RGB;
123         imgTB_flag = false;
124       } break;
125       case kBmpInfoHeaderSize: {
126         BmpInfoHeader* pBmp_info_header = nullptr;
127         if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_info_header),
128                       img_ifh_size)) {
129           skip_size = skip_size_org;
130           return 2;
131         }
132         width = FXDWORD_GET_LSBFIRST(
133             reinterpret_cast<uint8_t*>(&pBmp_info_header->biWidth));
134         int32_t signed_height = FXDWORD_GET_LSBFIRST(
135             reinterpret_cast<uint8_t*>(&pBmp_info_header->biHeight));
136         bitCounts = FXWORD_GET_LSBFIRST(
137             reinterpret_cast<uint8_t*>(&pBmp_info_header->biBitCount));
138         compress_flag = FXDWORD_GET_LSBFIRST(
139             reinterpret_cast<uint8_t*>(&pBmp_info_header->biCompression));
140         color_used = FXDWORD_GET_LSBFIRST(
141             reinterpret_cast<uint8_t*>(&pBmp_info_header->biClrUsed));
142         dpi_x = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
143             reinterpret_cast<uint8_t*>(&pBmp_info_header->biXPelsPerMeter)));
144         dpi_y = static_cast<int32_t>(FXDWORD_GET_LSBFIRST(
145             reinterpret_cast<uint8_t*>(&pBmp_info_header->biYPelsPerMeter)));
146         SetHeight(signed_height);
147       } break;
148       default: {
149         if (img_ifh_size >
150             std::min(kBmpInfoHeaderSize, sizeof(BmpInfoHeader))) {
151           BmpInfoHeader* pBmp_info_header = nullptr;
152           if (!ReadData(reinterpret_cast<uint8_t**>(&pBmp_info_header),
153                         img_ifh_size)) {
154             skip_size = skip_size_org;
155             return 2;
156           }
157           uint16_t biPlanes;
158           width = FXDWORD_GET_LSBFIRST(
159               reinterpret_cast<uint8_t*>(&pBmp_info_header->biWidth));
160           int32_t signed_height = FXDWORD_GET_LSBFIRST(
161               reinterpret_cast<uint8_t*>(&pBmp_info_header->biHeight));
162           bitCounts = FXWORD_GET_LSBFIRST(
163               reinterpret_cast<uint8_t*>(&pBmp_info_header->biBitCount));
164           compress_flag = FXDWORD_GET_LSBFIRST(
165               reinterpret_cast<uint8_t*>(&pBmp_info_header->biCompression));
166           color_used = FXDWORD_GET_LSBFIRST(
167               reinterpret_cast<uint8_t*>(&pBmp_info_header->biClrUsed));
168           biPlanes = FXWORD_GET_LSBFIRST(
169               reinterpret_cast<uint8_t*>(&pBmp_info_header->biPlanes));
170           dpi_x = FXDWORD_GET_LSBFIRST(
171               reinterpret_cast<uint8_t*>(&pBmp_info_header->biXPelsPerMeter));
172           dpi_y = FXDWORD_GET_LSBFIRST(
173               reinterpret_cast<uint8_t*>(&pBmp_info_header->biYPelsPerMeter));
174           SetHeight(signed_height);
175           if (compress_flag == BMP_RGB && biPlanes == 1 && color_used == 0)
176             break;
177         }
178         Error();
179         NOTREACHED();
180       }
181     }
182     if (width > BMP_MAX_WIDTH || compress_flag > BMP_BITFIELDS) {
183       Error();
184       NOTREACHED();
185     }
186     switch (bitCounts) {
187       case 1:
188       case 4:
189       case 8:
190       case 16:
191       case 24: {
192         if (color_used > 1U << bitCounts) {
193           Error();
194           NOTREACHED();
195         }
196       }
197       case 32:
198         break;
199       default:
200         Error();
201         NOTREACHED();
202     }
203     src_row_bytes = BMP_WIDTHBYTES(width, bitCounts);
204     switch (bitCounts) {
205       case 1:
206       case 4:
207       case 8:
208         out_row_bytes = BMP_WIDTHBYTES(width, 8);
209         components = 1;
210         break;
211       case 16:
212       case 24:
213         out_row_bytes = BMP_WIDTHBYTES(width, 24);
214         components = 3;
215         break;
216       case 32:
217         out_row_bytes = src_row_bytes;
218         components = 4;
219         break;
220     }
221     out_row_buffer.clear();
222 
223     if (out_row_bytes <= 0) {
224       Error();
225       NOTREACHED();
226     }
227 
228     out_row_buffer.resize(out_row_bytes);
229     SaveDecodingStatus(BMP_D_STATUS_PAL);
230   }
231   if (decode_status == BMP_D_STATUS_PAL) {
232     skip_size_org = skip_size;
233     if (compress_flag == BMP_BITFIELDS) {
234       if (bitCounts != 16 && bitCounts != 32) {
235         Error();
236         NOTREACHED();
237       }
238       uint32_t* mask;
239       if (ReadData(reinterpret_cast<uint8_t**>(&mask), 3 * sizeof(uint32_t)) ==
240           nullptr) {
241         skip_size = skip_size_org;
242         return 2;
243       }
244       mask_red = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[0]));
245       mask_green = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[1]));
246       mask_blue = FXDWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(&mask[2]));
247       if (mask_red & mask_green || mask_red & mask_blue ||
248           mask_green & mask_blue) {
249         Error();
250         NOTREACHED();
251       }
252       header_offset = std::max(header_offset, 26 + img_ifh_size);
253       SaveDecodingStatus(BMP_D_STATUS_DATA_PRE);
254       return 1;
255     } else if (bitCounts == 16) {
256       mask_red = 0x7C00;
257       mask_green = 0x03E0;
258       mask_blue = 0x001F;
259     }
260     pal_num = 0;
261     if (bitCounts < 16) {
262       pal_num = 1 << bitCounts;
263       if (color_used != 0)
264         pal_num = color_used;
265       uint8_t* src_pal_ptr = nullptr;
266       uint32_t src_pal_size = pal_num * (pal_type ? 3 : 4);
267       if (ReadData(&src_pal_ptr, src_pal_size) == nullptr) {
268         skip_size = skip_size_org;
269         return 2;
270       }
271       palette.resize(pal_num);
272       int32_t src_pal_index = 0;
273       if (pal_type == BMP_PAL_OLD) {
274         while (src_pal_index < pal_num) {
275           palette[src_pal_index++] = BMP_PAL_ENCODE(
276               0x00, src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
277           src_pal_ptr += 3;
278         }
279       } else {
280         while (src_pal_index < pal_num) {
281           palette[src_pal_index++] = BMP_PAL_ENCODE(
282               src_pal_ptr[3], src_pal_ptr[2], src_pal_ptr[1], src_pal_ptr[0]);
283           src_pal_ptr += 4;
284         }
285       }
286     }
287     header_offset = std::max(header_offset,
288                              14 + img_ifh_size + pal_num * (pal_type ? 3 : 4));
289     SaveDecodingStatus(BMP_D_STATUS_DATA_PRE);
290   }
291   return 1;
292 }
293 
ValidateFlag() const294 bool BMPDecompressor::ValidateFlag() const {
295   switch (compress_flag) {
296     case BMP_RGB:
297     case BMP_BITFIELDS:
298     case BMP_RLE8:
299     case BMP_RLE4:
300       return true;
301     default:
302       return false;
303   }
304 }
305 
DecodeImage()306 int32_t BMPDecompressor::DecodeImage() {
307   if (decode_status == BMP_D_STATUS_DATA_PRE) {
308     avail_in = 0;
309     if (!GetDataPosition(header_offset)) {
310       decode_status = BMP_D_STATUS_TAIL;
311       Error();
312       NOTREACHED();
313     }
314     row_num = 0;
315     SaveDecodingStatus(BMP_D_STATUS_DATA);
316   }
317   if (decode_status != BMP_D_STATUS_DATA || !ValidateFlag()) {
318     Error();
319     NOTREACHED();
320   }
321   switch (compress_flag) {
322     case BMP_RGB:
323     case BMP_BITFIELDS:
324       return DecodeRGB();
325     case BMP_RLE8:
326       return DecodeRLE8();
327     case BMP_RLE4:
328       return DecodeRLE4();
329     default:
330       return 0;
331   }
332 }
333 
ValidateColorIndex(uint8_t val)334 bool BMPDecompressor::ValidateColorIndex(uint8_t val) {
335   if (val >= pal_num) {
336     Error();
337     NOTREACHED();
338   }
339   return true;
340 }
341 
DecodeRGB()342 int32_t BMPDecompressor::DecodeRGB() {
343   uint8_t* des_buf = nullptr;
344   while (row_num < height) {
345     size_t idx = 0;
346     if (!ReadData(&des_buf, src_row_bytes))
347       return 2;
348 
349     SaveDecodingStatus(BMP_D_STATUS_DATA);
350     switch (bitCounts) {
351       case 1: {
352         for (uint32_t col = 0; col < width; ++col)
353           out_row_buffer[idx++] =
354               des_buf[col >> 3] & (0x80 >> (col % 8)) ? 0x01 : 0x00;
355       } break;
356       case 4: {
357         for (uint32_t col = 0; col < width; ++col) {
358           out_row_buffer[idx++] = (col & 0x01)
359                                       ? (des_buf[col >> 1] & 0x0F)
360                                       : ((des_buf[col >> 1] & 0xF0) >> 4);
361         }
362       } break;
363       case 16: {
364         uint16_t* buf = (uint16_t*)des_buf;
365         uint8_t blue_bits = 0;
366         uint8_t green_bits = 0;
367         uint8_t red_bits = 0;
368         for (int32_t i = 0; i < 16; i++) {
369           if ((mask_blue >> i) & 0x01)
370             blue_bits++;
371           if ((mask_green >> i) & 0x01)
372             green_bits++;
373           if ((mask_red >> i) & 0x01)
374             red_bits++;
375         }
376         green_bits += blue_bits;
377         red_bits += green_bits;
378         if (blue_bits > 8 || green_bits < 8 || red_bits < 8)
379           return 2;
380         blue_bits = 8 - blue_bits;
381         green_bits -= 8;
382         red_bits -= 8;
383         for (uint32_t col = 0; col < width; ++col) {
384           *buf = FXWORD_GET_LSBFIRST(reinterpret_cast<uint8_t*>(buf));
385           out_row_buffer[idx++] =
386               static_cast<uint8_t>((*buf & mask_blue) << blue_bits);
387           out_row_buffer[idx++] =
388               static_cast<uint8_t>((*buf & mask_green) >> green_bits);
389           out_row_buffer[idx++] =
390               static_cast<uint8_t>((*buf++ & mask_red) >> red_bits);
391         }
392       } break;
393       case 8:
394       case 24:
395       case 32:
396         std::copy(des_buf, des_buf + src_row_bytes, out_row_buffer.begin());
397         idx += src_row_bytes;
398         break;
399     }
400     for (uint8_t byte : out_row_buffer) {
401       if (!ValidateColorIndex(byte))
402         return 0;
403     }
404     ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
405                  out_row_buffer);
406   }
407   SaveDecodingStatus(BMP_D_STATUS_TAIL);
408   return 1;
409 }
410 
DecodeRLE8()411 int32_t BMPDecompressor::DecodeRLE8() {
412   uint8_t* first_byte_ptr = nullptr;
413   uint8_t* second_byte_ptr = nullptr;
414   col_num = 0;
415   while (true) {
416     uint32_t skip_size_org = skip_size;
417     if (!ReadData(&first_byte_ptr, 1))
418       return 2;
419 
420     switch (*first_byte_ptr) {
421       case RLE_MARKER: {
422         if (!ReadData(&first_byte_ptr, 1)) {
423           skip_size = skip_size_org;
424           return 2;
425         }
426         switch (*first_byte_ptr) {
427           case RLE_EOL: {
428             if (row_num >= height) {
429               SaveDecodingStatus(BMP_D_STATUS_TAIL);
430               Error();
431               NOTREACHED();
432             }
433             ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
434                          out_row_buffer);
435             col_num = 0;
436             std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
437             SaveDecodingStatus(BMP_D_STATUS_DATA);
438             continue;
439           }
440           case RLE_EOI: {
441             if (row_num < height) {
442               ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
443                            out_row_buffer);
444             }
445             SaveDecodingStatus(BMP_D_STATUS_TAIL);
446             return 1;
447           }
448           case RLE_DELTA: {
449             uint8_t* delta_ptr;
450             if (!ReadData(&delta_ptr, 2)) {
451               skip_size = skip_size_org;
452               return 2;
453             }
454             col_num += delta_ptr[0];
455             size_t bmp_row_num_next = row_num + delta_ptr[1];
456             if (col_num >= out_row_bytes || bmp_row_num_next >= height) {
457               Error();
458               NOTREACHED();
459             }
460             while (row_num < bmp_row_num_next) {
461               std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
462               ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
463                            out_row_buffer);
464             }
465           } break;
466           default: {
467             int32_t avail_size = out_row_bytes - col_num;
468             if (!avail_size ||
469                 static_cast<int32_t>(*first_byte_ptr) > avail_size) {
470               Error();
471               NOTREACHED();
472             }
473             if (!ReadData(&second_byte_ptr, *first_byte_ptr & 1
474                                                 ? *first_byte_ptr + 1
475                                                 : *first_byte_ptr)) {
476               skip_size = skip_size_org;
477               return 2;
478             }
479             std::copy(second_byte_ptr, second_byte_ptr + *first_byte_ptr,
480                       out_row_buffer.begin() + col_num);
481             for (size_t i = col_num; i < col_num + *first_byte_ptr; ++i) {
482               if (!ValidateColorIndex(out_row_buffer[i]))
483                 return 0;
484             }
485             col_num += *first_byte_ptr;
486           }
487         }
488       } break;
489       default: {
490         int32_t avail_size = out_row_bytes - col_num;
491         if (!avail_size || static_cast<int32_t>(*first_byte_ptr) > avail_size) {
492           Error();
493           NOTREACHED();
494         }
495         if (!ReadData(&second_byte_ptr, 1)) {
496           skip_size = skip_size_org;
497           return 2;
498         }
499         std::fill(out_row_buffer.begin() + col_num,
500                   out_row_buffer.begin() + col_num + *first_byte_ptr,
501                   *second_byte_ptr);
502         if (!ValidateColorIndex(out_row_buffer[col_num]))
503           return 0;
504         col_num += *first_byte_ptr;
505       }
506     }
507   }
508   Error();
509   NOTREACHED();
510 }
511 
DecodeRLE4()512 int32_t BMPDecompressor::DecodeRLE4() {
513   uint8_t* first_byte_ptr = nullptr;
514   uint8_t* second_byte_ptr = nullptr;
515   col_num = 0;
516   while (true) {
517     uint32_t skip_size_org = skip_size;
518     if (!ReadData(&first_byte_ptr, 1))
519       return 2;
520 
521     switch (*first_byte_ptr) {
522       case RLE_MARKER: {
523         if (!ReadData(&first_byte_ptr, 1)) {
524           skip_size = skip_size_org;
525           return 2;
526         }
527         switch (*first_byte_ptr) {
528           case RLE_EOL: {
529             if (row_num >= height) {
530               SaveDecodingStatus(BMP_D_STATUS_TAIL);
531               Error();
532               NOTREACHED();
533             }
534             ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
535                          out_row_buffer);
536             col_num = 0;
537             std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
538             SaveDecodingStatus(BMP_D_STATUS_DATA);
539             continue;
540           }
541           case RLE_EOI: {
542             if (row_num < height) {
543               ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
544                            out_row_buffer);
545             }
546             SaveDecodingStatus(BMP_D_STATUS_TAIL);
547             return 1;
548           }
549           case RLE_DELTA: {
550             uint8_t* delta_ptr;
551             if (!ReadData(&delta_ptr, 2)) {
552               skip_size = skip_size_org;
553               return 2;
554             }
555             col_num += delta_ptr[0];
556             size_t bmp_row_num_next = row_num + delta_ptr[1];
557             if (col_num >= out_row_bytes || bmp_row_num_next >= height) {
558               Error();
559               NOTREACHED();
560             }
561             while (row_num < bmp_row_num_next) {
562               std::fill(out_row_buffer.begin(), out_row_buffer.end(), 0);
563               ReadScanline(imgTB_flag ? row_num++ : (height - 1 - row_num++),
564                            out_row_buffer);
565             }
566           } break;
567           default: {
568             int32_t avail_size = out_row_bytes - col_num;
569             if (!avail_size) {
570               Error();
571               NOTREACHED();
572             }
573             uint8_t size = HalfRoundUp(*first_byte_ptr);
574             if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
575               if (size + (col_num >> 1) > src_row_bytes) {
576                 Error();
577                 NOTREACHED();
578               }
579               *first_byte_ptr = avail_size - 1;
580             }
581             if (!ReadData(&second_byte_ptr, size & 1 ? size + 1 : size)) {
582               skip_size = skip_size_org;
583               return 2;
584             }
585             for (uint8_t i = 0; i < *first_byte_ptr; i++) {
586               uint8_t color = (i & 0x01) ? (*second_byte_ptr++ & 0x0F)
587                                          : (*second_byte_ptr & 0xF0) >> 4;
588               if (!ValidateColorIndex(color))
589                 return 0;
590 
591               out_row_buffer[col_num++] = color;
592             }
593           }
594         }
595       } break;
596       default: {
597         int32_t avail_size = out_row_bytes - col_num;
598         if (!avail_size) {
599           Error();
600           NOTREACHED();
601         }
602         if (static_cast<int32_t>(*first_byte_ptr) > avail_size) {
603           uint8_t size = HalfRoundUp(*first_byte_ptr);
604           if (size + (col_num >> 1) > src_row_bytes) {
605             Error();
606             NOTREACHED();
607           }
608           *first_byte_ptr = avail_size - 1;
609         }
610         if (!ReadData(&second_byte_ptr, 1)) {
611           skip_size = skip_size_org;
612           return 2;
613         }
614         for (uint8_t i = 0; i < *first_byte_ptr; i++) {
615           uint8_t second_byte = *second_byte_ptr;
616           second_byte =
617               i & 0x01 ? (second_byte & 0x0F) : (second_byte & 0xF0) >> 4;
618           if (!ValidateColorIndex(second_byte))
619             return 0;
620           out_row_buffer[col_num++] = second_byte;
621         }
622       }
623     }
624   }
625   Error();
626   NOTREACHED();
627 }
628 
ReadData(uint8_t ** des_buf,uint32_t data_size)629 uint8_t* BMPDecompressor::ReadData(uint8_t** des_buf, uint32_t data_size) {
630   if (avail_in < skip_size + data_size)
631     return nullptr;
632 
633   *des_buf = next_in + skip_size;
634   skip_size += data_size;
635   return *des_buf;
636 }
637 
SaveDecodingStatus(int32_t status)638 void BMPDecompressor::SaveDecodingStatus(int32_t status) {
639   decode_status = status;
640   next_in += skip_size;
641   avail_in -= skip_size;
642   skip_size = 0;
643 }
644 
SetInputBuffer(uint8_t * src_buf,uint32_t src_size)645 void BMPDecompressor::SetInputBuffer(uint8_t* src_buf, uint32_t src_size) {
646   next_in = src_buf;
647   avail_in = src_size;
648   skip_size = 0;
649 }
650 
GetAvailInput(uint8_t ** avail_buf)651 uint32_t BMPDecompressor::GetAvailInput(uint8_t** avail_buf) {
652   if (avail_buf) {
653     *avail_buf = nullptr;
654     if (avail_in > 0)
655       *avail_buf = next_in;
656   }
657   return avail_in;
658 }
659 
SetHeight(int32_t signed_height)660 void BMPDecompressor::SetHeight(int32_t signed_height) {
661   if (signed_height >= 0) {
662     height = signed_height;
663     return;
664   }
665   if (signed_height == std::numeric_limits<int>::min()) {
666     Error();
667     NOTREACHED();
668   }
669   height = -signed_height;
670   imgTB_flag = true;
671 }
672