#include #include #include #include "gdiplus.h" #include #include //#include 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 \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"); }