windows-nt/Source/XPSP1/NT/printscan/ui/unittest/rotimg/rotimg.cpp
2020-09-26 16:20:57 +08:00

217 lines
5.8 KiB
C++

#include <windows.h>
#include <stdio.h>
#include <objbase.h>
#include "gdiplus.h"
#include <shlwapi.h>
#include <initguid.h>
//#include <shlwapip.h>
using namespace Gdiplus;
DEFINE_GUID(GUID_NULL, 0L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
UINT FindInDecoderList(ImageCodecInfo *pici, UINT cDecoders, LPCTSTR pszFile)
{
LPCTSTR pszExt = PathFindExtension(pszFile); // speed up PathMatchSpec calls
// look at the list of decoders to see if this format is there
for (UINT i = 0; i < cDecoders; i++)
{
if (PathMatchSpec(pszExt, pici[i].FilenameExtension))
return i;
}
return (UINT)-1; // not found!
}
class CEncoderInfo
{
public:
Status GetDataFormatFromPath(LPCWSTR pszPath, GUID *pguidFmt);
Status GetEncoderList();
Status GetEncoderFromFormat(const GUID *pfmt, CLSID *pclsidEncoder);
CEncoderInfo();
~CEncoderInfo();
private:
UINT _cEncoders; // number of encoders discovered
ImageCodecInfo *_pici; // array of image encoder classes
};
CEncoderInfo::CEncoderInfo()
{
_cEncoders = 0;
_pici = NULL;
}
CEncoderInfo::~CEncoderInfo()
{
LocalFree (_pici);
}
Status CEncoderInfo::GetDataFormatFromPath(LPCWSTR pszPath, GUID *pguidFmt)
{
*pguidFmt = GUID_NULL;
Status s = GetEncoderList();
if (Ok == s)
{
UINT i = FindInDecoderList(_pici, _cEncoders, pszPath);
if (-1 != i)
{
*pguidFmt = _pici[i].FormatID;
}
else
{
s = GenericError;
}
}
return s;
}
Status CEncoderInfo::GetEncoderList()
{
Status s = Ok;
if (!_pici)
{
// lets pick up the list of encoders, first we get the encoder size which
// gives us the CB and the number of encoders that are installed on the
// machine.
UINT cb;
s = GetImageEncodersSize(&_cEncoders, &cb);
if (Ok == s)
{
// allocate the buffer for the encoders and then fill it
// with the encoder list.
_pici = (ImageCodecInfo*)LocalAlloc(LPTR, cb);
if (_pici)
{
s = GetImageEncoders(_cEncoders, cb, _pici);
if (Ok != s)
{
LocalFree(_pici);
_pici = NULL;
}
}
else
{
s = OutOfMemory;
}
}
}
return s;
}
Status CEncoderInfo::GetEncoderFromFormat(const GUID *pfmt, CLSID *pclsidEncoder)
{
Status s = GetEncoderList();
if (Ok == s)
{
s = GenericError;
for (UINT i = 0; i != _cEncoders; i++)
{
if (_pici[i].FormatID == *pfmt)
{
if (pclsidEncoder)
{
*pclsidEncoder = _pici[i].Clsid; // return the CLSID of the encoder so we can create again
}
s = Ok;
break;
}
}
}
return s;
}
void AddEncParameter(EncoderParameters *pep, GUID guidProperty, ULONG type, void *pv)
{
pep->Parameter[pep->Count].Guid = guidProperty;
pep->Parameter[pep->Count].Type = type;
pep->Parameter[pep->Count].NumberOfValues = 1;
pep->Parameter[pep->Count].Value = pv;
pep->Count++;
}
class CGraphicsInit
{
ULONG_PTR _token;
public:
CGraphicsInit()
{
GdiplusStartupInput gsi;
GdiplusStartupOutput gso;
GdiplusStartup(&_token, &gsi, &gso);
};
~CGraphicsInit()
{
GdiplusShutdown(_token);
};
};
int __cdecl wmain(int argc, LPCWSTR argv[])
{
if (argc < 2)
{
printf("Usage: rotimg <filename> <targetfile>\n");
}
else
{
CGraphicsInit cgi;
LPCWSTR szSrc = argv[1];
LPCWSTR szSave = argc > 2 ? argv[2] : argv[1];
Status s;
printf("Source image: %ls, Target image: %ls\n", szSrc, szSave);
Image *pimg = new Image(szSrc, TRUE);
s = pimg->GetLastStatus();
if (Ok != s)
{
printf("Error %d constructing Image\n", s);
}
UINT nPages = pimg->GetFrameCount(&FrameDimensionPage);
Image *pimgWork = pimg->Clone();
s = pimgWork->RotateFlip(Rotate90FlipNone);
if (Ok != s)
{
printf("RotateFlip returned %d\n", s);
}
else
{
IStream *pstrm;
SHCreateStreamOnFileEx(szSave, STGM_WRITE | STGM_CREATE, 0, TRUE, NULL, &pstrm);
CEncoderInfo cei;
GUID guidFmt;
CLSID clsidEncoder;
cei.GetDataFormatFromPath(szSave, &guidFmt);
cei.GetEncoderFromFormat(&guidFmt, &clsidEncoder);
EncoderParameters ep[1] = {0};
ULONG flagValueMulti = nPages > 1 ? EncoderValueMultiFrame : EncoderValueLastFrame;
AddEncParameter(ep, EncoderSaveFlag, EncoderParameterValueTypeLong, &flagValueMulti);
pimgWork->SelectActiveFrame(&FrameDimensionPage, 0);
s = pimgWork->Save(pstrm,&clsidEncoder, ep);
printf("first Save returned %d\n", s);
if (Ok == s && nPages > 1)
{
EncoderParameters ep[2] = {0};
ULONG flagValueDim = EncoderValueFrameDimensionPage;
ULONG flagValueLastFrame = EncoderValueLastFrame;
pimg->SelectActiveFrame(&FrameDimensionPage, 1);
AddEncParameter(ep, EncoderSaveFlag, EncoderParameterValueTypeLong, &flagValueDim);
AddEncParameter(ep, EncoderSaveFlag, EncoderParameterValueTypeLong, &flagValueLastFrame);
s = pimgWork->SaveAdd(pimg, ep);
printf("SaveAdd returned %d\n", s);
}
pstrm->Release();
}
delete pimg;
delete pimgWork;
}
printf("Rotimg complete\n");
}