https://git.reactos.org/?p=reactos.git;a=commitdiff;h=50774f865c4f9d9b926f3…
commit 50774f865c4f9d9b926f32a8bcfc20bbeced8fb5
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Mon Jul 31 07:22:38 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Mon Jul 31 07:22:38 2023 +0900
[ATL] CImage: Respect CODEC info (#5408)
Add _getAllEncoders and _getAllDecoders helper functions and use them
in GetImporterFilterString, GetExporterFilterString, FileTypeFromExtension
and GetClsidFromFileType functions.
CORE-18867, CORE-19008
---
sdk/lib/atl/atlimage.h | 490 +++++++++++++++++++++++++++----------------------
1 file changed, 266 insertions(+), 224 deletions(-)
diff --git a/sdk/lib/atl/atlimage.h b/sdk/lib/atl/atlimage.h
index 9765b0e70d5..236defea834 100644
--- a/sdk/lib/atl/atlimage.h
+++ b/sdk/lib/atl/atlimage.h
@@ -387,14 +387,10 @@ public:
return E_FAIL;
}
- // TODO & FIXME: get parameters (m_rgbTransColor etc.)
-
// get bitmap handle
HBITMAP hbm = NULL;
Color color(0xFF, 0xFF, 0xFF);
- Gdiplus::Status status;
- status = GetCommon().CreateHBITMAPFromBitmap(
- pBitmap, &hbm, color.GetValue());
+ Status status = GetCommon().CreateHBITMAPFromBitmap(pBitmap, &hbm,
color.GetValue());
// delete GpBitmap
GetCommon().DisposeImage(pBitmap);
@@ -414,14 +410,10 @@ public:
return E_FAIL;
}
- // TODO & FIXME: get parameters (m_rgbTransColor etc.)
-
// get bitmap handle
HBITMAP hbm = NULL;
Color color(0xFF, 0xFF, 0xFF);
- Gdiplus::Status status;
- status = GetCommon().CreateHBITMAPFromBitmap(
- pBitmap, &hbm, color.GetValue());
+ Status status = GetCommon().CreateHBITMAPFromBitmap(pBitmap, &hbm,
color.GetValue());
// delete Bitmap
GetCommon().DisposeImage(pBitmap);
@@ -525,10 +517,13 @@ public:
using namespace Gdiplus;
ATLASSERT(m_hbm);
- // TODO & FIXME: set parameters (m_rgbTransColor etc.)
- CLSID clsid;
- if (!GetClsidFromFileType(&clsid, guidFileType))
- return E_FAIL;
+ // Get encoders
+ UINT cEncoders = 0;
+ ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
+
+ // Get Codec
+ CLSID clsid = FindCodecForFileType(*guidFileType, pEncoders, cEncoders);
+ delete[] pEncoders;
// create a GpBitmap from HBITMAP
GpBitmap *pBitmap = NULL;
@@ -550,31 +545,32 @@ public:
using namespace Gdiplus;
ATLASSERT(m_hbm);
- // TODO & FIXME: set parameters (m_rgbTransColor etc.)
-
// convert the file name string into Unicode
CStringW pszNameW(pszFileName);
+ // Get encoders
+ UINT cEncoders = 0;
+ ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
+
// if the file type is null, get the file type from extension
- const GUID *FileType = &guidFileType;
+ CLSID clsid;
if (::IsEqualGUID(guidFileType, GUID_NULL))
{
- LPCWSTR pszExt = GetFileExtension(pszNameW);
- FileType = FileTypeFromExtension(pszExt);
+ CString strExt(GetFileExtension(pszNameW));
+ clsid = FindCodecForExtension(strExt, pEncoders, cEncoders);
}
-
- // get CLSID from file type
- CLSID clsid;
- if (!GetClsidFromFileType(&clsid, FileType))
- return E_FAIL;
+ else
+ {
+ clsid = FindCodecForFileType(guidFileType, pEncoders, cEncoders);
+ }
+ delete[] pEncoders;
// create a GpBitmap from HBITMAP
GpBitmap *pBitmap = NULL;
GetCommon().CreateBitmapFromHBITMAP(m_hbm, NULL, &pBitmap);
// save to file
- Status status;
- status = GetCommon().SaveImageToFile(pBitmap, pszNameW, &clsid, NULL);
+ Status status = GetCommon().SaveImageToFile(pBitmap, pszNameW, &clsid,
NULL);
// destroy GpBitmap
GetCommon().DisposeImage(pBitmap);
@@ -714,73 +710,96 @@ public:
excludeDefaultSave = excludeIcon | excludeEMF | excludeWMF
};
- struct FILTER_DATA {
- DWORD dwExclude;
- const TCHAR *title;
- const TCHAR *extensions;
- const GUID *guid;
- };
-
protected:
- static HRESULT GetCommonFilterString(
+ static bool ShouldExcludeFormat(REFGUID guidFileType, DWORD dwExclude)
+ {
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatGIF))
+ return !!(dwExclude & excludeGIF);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatBMP))
+ return !!(dwExclude & excludeBMP);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatEMF))
+ return !!(dwExclude & excludeEMF);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatWMF))
+ return !!(dwExclude & excludeWMF);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatJPEG))
+ return !!(dwExclude & excludeJPEG);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatPNG))
+ return !!(dwExclude & excludePNG);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatTIFF))
+ return !!(dwExclude & excludeTIFF);
+ if (::IsEqualGUID(guidFileType, Gdiplus::ImageFormatIcon))
+ return !!(dwExclude & excludeIcon);
+ return ((dwExclude & excludeOther) == excludeOther);
+ }
+
+ static HRESULT BuildCodecFilterString(
+ const Gdiplus::ImageCodecInfo* pCodecs,
+ UINT cCodecs,
CSimpleString& strFilter,
CSimpleArray<GUID>& aguidFileTypes,
LPCTSTR pszAllFilesDescription,
DWORD dwExclude,
TCHAR chSeparator)
{
- static const FILTER_DATA table[] =
+ if (!pCodecs || !cCodecs)
{
- {excludeBMP, TEXT("BMP"), TEXT("*.BMP;*.DIB;*.RLE"),
&Gdiplus::ImageFormatBMP},
- {excludeJPEG, TEXT("JPEG"),
TEXT("*.JPG;*.JPEG;*.JPE;*.JFIF"), &Gdiplus::ImageFormatJPEG},
- {excludeGIF, TEXT("GIF"), TEXT("*.GIF"),
&Gdiplus::ImageFormatGIF},
- {excludeEMF, TEXT("EMF"), TEXT("*.EMF"),
&Gdiplus::ImageFormatEMF},
- {excludeWMF, TEXT("WMF"), TEXT("*.WMF"),
&Gdiplus::ImageFormatWMF},
- {excludeTIFF, TEXT("TIFF"), TEXT("*.TIF;*.TIFF"),
&Gdiplus::ImageFormatTIFF},
- {excludePNG, TEXT("PNG"), TEXT("*.PNG"),
&Gdiplus::ImageFormatPNG},
- {excludeIcon, TEXT("ICO"), TEXT("*.ICO"),
&Gdiplus::ImageFormatIcon}
- };
+ strFilter += chSeparator;
+ return E_FAIL;
+ }
if (pszAllFilesDescription)
{
strFilter += pszAllFilesDescription;
- strFilter += chSeparator;
BOOL bFirst = TRUE;
- for (size_t i = 0; i < _countof(table); ++i)
+ CString extensions;
+ for (UINT i = 0; i < cCodecs; ++i)
{
- if ((dwExclude & table[i].dwExclude) != 0)
+ if (ShouldExcludeFormat(pCodecs[i].FormatID, dwExclude))
continue;
if (bFirst)
bFirst = FALSE;
else
- strFilter += TEXT(';');
+ extensions += TEXT(';');
- strFilter += table[i].extensions;
+ CString ext(pCodecs[i].FilenameExtension);
+ extensions += ext;
}
+ extensions.MakeLower();
+
+ strFilter += TEXT(" (");
+ strFilter += extensions;
+ strFilter += TEXT(")");
+ strFilter += chSeparator;
+
+ strFilter += extensions;
strFilter += chSeparator;
aguidFileTypes.Add(GUID_NULL);
}
- for (size_t i = 0; i < _countof(table); ++i)
+ for (UINT i = 0; i < cCodecs; ++i)
{
- if ((dwExclude & table[i].dwExclude) != 0)
+ if (ShouldExcludeFormat(pCodecs[i].FormatID, dwExclude))
continue;
- strFilter += table[i].title;
+
+ CString extensions(pCodecs[i].FilenameExtension);
+ extensions.MakeLower();
+
+ CString desc(pCodecs[i].FormatDescription);
+ strFilter += desc;
strFilter += TEXT(" (");
- strFilter += table[i].extensions;
+ strFilter += extensions;
strFilter += TEXT(")");
strFilter += chSeparator;
- strFilter += table[i].extensions;
+ strFilter += extensions;
strFilter += chSeparator;
- aguidFileTypes.Add(*table[i].guid);
+ aguidFileTypes.Add(pCodecs[i].FormatID);
}
strFilter += chSeparator;
-
return S_OK;
}
@@ -792,11 +811,17 @@ public:
DWORD dwExclude = excludeDefaultLoad,
TCHAR chSeparator = TEXT('|'))
{
- return GetCommonFilterString(strImporters,
- aguidFileTypes,
- pszAllFilesDescription,
- dwExclude,
- chSeparator);
+ UINT cDecoders = 0;
+ Gdiplus::ImageCodecInfo* pDecoders = _getAllDecoders(cDecoders);
+ HRESULT hr = BuildCodecFilterString(pDecoders,
+ cDecoders,
+ strImporters,
+ aguidFileTypes,
+ pszAllFilesDescription,
+ dwExclude,
+ chSeparator);
+ delete[] pDecoders;
+ return hr;
}
static HRESULT GetExporterFilterString(
@@ -806,30 +831,27 @@ public:
DWORD dwExclude = excludeDefaultSave,
TCHAR chSeparator = TEXT('|'))
{
- return GetCommonFilterString(strExporters,
- aguidFileTypes,
- pszAllFilesDescription,
- dwExclude,
- chSeparator);
+ UINT cEncoders = 0;
+ Gdiplus::ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
+ HRESULT hr = BuildCodecFilterString(pEncoders,
+ cEncoders,
+ strExporters,
+ aguidFileTypes,
+ pszAllFilesDescription,
+ dwExclude,
+ chSeparator);
+ delete[] pEncoders;
+ return hr;
}
protected:
// an extension of BITMAPINFO
- struct MYBITMAPINFOEX
+ struct MYBITMAPINFOEX : BITMAPINFO
{
- BITMAPINFOHEADER bmiHeader;
- RGBQUAD bmiColors[256];
- BITMAPINFO *get()
- {
- return reinterpret_cast<BITMAPINFO *>(this);
- }
- const BITMAPINFO *get() const
- {
- return reinterpret_cast<const BITMAPINFO *>(this);
- }
+ RGBQUAD bmiColorsExtra[256 - 1];
};
- // abbreviations of GDI+ basic types
+ // abbreviations of GDI+ basic types. FIXME: Delete us
typedef Gdiplus::GpStatus St;
typedef Gdiplus::GpBitmap Bm;
typedef Gdiplus::GpImage Im;
@@ -837,69 +859,45 @@ protected:
// The common data of atlimage
struct COMMON
{
- // abbreviations of GDI+ basic types
- typedef Gdiplus::ImageCodecInfo ICI;
- typedef Gdiplus::EncoderParameters EncParams;
- typedef Gdiplus::ARGB ARGB;
- typedef HBITMAP HBM;
- typedef Gdiplus::GdiplusStartupInput GSI;
- typedef Gdiplus::GdiplusStartupOutput GSO;
-
// GDI+ function types
-#undef API
-#undef CST
-#define API WINGDIPAPI
-#define CST GDIPCONST
- typedef St (WINAPI *STARTUP)(ULONG_PTR *, const GSI *, GSO *);
- typedef void (WINAPI *SHUTDOWN)(ULONG_PTR);
- typedef St (API *GETIMAGEENCODERSSIZE)(UINT *, UINT *);
- typedef St (API *GETIMAGEENCODERS)(UINT, UINT, ICI *);
- typedef St (API *CREATEBITMAPFROMFILE)(CST WCHAR*, Bm **);
- typedef St (API *CREATEHBITMAPFROMBITMAP)(Bm *, HBM *, ARGB);
- typedef St (API *CREATEBITMAPFROMSTREAM)(IStream *, Bm **);
- typedef St (API *CREATEBITMAPFROMHBITMAP)(HBM, HPALETTE, Bm **);
- typedef St (API *SAVEIMAGETOSTREAM)(Im *, IStream *, CST CLSID *,
- CST EncParams *);
- typedef St (API *SAVEIMAGETOFILE)(Im *, CST WCHAR *, CST CLSID *,
- CST EncParams *);
- typedef St (API *DISPOSEIMAGE)(Im*);
-#undef API
-#undef CST
+ using FUN_Startup = decltype(&Gdiplus::GdiplusStartup);
+ using FUN_Shutdown = decltype(&Gdiplus::GdiplusShutdown);
+ using FUN_GetImageEncoderSize =
decltype(&Gdiplus::DllExports::GdipGetImageEncodersSize);
+ using FUN_GetImageEncoder =
decltype(&Gdiplus::DllExports::GdipGetImageEncoders);
+ using FUN_GetImageDecoderSize =
decltype(&Gdiplus::DllExports::GdipGetImageDecodersSize);
+ using FUN_GetImageDecoder =
decltype(&Gdiplus::DllExports::GdipGetImageDecoders);
+ using FUN_CreateBitmapFromFile =
decltype(&Gdiplus::DllExports::GdipCreateBitmapFromFile);
+ using FUN_CreateHBITMAPFromBitmap =
decltype(&Gdiplus::DllExports::GdipCreateHBITMAPFromBitmap);
+ using FUN_CreateBitmapFromStream =
decltype(&Gdiplus::DllExports::GdipCreateBitmapFromStream);
+ using FUN_CreateBitmapFromHBITMAP =
decltype(&Gdiplus::DllExports::GdipCreateBitmapFromHBITMAP);
+ using FUN_SaveImageToStream =
decltype(&Gdiplus::DllExports::GdipSaveImageToStream);
+ using FUN_SaveImageToFile =
decltype(&Gdiplus::DllExports::GdipSaveImageToFile);
+ using FUN_DisposeImage = decltype(&Gdiplus::DllExports::GdipDisposeImage);
// members
- int count;
- HINSTANCE hinstGdiPlus;
- ULONG_PTR gdiplusToken;
+ int count = 0;
+ HINSTANCE hinstGdiPlus = NULL;
+ ULONG_PTR gdiplusToken = 0;
// GDI+ functions
- STARTUP Startup;
- SHUTDOWN Shutdown;
- GETIMAGEENCODERSSIZE GetImageEncodersSize;
- GETIMAGEENCODERS GetImageEncoders;
- CREATEBITMAPFROMFILE CreateBitmapFromFile;
- CREATEHBITMAPFROMBITMAP CreateHBITMAPFromBitmap;
- CREATEBITMAPFROMSTREAM CreateBitmapFromStream;
- CREATEBITMAPFROMHBITMAP CreateBitmapFromHBITMAP;
- SAVEIMAGETOSTREAM SaveImageToStream;
- SAVEIMAGETOFILE SaveImageToFile;
- DISPOSEIMAGE DisposeImage;
+ FUN_Startup Startup = NULL;
+ FUN_Shutdown Shutdown = NULL;
+ FUN_GetImageEncoderSize GetImageEncodersSize = NULL;
+ FUN_GetImageEncoder GetImageEncoders = NULL;
+ FUN_GetImageDecoderSize GetImageDecodersSize = NULL;
+ FUN_GetImageDecoder GetImageDecoders = NULL;
+ FUN_CreateBitmapFromFile CreateBitmapFromFile = NULL;
+ FUN_CreateHBITMAPFromBitmap CreateHBITMAPFromBitmap = NULL;
+ FUN_CreateBitmapFromStream CreateBitmapFromStream = NULL;
+ FUN_CreateBitmapFromHBITMAP CreateBitmapFromHBITMAP = NULL;
+ FUN_SaveImageToStream SaveImageToStream = NULL;
+ FUN_SaveImageToFile SaveImageToFile = NULL;
+ FUN_DisposeImage DisposeImage = NULL;
COMMON()
{
- count = 0;
- hinstGdiPlus = NULL;
- Startup = NULL;
- Shutdown = NULL;
- GetImageEncodersSize = NULL;
- GetImageEncoders = NULL;
- CreateBitmapFromFile = NULL;
- CreateHBITMAPFromBitmap = NULL;
- CreateBitmapFromStream = NULL;
- CreateBitmapFromHBITMAP = NULL;
- SaveImageToStream = NULL;
- SaveImageToFile = NULL;
- DisposeImage = NULL;
}
+
~COMMON()
{
FreeLib();
@@ -915,11 +913,13 @@ protected:
}
// get procedure address of the DLL
- template <typename TYPE>
- TYPE AddrOf(const char *name)
+ template <typename FUN_T>
+ FUN_T _getFUN(FUN_T& fun, const char *name)
{
- FARPROC proc = ::GetProcAddress(hinstGdiPlus, name);
- return reinterpret_cast<TYPE>(proc);
+ if (fun)
+ return fun;
+ fun = reinterpret_cast<FUN_T>(::GetProcAddress(hinstGdiPlus, name));
+ return fun;
}
HINSTANCE LoadLib()
@@ -929,24 +929,19 @@ protected:
hinstGdiPlus = ::LoadLibraryA("gdiplus.dll");
- // get procedure addresses from the DLL
- Startup = AddrOf<STARTUP>("GdiplusStartup");
- Shutdown = AddrOf<SHUTDOWN>("GdiplusShutdown");
- GetImageEncodersSize =
-
AddrOf<GETIMAGEENCODERSSIZE>("GdipGetImageEncodersSize");
- GetImageEncoders =
AddrOf<GETIMAGEENCODERS>("GdipGetImageEncoders");
- CreateBitmapFromFile =
-
AddrOf<CREATEBITMAPFROMFILE>("GdipCreateBitmapFromFile");
- CreateHBITMAPFromBitmap =
-
AddrOf<CREATEHBITMAPFROMBITMAP>("GdipCreateHBITMAPFromBitmap");
- CreateBitmapFromStream =
-
AddrOf<CREATEBITMAPFROMSTREAM>("GdipCreateBitmapFromStream");
- CreateBitmapFromHBITMAP =
-
AddrOf<CREATEBITMAPFROMHBITMAP>("GdipCreateBitmapFromHBITMAP");
- SaveImageToStream =
- AddrOf<SAVEIMAGETOSTREAM>("GdipSaveImageToStream");
- SaveImageToFile =
AddrOf<SAVEIMAGETOFILE>("GdipSaveImageToFile");
- DisposeImage = AddrOf<DISPOSEIMAGE>("GdipDisposeImage");
+ _getFUN(Startup, "GdiplusStartup");
+ _getFUN(Shutdown, "GdiplusShutdown");
+ _getFUN(GetImageEncodersSize, "GdipGetImageEncodersSize");
+ _getFUN(GetImageEncoders, "GdipGetImageEncoders");
+ _getFUN(GetImageDecodersSize, "GdipGetImageDecodersSize");
+ _getFUN(GetImageDecoders, "GdipGetImageDecoders");
+ _getFUN(CreateBitmapFromFile, "GdipCreateBitmapFromFile");
+ _getFUN(CreateHBITMAPFromBitmap, "GdipCreateHBITMAPFromBitmap");
+ _getFUN(CreateBitmapFromStream, "GdipCreateBitmapFromStream");
+ _getFUN(CreateBitmapFromHBITMAP, "GdipCreateBitmapFromHBITMAP");
+ _getFUN(SaveImageToStream, "GdipSaveImageToStream");
+ _getFUN(SaveImageToFile, "GdipSaveImageToFile");
+ _getFUN(DisposeImage, "GdipDisposeImage");
if (hinstGdiPlus && Startup)
{
@@ -966,6 +961,8 @@ protected:
Shutdown = NULL;
GetImageEncodersSize = NULL;
GetImageEncoders = NULL;
+ GetImageDecodersSize = NULL;
+ GetImageDecoders = NULL;
CreateBitmapFromFile = NULL;
CreateHBITMAPFromBitmap = NULL;
CreateBitmapFromStream = NULL;
@@ -1024,96 +1021,143 @@ protected:
return RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
}
- struct EXTENSION_ENTRY
+ static CLSID
+ FindCodecForExtension(LPCTSTR dotext, const Gdiplus::ImageCodecInfo *pCodecs, UINT
nCodecs)
{
- LPCWSTR pszExt;
- GUID guid;
- };
-
- const GUID *FileTypeFromExtension(LPCWSTR pszExt) const
- {
- static const EXTENSION_ENTRY table[] =
- {
- {L".jpg", Gdiplus::ImageFormatJPEG},
- {L".png", Gdiplus::ImageFormatPNG},
- {L".bmp", Gdiplus::ImageFormatBMP},
- {L".gif", Gdiplus::ImageFormatGIF},
- {L".tif", Gdiplus::ImageFormatTIFF},
- {L".jpeg", Gdiplus::ImageFormatJPEG},
- {L".jpe", Gdiplus::ImageFormatJPEG},
- {L".jfif", Gdiplus::ImageFormatJPEG},
- {L".dib", Gdiplus::ImageFormatBMP},
- {L".rle", Gdiplus::ImageFormatBMP},
- {L".tiff", Gdiplus::ImageFormatTIFF}
- };
- const size_t count = _countof(table);
- for (size_t i = 0; i < count; ++i)
+ for (UINT i = 0; i < nCodecs; ++i)
{
- if (::lstrcmpiW(table[i].pszExt, pszExt) == 0)
- return &table[i].guid;
+ CString strSpecs(pCodecs[i].FilenameExtension);
+ int ichOld = 0, ichSep;
+ for (;;)
+ {
+ ichSep = strSpecs.Find(TEXT(';'), ichOld);
+
+ CString strSpec;
+ if (ichSep < 0)
+ strSpec = strSpecs.Mid(ichOld);
+ else
+ strSpec = strSpecs.Mid(ichOld, ichSep - ichOld);
+
+ int ichDot = strSpec.ReverseFind(TEXT('.'));
+ if (ichDot >= 0)
+ strSpec = strSpec.Mid(ichDot);
+
+ if (!dotext || strSpec.CompareNoCase(dotext) == 0)
+ return pCodecs[i].Clsid;
+
+ if (ichSep < 0)
+ break;
+
+ ichOld = ichSep + 1;
+ }
}
- return NULL;
+ return CLSID_NULL;
}
- struct FORMAT_ENTRY
+ // Deprecated. Don't use this
+ static const GUID *FileTypeFromExtension(LPCTSTR dotext)
{
- GUID guid;
- LPCWSTR mime;
- };
+ UINT cEncoders = 0;
+ Gdiplus::ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
- bool GetClsidFromFileType(CLSID *clsid, const GUID *guid) const
- {
- static const FORMAT_ENTRY table[] =
- {
- {Gdiplus::ImageFormatJPEG, L"image/jpeg"},
- {Gdiplus::ImageFormatPNG, L"image/png"},
- {Gdiplus::ImageFormatBMP, L"image/bmp"},
- {Gdiplus::ImageFormatGIF, L"image/gif"},
- {Gdiplus::ImageFormatTIFF, L"image/tiff"}
- };
- const size_t count = _countof(table);
- for (size_t i = 0; i < count; ++i)
+ for (UINT i = 0; i < cEncoders; ++i)
{
- if (::IsEqualGUID(table[i].guid, *guid))
+ CString strSpecs(pEncoders[i].FilenameExtension);
+ int ichOld = 0, ichSep;
+ for (;;)
{
- int num = GetEncoderClsid(table[i].mime, clsid);
- if (num >= 0)
+ ichSep = strSpecs.Find(TEXT(';'), ichOld);
+
+ CString strSpec;
+ if (ichSep < 0)
+ strSpec = strSpecs.Mid(ichOld);
+ else
+ strSpec = strSpecs.Mid(ichOld, ichSep - ichOld);
+
+ int ichDot = strSpec.ReverseFind(TEXT('.'));
+ if (ichDot >= 0)
+ strSpec = strSpec.Mid(ichDot);
+
+ if (!dotext || strSpec.CompareNoCase(dotext) == 0)
{
- return true;
+ static GUID s_guid;
+ s_guid = pEncoders[i].FormatID;
+ delete[] pEncoders;
+ return &s_guid;
}
+
+ if (ichSep < 0)
+ break;
+
+ ichOld = ichSep + 1;
}
}
- return false;
+
+ delete[] pEncoders;
+ return NULL;
+ }
+
+ static CLSID
+ FindCodecForFileType(REFGUID guidFileType, const Gdiplus::ImageCodecInfo *pCodecs,
UINT nCodecs)
+ {
+ for (UINT iInfo = 0; iInfo < nCodecs; ++iInfo)
+ {
+ if (::IsEqualGUID(pCodecs[iInfo].FormatID, guidFileType))
+ return pCodecs[iInfo].Clsid;
+ }
+ return CLSID_NULL;
}
- int GetEncoderClsid(LPCWSTR mime, CLSID *clsid) const
+ // Deprecated. Don't use this
+ static bool GetClsidFromFileType(CLSID *clsid, const GUID *guid)
{
- UINT count = 0, total_size = 0;
- GetCommon().GetImageEncodersSize(&count, &total_size);
+ UINT cEncoders = 0;
+ Gdiplus::ImageCodecInfo* pEncoders = _getAllEncoders(cEncoders);
+ *clsid = FindCodecForFileType(*guid, pEncoders, cEncoders);
+ delete[] pEncoders;
+ return true;
+ }
+
+ static Gdiplus::ImageCodecInfo* _getAllEncoders(UINT& cEncoders)
+ {
+ CImage image; // Initialize common
+
+ UINT total_size = 0;
+ GetCommon().GetImageEncodersSize(&cEncoders, &total_size);
if (total_size == 0)
- return -1; // failure
+ return NULL; // failure
- Gdiplus::ImageCodecInfo *pInfo;
- BYTE *pb = new BYTE[total_size];
- ATLASSERT(pb);
- pInfo = reinterpret_cast<Gdiplus::ImageCodecInfo *>(pb);
- if (pInfo == NULL)
- return -1; // failure
+ Gdiplus::ImageCodecInfo *ret;
+ ret = new Gdiplus::ImageCodecInfo[total_size / sizeof(ret[0])];
+ if (ret == NULL)
+ {
+ cEncoders = 0;
+ return NULL; // failure
+ }
- GetCommon().GetImageEncoders(count, total_size, pInfo);
+ GetCommon().GetImageEncoders(cEncoders, total_size, ret);
+ return ret; // needs delete[]
+ }
+
+ static Gdiplus::ImageCodecInfo* _getAllDecoders(UINT& cDecoders)
+ {
+ CImage image; // Initialize common
- for (UINT iInfo = 0; iInfo < count; ++iInfo)
+ UINT total_size = 0;
+ GetCommon().GetImageDecodersSize(&cDecoders, &total_size);
+ if (total_size == 0)
+ return NULL; // failure
+
+ Gdiplus::ImageCodecInfo *ret;
+ ret = new Gdiplus::ImageCodecInfo[total_size / sizeof(ret[0])];
+ if (ret == NULL)
{
- if (::lstrcmpiW(pInfo[iInfo].MimeType, mime) == 0)
- {
- *clsid = pInfo[iInfo].Clsid;
- delete[] pb;
- return iInfo; // success
- }
+ cDecoders = 0;
+ return NULL; // failure
}
- delete[] pb;
- return -1; // failure
+ GetCommon().GetImageDecoders(cDecoders, total_size, ret);
+ return ret; // needs delete[]
}
void AttachInternal(HBITMAP hBitmap, DIBOrientation eOrientation,
@@ -1186,9 +1230,7 @@ protected:
// create a DIB section
HDC hDC = ::CreateCompatibleDC(NULL);
ATLASSERT(hDC);
- LPVOID pvBits;
- HBITMAP hbm = ::CreateDIBSection(hDC, bi.get(), DIB_RGB_COLORS,
- &pvBits, NULL, 0);
+ HBITMAP hbm = ::CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, NULL, NULL, 0);
ATLASSERT(hbm);
::DeleteDC(hDC);