windowscodecs: Handle TGA attribute bits.
This commit is contained in:
parent
a2e5321b01
commit
6ecb81976f
|
@ -63,6 +63,41 @@ typedef struct {
|
||||||
#define IMAGE_RIGHTTOLEFT 0x10
|
#define IMAGE_RIGHTTOLEFT 0x10
|
||||||
#define IMAGE_TOPTOBOTTOM 0x20
|
#define IMAGE_TOPTOBOTTOM 0x20
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD extension_area_offset;
|
||||||
|
DWORD developer_directory_offset;
|
||||||
|
char magic[18];
|
||||||
|
} tga_footer;
|
||||||
|
|
||||||
|
static const BYTE tga_footer_magic[18] = "TRUEVISION-XFILE.";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
WORD size;
|
||||||
|
char author_name[41];
|
||||||
|
char author_comments[324];
|
||||||
|
WORD timestamp[6];
|
||||||
|
char job_name[41];
|
||||||
|
WORD job_timestamp[6];
|
||||||
|
char software_id[41];
|
||||||
|
WORD software_version;
|
||||||
|
char software_version_letter;
|
||||||
|
DWORD key_color;
|
||||||
|
WORD pixel_width;
|
||||||
|
WORD pixel_height;
|
||||||
|
WORD gamma_numerator;
|
||||||
|
WORD gamma_denominator;
|
||||||
|
DWORD color_correction_offset;
|
||||||
|
DWORD thumbnail_offset;
|
||||||
|
DWORD scanline_offset;
|
||||||
|
BYTE attributes_type;
|
||||||
|
} tga_extension_area;
|
||||||
|
|
||||||
|
#define ATTRIBUTE_NO_ALPHA 0
|
||||||
|
#define ATTRIBUTE_UNDEFINED 1
|
||||||
|
#define ATTRIBUTE_UNDEFINED_PRESERVE 2
|
||||||
|
#define ATTRIBUTE_ALPHA 3
|
||||||
|
#define ATTRIBUTE_PALPHA 4
|
||||||
|
|
||||||
#include "poppack.h"
|
#include "poppack.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -72,6 +107,7 @@ typedef struct {
|
||||||
BOOL initialized;
|
BOOL initialized;
|
||||||
IStream *stream;
|
IStream *stream;
|
||||||
tga_header header;
|
tga_header header;
|
||||||
|
tga_extension_area extension_area;
|
||||||
BYTE *imagebits;
|
BYTE *imagebits;
|
||||||
BYTE *origin;
|
BYTE *origin;
|
||||||
int stride;
|
int stride;
|
||||||
|
@ -79,6 +115,8 @@ typedef struct {
|
||||||
ULONG colormap_length;
|
ULONG colormap_length;
|
||||||
ULONG colormap_offset;
|
ULONG colormap_offset;
|
||||||
ULONG image_offset;
|
ULONG image_offset;
|
||||||
|
ULONG extension_area_offset;
|
||||||
|
ULONG developer_directory_offset;
|
||||||
CRITICAL_SECTION lock;
|
CRITICAL_SECTION lock;
|
||||||
} TgaDecoder;
|
} TgaDecoder;
|
||||||
|
|
||||||
|
@ -153,6 +191,8 @@ static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
|
||||||
HRESULT hr=S_OK;
|
HRESULT hr=S_OK;
|
||||||
DWORD bytesread;
|
DWORD bytesread;
|
||||||
LARGE_INTEGER seek;
|
LARGE_INTEGER seek;
|
||||||
|
tga_footer footer;
|
||||||
|
int attribute_bitcount;
|
||||||
|
|
||||||
TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
|
TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions);
|
||||||
|
|
||||||
|
@ -207,8 +247,15 @@ static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
|
||||||
This->header.depth != 24 && This->header.depth != 32)
|
This->header.depth != 24 && This->header.depth != 32)
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
|
|
||||||
if ((This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK) > 8 ||
|
if ((This->header.image_descriptor & 0xc0) != 0)
|
||||||
(This->header.image_descriptor & 0xc0) != 0)
|
hr = E_FAIL;
|
||||||
|
|
||||||
|
attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
|
||||||
|
|
||||||
|
if (attribute_bitcount &&
|
||||||
|
!((This->header.image_type & IMAGETYPE_TRUECOLOR) &&
|
||||||
|
((This->header.depth == 32 && attribute_bitcount == 8) ||
|
||||||
|
(This->header.depth == 16 && attribute_bitcount == 1))))
|
||||||
hr = E_FAIL;
|
hr = E_FAIL;
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
|
@ -226,7 +273,49 @@ static HRESULT WINAPI TgaDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p
|
||||||
This->colormap_length = 0;
|
This->colormap_length = 0;
|
||||||
This->image_offset = This->colormap_offset + This->colormap_length;
|
This->image_offset = This->colormap_offset + This->colormap_length;
|
||||||
|
|
||||||
/* FIXME: Read footer if there is one. */
|
/* Read footer if there is one */
|
||||||
|
seek.QuadPart = -sizeof(tga_footer);
|
||||||
|
hr = IStream_Seek(pIStream, seek, STREAM_SEEK_END, NULL);
|
||||||
|
if (FAILED(hr)) goto end;
|
||||||
|
|
||||||
|
hr = IStream_Read(pIStream, &footer, sizeof(tga_footer), &bytesread);
|
||||||
|
if (SUCCEEDED(hr) && bytesread != sizeof(tga_footer))
|
||||||
|
{
|
||||||
|
TRACE("got only %u footer bytes\n", bytesread);
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) goto end;
|
||||||
|
|
||||||
|
if (memcmp(footer.magic, tga_footer_magic, sizeof(tga_footer_magic)) == 0)
|
||||||
|
{
|
||||||
|
This->extension_area_offset = footer.extension_area_offset;
|
||||||
|
This->developer_directory_offset = footer.developer_directory_offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
This->extension_area_offset = 0;
|
||||||
|
This->developer_directory_offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->extension_area_offset)
|
||||||
|
{
|
||||||
|
seek.QuadPart = This->extension_area_offset;
|
||||||
|
hr = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL);
|
||||||
|
if (FAILED(hr)) goto end;
|
||||||
|
|
||||||
|
hr = IStream_Read(pIStream, &This->extension_area, sizeof(tga_extension_area), &bytesread);
|
||||||
|
if (SUCCEEDED(hr) && bytesread != sizeof(tga_extension_area))
|
||||||
|
{
|
||||||
|
TRACE("got only %u extension area bytes\n", bytesread);
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
if (SUCCEEDED(hr) && This->extension_area.size < 495)
|
||||||
|
{
|
||||||
|
TRACE("extension area is only %u bytes long\n", This->extension_area.size);
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) goto end;
|
||||||
|
}
|
||||||
|
|
||||||
IStream_AddRef(pIStream);
|
IStream_AddRef(pIStream);
|
||||||
This->stream = pIStream;
|
This->stream = pIStream;
|
||||||
|
@ -379,16 +468,18 @@ static HRESULT WINAPI TgaDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *ifa
|
||||||
{
|
{
|
||||||
TgaDecoder *This = decoder_from_frame(iface);
|
TgaDecoder *This = decoder_from_frame(iface);
|
||||||
int attribute_bitcount;
|
int attribute_bitcount;
|
||||||
|
byte attribute_type;
|
||||||
|
|
||||||
TRACE("(%p,%p)\n", iface, pPixelFormat);
|
TRACE("(%p,%p)\n", iface, pPixelFormat);
|
||||||
|
|
||||||
attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
|
attribute_bitcount = This->header.image_descriptor & IMAGE_ATTRIBUTE_BITCOUNT_MASK;
|
||||||
|
|
||||||
if (attribute_bitcount)
|
if (attribute_bitcount && This->extension_area_offset)
|
||||||
{
|
attribute_type = This->extension_area.attributes_type;
|
||||||
FIXME("Need to read footer to find meaning of attribute bits\n");
|
else if (attribute_bitcount)
|
||||||
return E_NOTIMPL;
|
attribute_type = ATTRIBUTE_ALPHA;
|
||||||
}
|
else
|
||||||
|
attribute_type = ATTRIBUTE_NO_ALPHA;
|
||||||
|
|
||||||
switch (This->header.image_type & ~IMAGETYPE_RLE)
|
switch (This->header.image_type & ~IMAGETYPE_RLE)
|
||||||
{
|
{
|
||||||
|
@ -407,7 +498,21 @@ static HRESULT WINAPI TgaDecoder_Frame_GetPixelFormat(IWICBitmapFrameDecode *ifa
|
||||||
switch (This->header.depth)
|
switch (This->header.depth)
|
||||||
{
|
{
|
||||||
case 16:
|
case 16:
|
||||||
memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGR555, sizeof(GUID));
|
switch (attribute_type)
|
||||||
|
{
|
||||||
|
case ATTRIBUTE_NO_ALPHA:
|
||||||
|
case ATTRIBUTE_UNDEFINED:
|
||||||
|
case ATTRIBUTE_UNDEFINED_PRESERVE:
|
||||||
|
memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGR555, sizeof(GUID));
|
||||||
|
break;
|
||||||
|
case ATTRIBUTE_ALPHA:
|
||||||
|
case ATTRIBUTE_PALPHA:
|
||||||
|
memcpy(pPixelFormat, &GUID_WICPixelFormat16bppBGRA5551, sizeof(GUID));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FIXME("Unhandled 16-bit attribute type %u\n", attribute_type);
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 24:
|
||||||
memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID));
|
memcpy(pPixelFormat, &GUID_WICPixelFormat24bppBGR, sizeof(GUID));
|
||||||
|
|
|
@ -158,6 +158,7 @@ cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppGray, 0x6fddc324,0x4e03,0x4bfe,0x
|
||||||
|
|
||||||
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGR555, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x09);")
|
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGR555, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x09);")
|
||||||
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGR565, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0a);")
|
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGR565, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0a);")
|
||||||
|
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat16bppBGRA5551, 0x05ec7c2b,0xf1e6,0x4961,0xad,0x46,0xe1,0xcc,0x81,0x0a,0x87,0xd2);")
|
||||||
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat24bppBGR, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0c);")
|
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat24bppBGR, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0c);")
|
||||||
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppBGR, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0e);")
|
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppBGR, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0e);")
|
||||||
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppBGRA, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0f);")
|
cpp_quote("DEFINE_GUID(GUID_WICPixelFormat32bppBGRA, 0x6fddc324,0x4e03,0x4bfe,0xb1,0x85,0x3d,0x77,0x76,0x8d,0xc9,0x0f);")
|
||||||
|
|
Loading…
Reference in New Issue