* Reads a 8-bit RLE compressed bpp bitmap */
| 159 | * Reads a 8-bit RLE compressed bpp bitmap |
| 160 | */ |
| 161 | static inline bool BmpRead8Rle(RandomAccessFile &file, BmpInfo &info, BmpData &data) |
| 162 | { |
| 163 | uint x = 0; |
| 164 | uint y = info.height - 1; |
| 165 | uint8_t *pixel = &data.bitmap[y * static_cast<size_t>(info.width)]; |
| 166 | while (y != 0 || x < info.width) { |
| 167 | if (file.AtEndOfFile()) return false; // the file is shorter than expected |
| 168 | |
| 169 | uint8_t n = file.ReadByte(); |
| 170 | uint8_t c = file.ReadByte(); |
| 171 | if (n == 0) { |
| 172 | switch (c) { |
| 173 | case 0: // end of line |
| 174 | x = 0; |
| 175 | if (y == 0) return false; |
| 176 | pixel = &data.bitmap[--y * static_cast<size_t>(info.width)]; |
| 177 | break; |
| 178 | |
| 179 | case 1: // end of bitmap |
| 180 | return true; |
| 181 | |
| 182 | case 2: { // delta |
| 183 | if (file.AtEndOfFile()) return false; |
| 184 | uint8_t dx = file.ReadByte(); |
| 185 | uint8_t dy = file.ReadByte(); |
| 186 | |
| 187 | /* Check for over- and underflow. */ |
| 188 | if (x + dx >= info.width || x + dx < x || dy > y) return false; |
| 189 | |
| 190 | x += dx; |
| 191 | y -= dy; |
| 192 | pixel = &data.bitmap[y * static_cast<size_t>(info.width) + x]; |
| 193 | break; |
| 194 | } |
| 195 | |
| 196 | default: { // uncompressed |
| 197 | for (uint i = 0; i < c; i++) { |
| 198 | if (file.AtEndOfFile() || x >= info.width) return false; |
| 199 | *pixel++ = file.ReadByte(); |
| 200 | x++; |
| 201 | } |
| 202 | /* Padding for 16 bit align */ |
| 203 | file.SkipBytes(c % 2); |
| 204 | break; |
| 205 | } |
| 206 | } |
| 207 | } else { |
| 208 | /* Apparently it is common to encounter BMPs where the count of |
| 209 | * pixels to be written is higher than the remaining line width. |
| 210 | * Ignore the superfluous pixels instead of reporting an error. */ |
| 211 | for (uint i = 0; x < info.width && i < n; i++) { |
| 212 | *pixel++ = c; |
| 213 | x++; |
| 214 | } |
| 215 | } |
| 216 | } |
| 217 | return true; |
| 218 | } |
no test coverage detected