windowscodecs: Ignore the length field of RLE compressed bitmaps.
This commit is contained in:
parent
5fe2fc20fd
commit
4dfcf843aa
|
@ -395,32 +395,52 @@ fail:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT ReadByte(IStream *stream, BYTE *buffer, ULONG buffer_size,
|
||||||
|
ULONG *cursor, ULONG *bytesread, BYTE *result)
|
||||||
|
{
|
||||||
|
HRESULT hr=S_OK;
|
||||||
|
|
||||||
|
if (*bytesread == 0 || *cursor == *bytesread)
|
||||||
|
{
|
||||||
|
hr = IStream_Read(stream, buffer, buffer_size, bytesread);
|
||||||
|
*cursor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (*cursor < *bytesread)
|
||||||
|
*result = buffer[(*cursor)++];
|
||||||
|
else
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
|
static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
|
||||||
{
|
{
|
||||||
UINT bytesperrow;
|
UINT bytesperrow;
|
||||||
UINT width, height;
|
UINT width, height;
|
||||||
BYTE *rledata, *cursor, *rledataend;
|
BYTE rledata[4096];
|
||||||
UINT rlesize, datasize, palettesize;
|
UINT datasize, palettesize;
|
||||||
DWORD palette[256];
|
DWORD palette[256];
|
||||||
UINT x, y;
|
UINT x, y;
|
||||||
DWORD *bgrdata;
|
DWORD *bgrdata;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
LARGE_INTEGER offbits;
|
LARGE_INTEGER offbits;
|
||||||
ULONG bytesread;
|
ULONG cursor=0, bytesread=0;
|
||||||
|
|
||||||
width = This->bih.bV5Width;
|
width = This->bih.bV5Width;
|
||||||
height = abs(This->bih.bV5Height);
|
height = abs(This->bih.bV5Height);
|
||||||
bytesperrow = width * 4;
|
bytesperrow = width * 4;
|
||||||
datasize = bytesperrow * height;
|
datasize = bytesperrow * height;
|
||||||
rlesize = This->bih.bV5SizeImage;
|
|
||||||
if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 256)
|
if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 256)
|
||||||
palettesize = 4 * This->bih.bV5ClrUsed;
|
palettesize = 4 * This->bih.bV5ClrUsed;
|
||||||
else
|
else
|
||||||
palettesize = 4 * 256;
|
palettesize = 4 * 256;
|
||||||
|
|
||||||
rledata = HeapAlloc(GetProcessHeap(), 0, rlesize);
|
|
||||||
This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
|
This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
|
||||||
if (!This->imagedata || !rledata)
|
if (!This->imagedata)
|
||||||
{
|
{
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -439,22 +459,26 @@ static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
|
||||||
hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
|
hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
|
||||||
if (FAILED(hr)) goto fail;
|
if (FAILED(hr)) goto fail;
|
||||||
|
|
||||||
hr = IStream_Read(This->stream, rledata, rlesize, &bytesread);
|
|
||||||
if (FAILED(hr) || bytesread != rlesize) goto fail;
|
|
||||||
|
|
||||||
/* decode RLE */
|
/* decode RLE */
|
||||||
bgrdata = (DWORD*)This->imagedata;
|
bgrdata = (DWORD*)This->imagedata;
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
rledataend = rledata + rlesize;
|
cursor = 0;
|
||||||
cursor = rledata;
|
bytesread = 0;
|
||||||
while (cursor < rledataend && y < height)
|
while (y < height)
|
||||||
{
|
{
|
||||||
BYTE length = *cursor++;
|
BYTE length;
|
||||||
if (length == 0)
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
else if (length == 0)
|
||||||
{
|
{
|
||||||
/* escape code */
|
/* escape code */
|
||||||
BYTE escape = *cursor++;
|
BYTE escape;
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
switch(escape)
|
switch(escape)
|
||||||
{
|
{
|
||||||
case 0: /* end of line */
|
case 0: /* end of line */
|
||||||
|
@ -464,37 +488,53 @@ static HRESULT BmpFrameDecode_ReadRLE8(BmpDecoder* This)
|
||||||
case 1: /* end of bitmap */
|
case 1: /* end of bitmap */
|
||||||
goto end;
|
goto end;
|
||||||
case 2: /* delta */
|
case 2: /* delta */
|
||||||
if (cursor < rledataend)
|
{
|
||||||
{
|
BYTE dx, dy;
|
||||||
x += *cursor++;
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
|
||||||
y += *cursor++;
|
if (SUCCEEDED(hr))
|
||||||
}
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default: /* absolute mode */
|
default: /* absolute mode */
|
||||||
length = escape;
|
length = escape;
|
||||||
while (cursor < rledataend && length-- && x < width)
|
while (length-- && x < width)
|
||||||
bgrdata[y*width + x++] = palette[*cursor++];
|
{
|
||||||
if (escape & 1) cursor++; /* skip pad byte */
|
BYTE index;
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
bgrdata[y*width + x++] = palette[index];
|
||||||
|
}
|
||||||
|
if (escape & 1)
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DWORD color = palette[*cursor++];
|
BYTE index;
|
||||||
|
DWORD color;
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &index);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
color = palette[index];
|
||||||
while (length-- && x < width)
|
while (length-- && x < width)
|
||||||
bgrdata[y*width + x++] = color;
|
bgrdata[y*width + x++] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
HeapFree(GetProcessHeap(), 0, rledata);
|
|
||||||
|
|
||||||
This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
|
This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
|
||||||
This->stride = -bytesperrow;
|
This->stride = -bytesperrow;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
HeapFree(GetProcessHeap(), 0, rledata);
|
|
||||||
HeapFree(GetProcessHeap(), 0, This->imagedata);
|
HeapFree(GetProcessHeap(), 0, This->imagedata);
|
||||||
This->imagedata = NULL;
|
This->imagedata = NULL;
|
||||||
if (SUCCEEDED(hr)) hr = E_FAIL;
|
if (SUCCEEDED(hr)) hr = E_FAIL;
|
||||||
|
@ -505,28 +545,26 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
|
||||||
{
|
{
|
||||||
UINT bytesperrow;
|
UINT bytesperrow;
|
||||||
UINT width, height;
|
UINT width, height;
|
||||||
BYTE *rledata, *cursor, *rledataend;
|
BYTE rledata[4096];
|
||||||
UINT rlesize, datasize, palettesize;
|
UINT datasize, palettesize;
|
||||||
DWORD palette[16];
|
DWORD palette[16];
|
||||||
UINT x, y;
|
UINT x, y;
|
||||||
DWORD *bgrdata;
|
DWORD *bgrdata;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
LARGE_INTEGER offbits;
|
LARGE_INTEGER offbits;
|
||||||
ULONG bytesread;
|
ULONG cursor=0, bytesread=0;
|
||||||
|
|
||||||
width = This->bih.bV5Width;
|
width = This->bih.bV5Width;
|
||||||
height = abs(This->bih.bV5Height);
|
height = abs(This->bih.bV5Height);
|
||||||
bytesperrow = width * 4;
|
bytesperrow = width * 4;
|
||||||
datasize = bytesperrow * height;
|
datasize = bytesperrow * height;
|
||||||
rlesize = This->bih.bV5SizeImage;
|
|
||||||
if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 16)
|
if (This->bih.bV5ClrUsed && This->bih.bV5ClrUsed < 16)
|
||||||
palettesize = 4 * This->bih.bV5ClrUsed;
|
palettesize = 4 * This->bih.bV5ClrUsed;
|
||||||
else
|
else
|
||||||
palettesize = 4 * 16;
|
palettesize = 4 * 16;
|
||||||
|
|
||||||
rledata = HeapAlloc(GetProcessHeap(), 0, rlesize);
|
|
||||||
This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
|
This->imagedata = HeapAlloc(GetProcessHeap(), 0, datasize);
|
||||||
if (!This->imagedata || !rledata)
|
if (!This->imagedata)
|
||||||
{
|
{
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -545,22 +583,26 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
|
||||||
hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
|
hr = IStream_Seek(This->stream, offbits, STREAM_SEEK_SET, NULL);
|
||||||
if (FAILED(hr)) goto fail;
|
if (FAILED(hr)) goto fail;
|
||||||
|
|
||||||
hr = IStream_Read(This->stream, rledata, rlesize, &bytesread);
|
|
||||||
if (FAILED(hr) || bytesread != rlesize) goto fail;
|
|
||||||
|
|
||||||
/* decode RLE */
|
/* decode RLE */
|
||||||
bgrdata = (DWORD*)This->imagedata;
|
bgrdata = (DWORD*)This->imagedata;
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
rledataend = rledata + rlesize;
|
cursor = 0;
|
||||||
cursor = rledata;
|
bytesread = 0;
|
||||||
while (cursor < rledataend && y < height)
|
while (y < height)
|
||||||
{
|
{
|
||||||
BYTE length = *cursor++;
|
BYTE length;
|
||||||
if (length == 0)
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
else if (length == 0)
|
||||||
{
|
{
|
||||||
/* escape code */
|
/* escape code */
|
||||||
BYTE escape = *cursor++;
|
BYTE escape;
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &escape);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
switch(escape)
|
switch(escape)
|
||||||
{
|
{
|
||||||
case 0: /* end of line */
|
case 0: /* end of line */
|
||||||
|
@ -570,31 +612,51 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
|
||||||
case 1: /* end of bitmap */
|
case 1: /* end of bitmap */
|
||||||
goto end;
|
goto end;
|
||||||
case 2: /* delta */
|
case 2: /* delta */
|
||||||
if (cursor < rledataend)
|
{
|
||||||
{
|
BYTE dx, dy;
|
||||||
x += *cursor++;
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dx);
|
||||||
y += *cursor++;
|
if (SUCCEEDED(hr))
|
||||||
}
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &dy);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default: /* absolute mode */
|
default: /* absolute mode */
|
||||||
|
{
|
||||||
|
BYTE realsize=0;
|
||||||
length = escape;
|
length = escape;
|
||||||
while (cursor < rledataend && length-- && x < width)
|
while (length-- && x < width)
|
||||||
{
|
{
|
||||||
BYTE colors = *cursor++;
|
BYTE colors;
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
|
||||||
|
realsize++;
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
bgrdata[y*width + x++] = palette[colors>>4];
|
bgrdata[y*width + x++] = palette[colors>>4];
|
||||||
if (length-- && x < width)
|
if (length-- && x < width)
|
||||||
bgrdata[y*width + x++] = palette[colors&0xf];
|
bgrdata[y*width + x++] = palette[colors&0xf];
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((cursor - rledata) & 1) cursor++; /* skip pad byte */
|
if (realsize & 1)
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &length); /* skip pad byte */
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BYTE colors = *cursor++;
|
BYTE colors;
|
||||||
DWORD color1 = palette[colors>>4];
|
DWORD color1;
|
||||||
DWORD color2 = palette[colors&0xf];
|
DWORD color2;
|
||||||
|
hr = ReadByte(This->stream, rledata, 4096, &cursor, &bytesread, &colors);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto fail;
|
||||||
|
color1 = palette[colors>>4];
|
||||||
|
color2 = palette[colors&0xf];
|
||||||
while (length-- && x < width)
|
while (length-- && x < width)
|
||||||
{
|
{
|
||||||
bgrdata[y*width + x++] = color1;
|
bgrdata[y*width + x++] = color1;
|
||||||
|
@ -607,15 +669,12 @@ static HRESULT BmpFrameDecode_ReadRLE4(BmpDecoder* This)
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
HeapFree(GetProcessHeap(), 0, rledata);
|
|
||||||
|
|
||||||
This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
|
This->imagedatastart = This->imagedata + (height-1) * bytesperrow;
|
||||||
This->stride = -bytesperrow;
|
This->stride = -bytesperrow;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
HeapFree(GetProcessHeap(), 0, rledata);
|
|
||||||
HeapFree(GetProcessHeap(), 0, This->imagedata);
|
HeapFree(GetProcessHeap(), 0, This->imagedata);
|
||||||
This->imagedata = NULL;
|
This->imagedata = NULL;
|
||||||
if (SUCCEEDED(hr)) hr = E_FAIL;
|
if (SUCCEEDED(hr)) hr = E_FAIL;
|
||||||
|
|
Loading…
Reference in New Issue