Commit b99abe2e authored by Vincent Povirk's avatar Vincent Povirk Committed by Alexandre Julliard

gdiplus: Use the decoder list to decide how to load image files.

parent 2f0b4bf3
...@@ -1201,10 +1201,9 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage * ...@@ -1201,10 +1201,9 @@ GpStatus WINGDIPAPI GdipLoadImageFromFileICM(GDIPCONST WCHAR* filename,GpImage *
return GdipLoadImageFromFile(filename, image); return GdipLoadImageFromFile(filename, image);
} }
GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image) static GpStatus decode_image_olepicture_icon(IStream* stream, REFCLSID clsid, GpImage **image)
{ {
IPicture *pic; IPicture *pic;
short type;
TRACE("%p %p\n", stream, image); TRACE("%p %p\n", stream, image);
...@@ -1217,14 +1216,34 @@ GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image) ...@@ -1217,14 +1216,34 @@ GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image)
return GenericError; return GenericError;
} }
IPicture_get_Type(pic, &type); *image = GdipAlloc(sizeof(GpImage));
if(!*image) return OutOfMemory;
(*image)->type = ImageTypeUnknown;
(*image)->picture = pic;
(*image)->flags = ImageFlagsNone;
if(type == PICTYPE_BITMAP){ return Ok;
}
static GpStatus decode_image_olepicture_bitmap(IStream* stream, REFCLSID clsid, GpImage **image)
{
IPicture *pic;
BITMAPINFO *pbmi; BITMAPINFO *pbmi;
BITMAPCOREHEADER* bmch; BITMAPCOREHEADER* bmch;
HBITMAP hbm; HBITMAP hbm;
HDC hdc; HDC hdc;
TRACE("%p %p\n", stream, image);
if(!stream || !image)
return InvalidParameter;
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture,
(LPVOID*) &pic) != S_OK){
TRACE("Could not load picture\n");
return GenericError;
}
pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
if (!pbmi) if (!pbmi)
return OutOfMemory; return OutOfMemory;
...@@ -1286,25 +1305,123 @@ GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image) ...@@ -1286,25 +1305,123 @@ GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image)
} }
GdipFree(pbmi); GdipFree(pbmi);
(*image)->picture = pic;
(*image)->flags = ImageFlagsNone;
return Ok;
}
static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, GpImage **image)
{
IPicture *pic;
TRACE("%p %p\n", stream, image);
if(!stream || !image)
return InvalidParameter;
if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture,
(LPVOID*) &pic) != S_OK){
TRACE("Could not load picture\n");
return GenericError;
} }
else if(type == PICTYPE_METAFILE || type == PICTYPE_ENHMETAFILE){
/* FIXME: missing initialization code */ /* FIXME: missing initialization code */
*image = GdipAlloc(sizeof(GpMetafile)); *image = GdipAlloc(sizeof(GpMetafile));
if(!*image) return OutOfMemory; if(!*image) return OutOfMemory;
(*image)->type = ImageTypeMetafile; (*image)->type = ImageTypeMetafile;
}
else{
*image = GdipAlloc(sizeof(GpImage));
if(!*image) return OutOfMemory;
(*image)->type = ImageTypeUnknown;
}
(*image)->picture = pic; (*image)->picture = pic;
(*image)->flags = ImageFlagsNone; (*image)->flags = ImageFlagsNone;
return Ok; return Ok;
} }
typedef GpStatus (*encode_image_func)(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info,
void **output, unsigned int *output_size);
typedef GpStatus (*decode_image_func)(IStream *stream, REFCLSID clsid, GpImage** image);
typedef struct image_codec {
ImageCodecInfo info;
encode_image_func encode_func;
decode_image_func decode_func;
} image_codec;
typedef enum {
BMP,
JPEG,
GIF,
EMF,
WMF,
PNG,
ICO,
NUM_CODECS
} ImageFormat;
static const struct image_codec codecs[NUM_CODECS];
static GpStatus get_decoder_info(IStream* stream, const struct image_codec **result)
{
BYTE signature[8];
LARGE_INTEGER seek;
HRESULT hr;
UINT bytesread;
int i, j;
/* seek to the start of the stream */
seek.QuadPart = 0;
hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
if (FAILED(hr)) return hresult_to_status(hr);
/* read the first 8 bytes */
/* FIXME: This assumes all codecs have one signature <= 8 bytes in length */
hr = IStream_Read(stream, signature, 8, &bytesread);
if (FAILED(hr)) return hresult_to_status(hr);
if (hr == S_FALSE || bytesread == 0) return GenericError;
for (i = 0; i < NUM_CODECS; i++) {
if ((codecs[i].info.Flags & ImageCodecFlagsDecoder) &&
bytesread >= codecs[i].info.SigSize)
{
for (j=0; j<codecs[i].info.SigSize; j++)
if ((signature[j] & codecs[i].info.SigMask[j]) != codecs[i].info.SigPattern[j])
break;
if (j == codecs[i].info.SigSize)
{
*result = &codecs[i];
return Ok;
}
}
}
TRACE("no match for %i byte signature %x %x %x %x %x %x %x %x\n", bytesread,
signature[0],signature[1],signature[2],signature[3],
signature[4],signature[5],signature[6],signature[7]);
return GenericError;
}
GpStatus WINGDIPAPI GdipLoadImageFromStream(IStream* stream, GpImage **image)
{
GpStatus stat;
LARGE_INTEGER seek;
HRESULT hr;
const struct image_codec *codec=NULL;
/* choose an appropriate image decoder */
stat = get_decoder_info(stream, &codec);
if (stat != Ok) return stat;
/* seek to the start of the stream */
seek.QuadPart = 0;
hr = IStream_Seek(stream, seek, STREAM_SEEK_SET, NULL);
if (FAILED(hr)) return hresult_to_status(hr);
/* call on the image decoder to do the real work */
return codec->decode_func(stream, &codec->info.Clsid, image);
}
/* FIXME: no ICM */ /* FIXME: no ICM */
GpStatus WINGDIPAPI GdipLoadImageFromStreamICM(IStream* stream, GpImage **image) GpStatus WINGDIPAPI GdipLoadImageFromStreamICM(IStream* stream, GpImage **image)
{ {
...@@ -1412,27 +1529,6 @@ static GpStatus encode_image_BMP(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info, ...@@ -1412,27 +1529,6 @@ static GpStatus encode_image_BMP(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info,
return Ok; return Ok;
} }
typedef GpStatus (*encode_image_func)(LPVOID bitmap_bits, LPBITMAPINFO bitmap_info,
void **output, unsigned int *output_size);
typedef struct image_codec {
ImageCodecInfo info;
encode_image_func encode_func;
} image_codec;
typedef enum {
BMP,
JPEG,
GIF,
EMF,
WMF,
PNG,
ICO,
NUM_CODECS
} ImageFormat;
static const struct image_codec codecs[NUM_CODECS];
/***************************************************************************** /*****************************************************************************
* GdipSaveImageToStream [GDIPLUS.@] * GdipSaveImageToStream [GDIPLUS.@]
*/ */
...@@ -1626,7 +1722,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1626,7 +1722,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ bmp_sig_pattern, /* SigPattern */ bmp_sig_pattern,
/* SigMask */ bmp_sig_mask, /* SigMask */ bmp_sig_mask,
}, },
encode_image_BMP encode_image_BMP,
decode_image_olepicture_bitmap
}, },
{ {
{ /* JPEG */ { /* JPEG */
...@@ -1644,7 +1741,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1644,7 +1741,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ jpeg_sig_pattern, /* SigPattern */ jpeg_sig_pattern,
/* SigMask */ jpeg_sig_mask, /* SigMask */ jpeg_sig_mask,
}, },
NULL NULL,
decode_image_olepicture_bitmap
}, },
{ {
{ /* GIF */ { /* GIF */
...@@ -1662,7 +1760,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1662,7 +1760,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ gif_sig_pattern, /* SigPattern */ gif_sig_pattern,
/* SigMask */ gif_sig_mask, /* SigMask */ gif_sig_mask,
}, },
NULL NULL,
decode_image_olepicture_bitmap
}, },
{ {
{ /* EMF */ { /* EMF */
...@@ -1680,7 +1779,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1680,7 +1779,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ emf_sig_pattern, /* SigPattern */ emf_sig_pattern,
/* SigMask */ emf_sig_mask, /* SigMask */ emf_sig_mask,
}, },
NULL NULL,
decode_image_olepicture_metafile
}, },
{ {
{ /* WMF */ { /* WMF */
...@@ -1698,7 +1798,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1698,7 +1798,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ wmf_sig_pattern, /* SigPattern */ wmf_sig_pattern,
/* SigMask */ wmf_sig_mask, /* SigMask */ wmf_sig_mask,
}, },
NULL NULL,
decode_image_olepicture_metafile
}, },
{ {
{ /* PNG */ { /* PNG */
...@@ -1716,7 +1817,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1716,7 +1817,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ png_sig_pattern, /* SigPattern */ png_sig_pattern,
/* SigMask */ png_sig_mask, /* SigMask */ png_sig_mask,
}, },
NULL NULL,
decode_image_olepicture_bitmap
}, },
{ {
{ /* ICO */ { /* ICO */
...@@ -1734,7 +1836,8 @@ static const struct image_codec codecs[NUM_CODECS] = { ...@@ -1734,7 +1836,8 @@ static const struct image_codec codecs[NUM_CODECS] = {
/* SigPattern */ ico_sig_pattern, /* SigPattern */ ico_sig_pattern,
/* SigMask */ ico_sig_mask, /* SigMask */ ico_sig_mask,
}, },
NULL NULL,
decode_image_olepicture_icon
}, },
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment