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 */ {
x = 0; case RLE_EOL:
lines--; x = 0;
continue; y--;
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,172 +1253,99 @@ 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
* bottom line of the bitmap and going upwards. Within each line, * bottom line of the bitmap and going upwards. Within each line,
* the data is stored left-to-right. That's the reason why line * the data is stored left-to-right. That's the reason why line
* goes from lines-1 to 0. [JAY] * goes from lines-1 to 0. [JAY]
*/ */
x = 0;
line = lines-1;
do
{
length = *pIn++;
/*
* If the length byte is not zero (which is the escape value),
* We have a run of length pixels all the same colour. The colour
* index is stored next.
*
* If the length byte is zero, we need to read the next byte to
* know what to do. [JAY]
*/
if (length != 0)
{
/*
* [Run-Length] Encoded mode
*/
color_index = (*pIn++); /* Get the colour index. */
color = colors[color_index];
while(length--) x = 0;
{ y = lines - 1;
if (x>=dstwidth) while (y >= 0)
{ {
x=0; length = *pIn++;
line--;
} /*
XPutPixel(bmpImage, x++, line, color); * If the length byte is not zero (which is the escape value),
} * We have a run of length pixels all the same colour. The colour
} * index is stored next.
else *
{ * If the length byte is zero, we need to read the next byte to
/* * know what to do. [JAY]
* Escape codes (may be an absolute sequence though) */
*/ if (length != 0)
escape_code = (*pIn++); {
switch(escape_code) /*
{ * [Run-Length] Encoded mode
case RleEol: /* =0, end of line */ */
{ int color = colors[*pIn++];
x = 0; while (length-- && x < dstwidth) XPutPixel(bmpImage, x++, y, color);
line--; }
break; else
} {
/*
case RleEnd: /* =1, end of bitmap */ * Escape codes (may be an absolute sequence though)
{ */
/* escape_code = (*pIn++);
* Not all RLE8 bitmaps end with this switch(escape_code)
* code. For example, Paint Shop Pro {
* produces some that don't. That's (I think) case RLE_EOL:
* what caused the previous implementation to x = 0;
* fail. [JAY] y--;
*/ break;
line=-1; /* Cause exit from do loop. */
break; case RLE_END:
} /* Not all RLE8 bitmaps end with this code. For
* example, Paint Shop Pro produces some that don't.
case RleDelta: /* =2, a delta */ * That's (I think) what caused the previous
{ * implementation to fail. [JAY]
/* */
* Note that deltaing to line 0 return;
* will cause an exit from the loop,
* which may not be what is intended. case RLE_DELTA:
* The fact that there is a delta in the bits x += (*pIn++);
* almost certainly implies that there is data y -= (*pIn++);
* to follow. You may feel that we should break;
* jump to the top of the loop to avoid exiting
* in this case. default: /* switch to absolute mode */
* length = escape_code;
* TODO: Decide what to do here in that case. [JAY] while (length--)
*/ {
x += (*pIn++); int color = colors[*pIn++];
line -= (*pIn++); if (x >= dstwidth)
if (line == 0) {
{ pIn += length;
TRACE("Delta to last line of bitmap " break;
"(wrongly?) causes loop exit\n"); }
} XPutPixel(bmpImage, x++, y, color);
break; }
} /*
* If you think for a moment you'll realise that the
default: /* >2, switch to absolute mode */ * only time we could ever possibly read an odd
{ * number of bytes is when there is a 0x00 (escape),
/* * a value >0x02 (absolute mode) and then an odd-
* Absolute Mode * length run. Therefore this is the only place we
*/ * need to worry about it. Everywhere else the
length = escape_code; * bytes are always read in pairs. [JAY]
while(length--) */
{ if (escape_code & 1) pIn++; /* Throw away the pad byte. */
color_index = (*pIn++); break;
if (x>=dstwidth) } /* switch (escape_code) : Escape sequence */
{ }
x=0; }
line--; }
}
XPutPixel(bmpImage, x++, line,
colors[color_index]);
}
/*
* If you think for a moment you'll realise that the
* only time we could ever possibly read an odd
* number of bytes is when there is a 0x00 (escape),
* a value >0x02 (absolute mode) and then an odd-
* length run. Therefore this is the only place we
* need to worry about it. Everywhere else the
* bytes are always read in pairs. [JAY]
*/
if (escape_code & 1)
pIn++; /* Throw away the pad byte. */
break;
}
} /* 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));
}
}
/*********************************************************************** /***********************************************************************