--- /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 <fshell/ioutils.h>
+#include <w32std.h>
+#include <fbs.h>
+#include <bitdev.h>
+#include <imageconversion.h>
+
+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<TInt> 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<KBufferSize> 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)
+