mirror of https://github.com/OpenTTD/OpenTTD
(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)
parent
73624abd5e
commit
655d45e7d3
155
src/bmp.cpp
155
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)
|
static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||||
{
|
{
|
||||||
uint i;
|
|
||||||
uint x = 0;
|
uint x = 0;
|
||||||
uint y = info->height - 1;
|
uint y = info->height - 1;
|
||||||
byte n, c, b;
|
|
||||||
byte *pixel = &data->bitmap[y * info->width];
|
byte *pixel = &data->bitmap[y * info->width];
|
||||||
while (y != 0 || x < info->width) {
|
while (y != 0 || x < info->width) {
|
||||||
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
|
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) {
|
if (n == 0) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0: // end of line
|
case 0: // end of line
|
||||||
x = 0;
|
x = 0;
|
||||||
if (y == 0) return false;
|
if (y == 0) return false;
|
||||||
pixel = &data->bitmap[--y * info->width];
|
pixel = &data->bitmap[--y * info->width];
|
||||||
break;
|
break;
|
||||||
case 1: // end of bitmap
|
|
||||||
x = info->width;
|
case 1: // end of bitmap
|
||||||
y = 0;
|
return true;
|
||||||
pixel = NULL;
|
|
||||||
break;
|
case 2: { // delta
|
||||||
case 2: // delta
|
if (EndOfBuffer(buffer)) return false;
|
||||||
x += ReadByte(buffer);
|
byte dx = ReadByte(buffer);
|
||||||
i = ReadByte(buffer);
|
byte dy = ReadByte(buffer);
|
||||||
if (x >= info->width || i > y) return false;
|
|
||||||
y -= i;
|
/* Check for over- and underflow. */
|
||||||
pixel = &data->bitmap[y * info->width + x];
|
if (x + dx >= info->width || x + dx < x || dy > y) return false;
|
||||||
break;
|
|
||||||
default: // uncompressed
|
x += dx;
|
||||||
i = 0;
|
y -= dy;
|
||||||
while (i++ < c) {
|
pixel = &data->bitmap[y * info->width + x];
|
||||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
break;
|
||||||
b = ReadByte(buffer);
|
}
|
||||||
*pixel++ = GB(b, 4, 4);
|
|
||||||
x++;
|
default: { // uncompressed
|
||||||
if (x < info->width && i++ < c) {
|
uint i = 0;
|
||||||
*pixel++ = GB(b, 0, 4);
|
while (i++ < c) {
|
||||||
x++;
|
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 {
|
} else {
|
||||||
i = 0;
|
/* Apparently it is common to encounter BMPs where the count of
|
||||||
while (i++ < n) {
|
* pixels to be written is higher than the remaining line width.
|
||||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
* Ignore the superfluous pixels instead of reporting an error. */
|
||||||
|
uint i = 0;
|
||||||
|
while (x < info->width && i++ < n) {
|
||||||
*pixel++ = GB(c, 4, 4);
|
*pixel++ = GB(c, 4, 4);
|
||||||
x++;
|
x++;
|
||||||
if (x < info->width && i++ < n) {
|
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)
|
static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
|
||||||
{
|
{
|
||||||
uint i;
|
|
||||||
uint x = 0;
|
uint x = 0;
|
||||||
uint y = info->height - 1;
|
uint y = info->height - 1;
|
||||||
byte n, c;
|
|
||||||
byte *pixel = &data->bitmap[y * info->width];
|
byte *pixel = &data->bitmap[y * info->width];
|
||||||
while (y != 0 || x < info->width) {
|
while (y != 0 || x < info->width) {
|
||||||
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
|
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) {
|
if (n == 0) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0: // end of line
|
case 0: // end of line
|
||||||
x = 0;
|
x = 0;
|
||||||
if (y == 0) return false;
|
if (y == 0) return false;
|
||||||
pixel = &data->bitmap[--y * info->width];
|
pixel = &data->bitmap[--y * info->width];
|
||||||
break;
|
break;
|
||||||
case 1: // end of bitmap
|
|
||||||
x = info->width;
|
case 1: // end of bitmap
|
||||||
y = 0;
|
return true;
|
||||||
pixel = NULL;
|
|
||||||
break;
|
case 2: { // delta
|
||||||
case 2: // delta
|
if (EndOfBuffer(buffer)) return false;
|
||||||
x += ReadByte(buffer);
|
byte dx = ReadByte(buffer);
|
||||||
i = ReadByte(buffer);
|
byte dy = ReadByte(buffer);
|
||||||
if (x >= info->width || i > y) return false;
|
|
||||||
y -= i;
|
/* Check for over- and underflow. */
|
||||||
pixel = &data->bitmap[y * info->width + x];
|
if (x + dx >= info->width || x + dx < x || dy > y) return false;
|
||||||
break;
|
|
||||||
default: // uncompressed
|
x += dx;
|
||||||
for (i = 0; i < c; i++) {
|
y -= dy;
|
||||||
if (EndOfBuffer(buffer) || x >= info->width) return false;
|
pixel = &data->bitmap[y * info->width + x];
|
||||||
*pixel++ = ReadByte(buffer);
|
break;
|
||||||
x++;
|
}
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
for (i = 0; i < n; i++) {
|
/* Apparently it is common to encounter BMPs where the count of
|
||||||
if (x >= info->width) return false;
|
* 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;
|
*pixel++ = c;
|
||||||
x++;
|
x++;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue