summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormichi_cc <michi_cc@openttd.org>2011-09-02 20:16:29 +0000
committermichi_cc <michi_cc@openttd.org>2011-09-02 20:16:29 +0000
commit655d45e7d391582fb67c83f109e69bcd027bdec6 (patch)
tree0e7177987d9368f5fd059389985122f882651e68
parent73624abd5e699077ab043ef03d7178a3ef0c4728 (diff)
downloadopenttd-655d45e7d391582fb67c83f109e69bcd027bdec6.tar.xz
(svn r22872) -Fix [FS#4746]: Improve handling of slightly invalid BMP files using the under-specified RLE compression. Improve coding style while at it as well. (Based on patch by monoid)
-rw-r--r--src/bmp.cpp151
1 files changed, 84 insertions, 67 deletions
diff --git a/src/bmp.cpp b/src/bmp.cpp
index d39f6198e..a93785d4f 100644
--- a/src/bmp.cpp
+++ b/src/bmp.cpp
@@ -130,54 +130,63 @@ static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/
static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
- uint i;
uint x = 0;
uint y = info->height - 1;
- byte n, c, b;
byte *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
- n = ReadByte(buffer);
- c = ReadByte(buffer);
+
+ byte n = ReadByte(buffer);
+ byte c = ReadByte(buffer);
if (n == 0) {
switch (c) {
- case 0: // end of line
- x = 0;
- if (y == 0) return false;
- pixel = &data->bitmap[--y * info->width];
- break;
- case 1: // end of bitmap
- x = info->width;
- y = 0;
- pixel = NULL;
- break;
- case 2: // delta
- x += ReadByte(buffer);
- i = ReadByte(buffer);
- if (x >= info->width || i > y) return false;
- y -= i;
- pixel = &data->bitmap[y * info->width + x];
- break;
- default: // uncompressed
- i = 0;
- while (i++ < c) {
- if (EndOfBuffer(buffer) || x >= info->width) return false;
- b = ReadByte(buffer);
- *pixel++ = GB(b, 4, 4);
- x++;
- if (x < info->width && i++ < c) {
- *pixel++ = GB(b, 0, 4);
+ case 0: // end of line
+ x = 0;
+ if (y == 0) return false;
+ pixel = &data->bitmap[--y * info->width];
+ break;
+
+ case 1: // end of bitmap
+ return true;
+
+ case 2: { // delta
+ if (EndOfBuffer(buffer)) return false;
+ byte dx = ReadByte(buffer);
+ byte dy = ReadByte(buffer);
+
+ /* Check for over- and underflow. */
+ if (x + dx >= info->width || x + dx < x || dy > y) return false;
+
+ x += dx;
+ y -= dy;
+ pixel = &data->bitmap[y * info->width + x];
+ break;
+ }
+
+ default: { // uncompressed
+ uint i = 0;
+ while (i++ < c) {
+ if (EndOfBuffer(buffer) || x >= info->width) return false;
+ byte b = ReadByte(buffer);
+ *pixel++ = GB(b, 4, 4);
x++;
+ if (i++ < c) {
+ if (x >= info->width) return false;
+ *pixel++ = GB(b, 0, 4);
+ x++;
+ }
}
+ /* Padding for 16 bit align */
+ SkipBytes(buffer, ((c + 1) / 2) % 2);
+ break;
}
- /* Padding for 16 bit align */
- SkipBytes(buffer, ((c + 1) / 2) % 2);
- break;
}
} else {
- i = 0;
- while (i++ < n) {
- if (EndOfBuffer(buffer) || x >= info->width) return false;
+ /* Apparently it is common to encounter BMPs where the count of
+ * pixels to be written is higher than the remaining line width.
+ * Ignore the superfluous pixels instead of reporting an error. */
+ uint i = 0;
+ while (x < info->width && i++ < n) {
*pixel++ = GB(c, 4, 4);
x++;
if (x < info->width && i++ < n) {
@@ -214,47 +223,55 @@ static inline bool BmpRead8(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/
static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
- uint i;
uint x = 0;
uint y = info->height - 1;
- byte n, c;
byte *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
- n = ReadByte(buffer);
- c = ReadByte(buffer);
+
+ byte n = ReadByte(buffer);
+ byte c = ReadByte(buffer);
if (n == 0) {
switch (c) {
- case 0: // end of line
- x = 0;
- if (y == 0) return false;
- pixel = &data->bitmap[--y * info->width];
- break;
- case 1: // end of bitmap
- x = info->width;
- y = 0;
- pixel = NULL;
- break;
- case 2: // delta
- x += ReadByte(buffer);
- i = ReadByte(buffer);
- if (x >= info->width || i > y) return false;
- y -= i;
- pixel = &data->bitmap[y * info->width + x];
- break;
- default: // uncompressed
- for (i = 0; i < c; i++) {
- if (EndOfBuffer(buffer) || x >= info->width) return false;
- *pixel++ = ReadByte(buffer);
- x++;
+ case 0: // end of line
+ x = 0;
+ if (y == 0) return false;
+ pixel = &data->bitmap[--y * info->width];
+ break;
+
+ case 1: // end of bitmap
+ return true;
+
+ case 2: { // delta
+ if (EndOfBuffer(buffer)) return false;
+ byte dx = ReadByte(buffer);
+ byte dy = ReadByte(buffer);
+
+ /* Check for over- and underflow. */
+ if (x + dx >= info->width || x + dx < x || dy > y) return false;
+
+ x += dx;
+ y -= dy;
+ pixel = &data->bitmap[y * info->width + x];
+ break;
+ }
+
+ default: { // uncompressed
+ for (uint i = 0; i < c; i++) {
+ if (EndOfBuffer(buffer) || x >= info->width) return false;
+ *pixel++ = ReadByte(buffer);
+ x++;
+ }
+ /* Padding for 16 bit align */
+ SkipBytes(buffer, c % 2);
+ break;
}
- /* Padding for 16 bit align */
- SkipBytes(buffer, c % 2);
- break;
}
} else {
- for (i = 0; i < n; i++) {
- if (x >= info->width) return false;
+ /* Apparently it is common to encounter BMPs where the count of
+ * pixels to be written is higher than the remaining line width.
+ * Ignore the superfluous pixels instead of reporting an error. */
+ for (uint i = 0; x < info->width && i < n; i++) {
*pixel++ = c;
x++;
}