Ignore RLE data that goes past the line end (found by Uwe Bonnes).

General cleanup of the RLE routines.
This commit is contained in:
Alexandre Julliard 2001-10-04 18:16:37 +00:00
parent 76598823d0
commit c8f3fed5cb

View File

@ -67,6 +67,13 @@ typedef struct
} X11DRV_DIB_IMAGEBITS_DESCR; } X11DRV_DIB_IMAGEBITS_DESCR;
enum Rle_EscapeCodes
{
RLE_EOL = 0, /* End of line */
RLE_END = 1, /* End of bitmap */
RLE_DELTA = 2 /* Delta */
};
/*********************************************************************** /***********************************************************************
* X11DRV_DIB_GetXImageWidthBytes * X11DRV_DIB_GetXImageWidthBytes
* *
@ -855,70 +862,44 @@ static void X11DRV_DIB_SetImageBits_RLE4( int lines, const BYTE *bits,
int left, int *colors, int left, int *colors,
XImage *bmpImage ) XImage *bmpImage )
{ {
int x = 0, c, length; int x = 0, y = lines - 1, c, length;
const BYTE *begin = bits; const BYTE *begin = bits;
lines--; while (y >= 0)
{
while ((int)lines >= 0) {
length = *bits++; length = *bits++;
if (length) { /* encoded */ if (length) { /* encoded */
c = *bits++; c = *bits++;
while (length--) { while (length--) {
if(x >= width) { if (x >= width) break;
x = 0; XPutPixel(bmpImage, x++, y, colors[c >> 4]);
if(--lines < 0) if (!length--) break;
return; if (x >= width) break;
} XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
XPutPixel(bmpImage, x++, lines, colors[c >>4]);
if (length) {
length--;
if(x >= width) {
x = 0;
if(--lines < 0)
return;
}
XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
}
} }
} else { } else {
length = *bits++; length = *bits++;
switch (length) { switch (length)
case 0: /* eol */ {
case RLE_EOL:
x = 0; x = 0;
lines--; y--;
continue; break;
case 1: /* eopicture */ case RLE_END:
return; return;
case 2: /* delta */ case RLE_DELTA:
x += *bits++; x += *bits++;
if(x >= width) { y -= *bits++;
FIXME_(x11drv)("x-delta is too large?\n"); break;
return;
}
lines -= *bits++;
continue;
default: /* absolute */ default: /* absolute */
while (length--) { while (length--) {
c = *bits++; c = *bits++;
if(x >= width) { if (x < width) XPutPixel(bmpImage, x++, y, colors[c >> 4]);
x = 0; if (!length--) break;
if(--lines < 0) if (x < width) XPutPixel(bmpImage, x++, y, colors[c & 0xf]);
return;
}
XPutPixel(bmpImage, x++, lines, colors[c >> 4]);
if (length) {
length--;
if(x >= width) {
x = 0;
if(--lines < 0)
return;
}
XPutPixel(bmpImage, x++, lines, colors[c & 0xf]);
}
} }
if ((bits - begin) & 1) if ((bits - begin) & 1)
bits++; bits++;
@ -1272,32 +1253,16 @@ static void X11DRV_DIB_GetImageBits_8( int lines, BYTE *dstbits,
* James A. Youngman <mbcstjy@afs.man.ac.uk> * James A. Youngman <mbcstjy@afs.man.ac.uk>
* [JAY] * [JAY]
*/ */
enum Rle8_EscapeCodes
{
/*
* Apologies for polluting your file's namespace...
*/
RleEol = 0, /* End of line */
RleEnd = 1, /* End of bitmap */
RleDelta = 2 /* Delta */
};
static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits, static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
DWORD width, DWORD dstwidth, DWORD width, DWORD dstwidth,
int left, int *colors, int left, int *colors,
XImage *bmpImage ) XImage *bmpImage )
{ {
int x; /* X-positon on each line. Increases. */ int x; /* X-positon on each line. Increases. */
int line; /* Line #. Starts at lines-1, decreases */ int y; /* Line #. Starts at lines-1, decreases */
const BYTE *pIn = bits; /* Pointer to current position in bits */ const BYTE *pIn = bits; /* Pointer to current position in bits */
BYTE length; /* The length pf a run */ BYTE length; /* The length pf a run */
BYTE color_index; /* index into colors[] as read from bits */
BYTE escape_code; /* See enum Rle8_EscapeCodes.*/ BYTE escape_code; /* See enum Rle8_EscapeCodes.*/
int color; /* value of colour[color_index] */
if (lines == 0) /* Let's hope this doesn't happen. */
return;
/* /*
* Note that the bitmap data is stored by Windows starting at the * Note that the bitmap data is stored by Windows starting at the
@ -1307,8 +1272,8 @@ static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
*/ */
x = 0; x = 0;
line = lines-1; y = lines - 1;
do while (y >= 0)
{ {
length = *pIn++; length = *pIn++;
@ -1325,18 +1290,8 @@ static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
/* /*
* [Run-Length] Encoded mode * [Run-Length] Encoded mode
*/ */
color_index = (*pIn++); /* Get the colour index. */ int color = colors[*pIn++];
color = colors[color_index]; while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
while(length--)
{
if (x>=dstwidth)
{
x=0;
line--;
}
XPutPixel(bmpImage, x++, line, color);
}
} }
else else
{ {
@ -1346,68 +1301,36 @@ static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
escape_code = (*pIn++); escape_code = (*pIn++);
switch(escape_code) switch(escape_code)
{ {
case RleEol: /* =0, end of line */ case RLE_EOL:
{
x = 0; x = 0;
line--; y--;
break; break;
}
case RleEnd: /* =1, end of bitmap */ case RLE_END:
{ /* Not all RLE8 bitmaps end with this code. For
/* * example, Paint Shop Pro produces some that don't.
* Not all RLE8 bitmaps end with this * That's (I think) what caused the previous
* code. For example, Paint Shop Pro * implementation to fail. [JAY]
* produces some that don't. That's (I think)
* what caused the previous implementation to
* fail. [JAY]
*/ */
line=-1; /* Cause exit from do loop. */ return;
break;
}
case RleDelta: /* =2, a delta */ case RLE_DELTA:
{
/*
* Note that deltaing to line 0
* will cause an exit from the loop,
* which may not be what is intended.
* The fact that there is a delta in the bits
* almost certainly implies that there is data
* to follow. You may feel that we should
* jump to the top of the loop to avoid exiting
* in this case.
*
* TODO: Decide what to do here in that case. [JAY]
*/
x += (*pIn++); x += (*pIn++);
line -= (*pIn++); y -= (*pIn++);
if (line == 0)
{
TRACE("Delta to last line of bitmap "
"(wrongly?) causes loop exit\n");
}
break; break;
}
default: /* >2, switch to absolute mode */ default: /* switch to absolute mode */
{
/*
* Absolute Mode
*/
length = escape_code; length = escape_code;
while (length--) while (length--)
{ {
color_index = (*pIn++); int color = colors[*pIn++];
if (x >= dstwidth) if (x >= dstwidth)
{ {
x=0; pIn += length;
line--; break;
} }
XPutPixel(bmpImage, x++, line, XPutPixel(bmpImage, x++, y, color);
colors[color_index]);
} }
/* /*
* If you think for a moment you'll realise that the * If you think for a moment you'll realise that the
* only time we could ever possibly read an odd * only time we could ever possibly read an odd
@ -1417,25 +1340,10 @@ static void X11DRV_DIB_SetImageBits_RLE8( int lines, const BYTE *bits,
* need to worry about it. Everywhere else the * need to worry about it. Everywhere else the
* bytes are always read in pairs. [JAY] * bytes are always read in pairs. [JAY]
*/ */
if (escape_code & 1) if (escape_code & 1) pIn++; /* Throw away the pad byte. */
pIn++; /* Throw away the pad byte. */
break; break;
}
} /* switch (escape_code) : Escape sequence */ } /* switch (escape_code) : Escape sequence */
} /* process either an encoded sequence or an escape sequence */ }
/* We expect to come here more than once per line. */
} while (line >= 0); /* Do this until the bitmap is filled */
/*
* Everybody comes here at the end.
* Check how we exited the loop and print a message if it's a bit odd.
* [JAY]
*/
if ( (*(pIn-2) != 0/*escape*/) || (*(pIn-1)!= RleEnd) )
{
TRACE("End-of-bitmap without (strictly) proper escape code. Last two "
"bytes were: %02X %02X.\n", (int)*(pIn-2),(int)*(pIn-1));
} }
} }