* Reads a 4-bit RLE compressed bitmap * The bitmap is converted to a 8 bpp bitmap */
| 69 | * The bitmap is converted to a 8 bpp bitmap |
| 70 | */ |
| 71 | static inline bool BmpRead4Rle(RandomAccessFile &file, BmpInfo &info, BmpData &data) |
| 72 | { |
| 73 | uint x = 0; |
| 74 | uint y = info.height - 1; |
| 75 | uint8_t *pixel = &data.bitmap[y * static_cast<size_t>(info.width)]; |
| 76 | while (y != 0 || x < info.width) { |
| 77 | if (file.AtEndOfFile()) return false; // the file is shorter than expected |
| 78 | |
| 79 | uint8_t n = file.ReadByte(); |
| 80 | uint8_t c = file.ReadByte(); |
| 81 | if (n == 0) { |
| 82 | switch (c) { |
| 83 | case 0: // end of line |
| 84 | x = 0; |
| 85 | if (y == 0) return false; |
| 86 | pixel = &data.bitmap[--y * static_cast<size_t>(info.width)]; |
| 87 | break; |
| 88 | |
| 89 | case 1: // end of bitmap |
| 90 | return true; |
| 91 | |
| 92 | case 2: { // delta |
| 93 | if (file.AtEndOfFile()) return false; |
| 94 | uint8_t dx = file.ReadByte(); |
| 95 | uint8_t dy = file.ReadByte(); |
| 96 | |
| 97 | /* Check for over- and underflow. */ |
| 98 | if (x + dx >= info.width || x + dx < x || dy > y) return false; |
| 99 | |
| 100 | x += dx; |
| 101 | y -= dy; |
| 102 | pixel = &data.bitmap[y * info.width + x]; |
| 103 | break; |
| 104 | } |
| 105 | |
| 106 | default: { // uncompressed |
| 107 | uint i = 0; |
| 108 | while (i++ < c) { |
| 109 | if (file.AtEndOfFile() || x >= info.width) return false; |
| 110 | uint8_t b = file.ReadByte(); |
| 111 | *pixel++ = GB(b, 4, 4); |
| 112 | x++; |
| 113 | if (i++ < c) { |
| 114 | if (x >= info.width) return false; |
| 115 | *pixel++ = GB(b, 0, 4); |
| 116 | x++; |
| 117 | } |
| 118 | } |
| 119 | /* Padding for 16 bit align */ |
| 120 | file.SkipBytes(((c + 1) / 2) % 2); |
| 121 | break; |
| 122 | } |
| 123 | } |
| 124 | } else { |
| 125 | /* Apparently it is common to encounter BMPs where the count of |
| 126 | * pixels to be written is higher than the remaining line width. |
| 127 | * Ignore the superfluous pixels instead of reporting an error. */ |
| 128 | uint i = 0; |
no test coverage detected