mirror of https://github.com/libsdl-org/SDL.git
Fixed decoding 4-bit RLE encoded BMP files
Also flipped the return value of readRlePixels() to match convention. Fixes https://github.com/libsdl-org/sdl2-compat/issues/308
This commit is contained in:
parent
8ccf85c59e
commit
07c22da464
|
|
@ -76,16 +76,16 @@ static bool readRlePixels(SDL_Surface *surface, SDL_IOStream *src, int isRle8)
|
||||||
int ofs = 0;
|
int ofs = 0;
|
||||||
Uint8 ch;
|
Uint8 ch;
|
||||||
Uint8 needsPad;
|
Uint8 needsPad;
|
||||||
|
const int pixels_per_byte = (isRle8 ? 1 : 2);
|
||||||
|
|
||||||
#define COPY_PIXEL(x) \
|
#define COPY_PIXEL(x) \
|
||||||
spot = &bits[ofs++]; \
|
spot = &bits[ofs++]; \
|
||||||
if (spot >= start && spot < end) \
|
if (spot >= start && spot < end) \
|
||||||
*spot = (x)
|
*spot = (x)
|
||||||
|
|
||||||
// !!! FIXME: for all these reads, handle error vs eof? handle -2 if non-blocking?
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!SDL_ReadU8(src, &ch)) {
|
if (!SDL_ReadU8(src, &ch)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
| encoded mode starts with a run length, and then a byte
|
| encoded mode starts with a run length, and then a byte
|
||||||
|
|
@ -94,26 +94,12 @@ static bool readRlePixels(SDL_Surface *surface, SDL_IOStream *src, int isRle8)
|
||||||
if (ch) {
|
if (ch) {
|
||||||
Uint8 pixel;
|
Uint8 pixel;
|
||||||
if (!SDL_ReadU8(src, &pixel)) {
|
if (!SDL_ReadU8(src, &pixel)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
if (isRle8) { // 256-color bitmap, compressed
|
|
||||||
do {
|
|
||||||
COPY_PIXEL(pixel);
|
|
||||||
} while (--ch);
|
|
||||||
} else { // 16-color bitmap, compressed
|
|
||||||
Uint8 pixel0 = pixel >> 4;
|
|
||||||
Uint8 pixel1 = pixel & 0x0F;
|
|
||||||
for (;;) {
|
|
||||||
COPY_PIXEL(pixel0); // even count, high nibble
|
|
||||||
if (!--ch) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
COPY_PIXEL(pixel1); // odd count, low nibble
|
|
||||||
if (!--ch) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ch /= pixels_per_byte;
|
||||||
|
do {
|
||||||
|
COPY_PIXEL(pixel);
|
||||||
|
} while (--ch);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
| A leading zero is an escape; it may signal the end of the bitmap,
|
| A leading zero is an escape; it may signal the end of the bitmap,
|
||||||
|
|
@ -121,7 +107,7 @@ static bool readRlePixels(SDL_Surface *surface, SDL_IOStream *src, int isRle8)
|
||||||
| zero tag may be absolute mode or an escape
|
| zero tag may be absolute mode or an escape
|
||||||
*/
|
*/
|
||||||
if (!SDL_ReadU8(src, &ch)) {
|
if (!SDL_ReadU8(src, &ch)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 0: // end of line
|
case 0: // end of line
|
||||||
|
|
@ -129,47 +115,33 @@ static bool readRlePixels(SDL_Surface *surface, SDL_IOStream *src, int isRle8)
|
||||||
bits -= pitch; // go to previous
|
bits -= pitch; // go to previous
|
||||||
break;
|
break;
|
||||||
case 1: // end of bitmap
|
case 1: // end of bitmap
|
||||||
return false; // success!
|
printf("SUCCESS!\n");
|
||||||
|
return true; // success!
|
||||||
case 2: // delta
|
case 2: // delta
|
||||||
if (!SDL_ReadU8(src, &ch)) {
|
if (!SDL_ReadU8(src, &ch)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
ofs += ch;
|
ofs += ch / pixels_per_byte;
|
||||||
|
|
||||||
if (!SDL_ReadU8(src, &ch)) {
|
if (!SDL_ReadU8(src, &ch)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
bits -= (ch * pitch);
|
bits -= ((ch / pixels_per_byte) * pitch);
|
||||||
break;
|
break;
|
||||||
default: // no compression
|
default: // no compression
|
||||||
if (isRle8) {
|
ch /= pixels_per_byte;
|
||||||
needsPad = (ch & 1);
|
needsPad = (ch & 1);
|
||||||
do {
|
do {
|
||||||
Uint8 pixel;
|
Uint8 pixel;
|
||||||
if (!SDL_ReadU8(src, &pixel)) {
|
if (!SDL_ReadU8(src, &pixel)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
|
||||||
COPY_PIXEL(pixel);
|
|
||||||
} while (--ch);
|
|
||||||
} else {
|
|
||||||
needsPad = (((ch + 1) >> 1) & 1); // (ch+1)>>1: bytes size
|
|
||||||
for (;;) {
|
|
||||||
Uint8 pixel;
|
|
||||||
if (!SDL_ReadU8(src, &pixel)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
COPY_PIXEL(pixel >> 4);
|
|
||||||
if (!--ch) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
COPY_PIXEL(pixel & 0x0F);
|
|
||||||
if (!--ch) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
COPY_PIXEL(pixel);
|
||||||
|
} while (--ch);
|
||||||
|
|
||||||
// pad at even boundary
|
// pad at even boundary
|
||||||
if (needsPad && !SDL_ReadU8(src, &ch)) {
|
if (needsPad && !SDL_ReadU8(src, &ch)) {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -513,10 +485,13 @@ SDL_Surface *SDL_LoadBMP_IO(SDL_IOStream *src, bool closeio)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
|
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
|
||||||
was_error = readRlePixels(surface, src, biCompression == BI_RLE8);
|
if (!readRlePixels(surface, src, biCompression == BI_RLE8)) {
|
||||||
if (was_error) {
|
|
||||||
SDL_SetError("Error reading from datastream");
|
SDL_SetError("Error reading from datastream");
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Success!
|
||||||
|
was_error = false;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
top = (Uint8 *)surface->pixels;
|
top = (Uint8 *)surface->pixels;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue