diff -r 000000000000 -r 7f656887cf89 commands/grabscreen/grabscreen.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/grabscreen/grabscreen.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,290 @@ +// grabscreen.cpp +// +// Copyright (c) 2008 - 2010 Accenture. All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Accenture - Initial contribution +// + +#include +#include +#include +#include +#include + +using namespace IoUtils; + + +class CCmdGrabscreen : public CCommandBase + { +public: + static CCommandBase* NewLC(); + ~CCmdGrabscreen(); +private: + enum TFormat + { + EJpeg, + EGif, + EBmp, + EPng, + ERaw + }; +private: + CCmdGrabscreen(); + void WriteEncodedL(TUid aEncodingUid); + void WriteRawL(); +private: // From CCommandBase. + virtual const TDesC& Name() const; + virtual void DoRunL(); + virtual void ArgumentsL(RCommandArgumentList& aArguments); + virtual void OptionsL(RCommandOptionList& aOptions); + + virtual void RunL(); +private: + TFileName2 iFileName; + CImageEncoder* iImageEncoder; + HBufC8* iImageData; + CFrameImageData* iFrameImageData; + RFile iFile; + TFormat iFormat; + RArray iRect; + TInt iScreen; + CFbsBitmap* iBitMap; + CWsScreenDevice* iDev; + RWsSession iWsSession; + TInt iQuality; + TBool iGreyscale; + }; + + +CCommandBase* CCmdGrabscreen::NewLC() + { + CCmdGrabscreen* self = new(ELeave) CCmdGrabscreen(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdGrabscreen::~CCmdGrabscreen() + { + delete iImageEncoder; + delete iFrameImageData; + delete iDev; + delete iBitMap; + delete iImageData; + iFile.Close(); + iRect.Close(); + iWsSession.Close(); + REComSession::FinalClose(); + } + +CCmdGrabscreen::CCmdGrabscreen() + : CCommandBase(EManualComplete), iQuality(100) + { + } + +const TDesC& CCmdGrabscreen::Name() const + { + _LIT(KName, "grabscreen"); + return KName; + } + +void CCmdGrabscreen::DoRunL() + { + if ((iFormat == ERaw) && (!iArguments.IsPresent(0))) + { + PrintError(KErrArgument, _L("STDOUT writing is not supported for raw format; please specify a filename")); + DisplayHelp(); + User::Leave(KErrArgument); + } + + LeaveIfErr(iWsSession.Connect(), _L("Couldn't connect to windowserver")); + iDev = new(ELeave) CWsScreenDevice(iWsSession); +#ifdef SYMBIAN_WSERV_AND_CONE_MULTIPLE_SCREENS + const TInt numScreens = iWsSession.NumberOfScreens(); + if (iScreen >= numScreens) + { + if (numScreens == 1) + { + LeaveIfErr(KErrArgument, _L("Invalid screen number - there is only 1 screen")); + } + else + { + LeaveIfErr(KErrArgument, _L("Invalid screen number - there are only %d screens")); + } + } +#endif + LeaveIfErr(iDev->Construct(iScreen), _L("Couldn't construct CWsScreenDevice for screen %d"), iScreen); + iBitMap = new(ELeave) CFbsBitmap(); + + TRect rect; + if (iOptions.IsPresent(&iRect)) + { + if (iRect.Count() != 4) + { + LeaveIfErr(KErrArgument, _L("Invalid --rect option - four integers must be specifed")); + } + rect.SetRect(iRect[0], iRect[1], iRect[2], iRect[3]); + } + else + { + rect.SetRect(TPoint(0, 0), iDev->SizeInPixels()); + } + + LeaveIfErr(iBitMap->Create(rect.Size(), iDev->DisplayMode()), _L("Couldn't create fbsbitmap of size (%d,%d) for display mode %d"), rect.Width(), rect.Height(), iDev->DisplayMode()); + User::LeaveIfError(iDev->CopyScreenToBitmap(iBitMap, rect)); + + switch (iFormat) + { + case EJpeg: + WriteEncodedL(KImageTypeJPGUid); + break; + case EGif: + WriteEncodedL(KImageTypeGIFUid); + break; + case EBmp: + WriteEncodedL(KImageTypeBMPUid); + break; + case EPng: + WriteEncodedL(KImageTypePNGUid); + break; + case ERaw: + WriteRawL(); + break; + } + } + +void CCmdGrabscreen::WriteEncodedL(TUid aEncodingUid) + { + if (aEncodingUid == KImageTypeJPGUid) + { + TJpegImageData* imageData = new(ELeave) TJpegImageData(); + CleanupStack::PushL(imageData); + imageData->iSampleScheme = iGreyscale ? TJpegImageData::EMonochrome : TJpegImageData::EColor444; + imageData->iQualityFactor = iQuality; + iFrameImageData = CFrameImageData::NewL(); + User::LeaveIfError(iFrameImageData->AppendImageData(imageData)); + CleanupStack::Pop(imageData); + } + else if (aEncodingUid == KImageTypeGIFUid) + { + if (iGreyscale) + { + PrintWarning(_L("Greyscale not supported for GIF images.")); + } + if (iOptions.IsPresent(&iQuality)) + { + PrintWarning(_L("Quality control not supported for GIF images.")); + } + } + else if (aEncodingUid == KImageTypeBMPUid) + { + if (iGreyscale) + { + PrintWarning(_L("Greyscale not supported for BMP images.")); + } + if (iOptions.IsPresent(&iQuality)) + { + PrintWarning(_L("Quality control not supported for BMP images.")); + } + } + else if (aEncodingUid == KImageTypePNGUid) + { + if (iOptions.IsPresent(&iQuality)) + { + PrintWarning(_L("Quality control not supported for PNG images.")); + } + + TPngEncodeData* imageData = new(ELeave) TPngEncodeData(); + CleanupStack::PushL(imageData); + imageData->iBitsPerPixel = iGreyscale ? 4 : 8; + imageData->iColor = !iGreyscale; + imageData->iLevel = TPngEncodeData::EBestCompression; + imageData->iPaletted = EFalse; + iFrameImageData = CFrameImageData::NewL(); + User::LeaveIfError(iFrameImageData->AppendFrameData(imageData)); + CleanupStack::Pop(imageData); + } + + if (iArguments.IsPresent(0)) + { + LeaveIfErr(iFile.Replace(FsL(), iFileName, EFileWrite), _L("Unable to open \"%S\" for writing"), &iFileName); + iImageEncoder = CImageEncoder::FileNewL(iFile, CImageEncoder::EOptionNone, aEncodingUid); + } + else + { + iImageEncoder = CImageEncoder::DataNewL(iImageData, CImageEncoder::EOptionNone, aEncodingUid); + } + iImageEncoder->Convert(&iStatus, *iBitMap, iFrameImageData); + SetActive(); + } + +void CCmdGrabscreen::RunL() + { + User::LeaveIfError(iStatus.Int()); + if (!iArguments.IsPresent(0)) + { + User::LeaveIfNull(iImageData); + + Stdout().SetModeL(RIoReadWriteHandle::EBinary); + + // we need to expand the 8 bit data when writing to stdout + static const TInt KBufferSize = 0x100; + TBuf buf; + TPtr8 imageData(iImageData->Des()); + while (imageData.Length()) + { + TInt thisCopyLen = Min(KBufferSize, imageData.Length()); + buf.Copy(imageData.Left(thisCopyLen)); + imageData.Set(imageData.MidTPtr(thisCopyLen)); + Stdout().WriteL(buf); + } + } + Complete(KErrNone); + } + +void CCmdGrabscreen::WriteRawL() + { + if (iGreyscale) + { + PrintWarning(_L("Greyscale not supported for raw images.")); + } + if (iOptions.IsPresent(&iQuality)) + { + PrintWarning(_L("Quality control not supported for raw images.")); + } + LeaveIfErr(iBitMap->Save(iFileName), _L("Unable to write \"%S\""), &iFileName); + Complete(KErrNone); + } + +void CCmdGrabscreen::ArgumentsL(RCommandArgumentList& aArguments) + { + _LIT(KArg, "file_name"); + aArguments.AppendFileNameL(iFileName, KArg); + } + +void CCmdGrabscreen::OptionsL(RCommandOptionList& aOptions) + { + _LIT(KOptFormat, "format"); + aOptions.AppendEnumL((TInt&)iFormat, KOptFormat); + + _LIT(KOptRect, "rect"); + aOptions.AppendIntL(iRect, KOptRect); + + _LIT(KOptScreen, "screen"); + aOptions.AppendIntL(iScreen, KOptScreen); + + _LIT(KOptQuality, "quality"); + aOptions.AppendIntL(iQuality, KOptQuality); + + _LIT(KOptGreyscale, "greyscale"); + aOptions.AppendBoolL(iGreyscale, KOptGreyscale); + } + + +EXE_BOILER_PLATE(CCmdGrabscreen) +