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