commands/grabscreen/grabscreen.cpp
changeset 0 7f656887cf89
child 30 35cb3fe43f60
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // grabscreen.cpp
       
     2 // 
       
     3 // Copyright (c) 2008 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <fshell/ioutils.h>
       
    14 #include <w32std.h>
       
    15 #include <fbs.h>
       
    16 #include <bitdev.h>
       
    17 #include <imageconversion.h>
       
    18 
       
    19 using namespace IoUtils;
       
    20 
       
    21 
       
    22 class CCmdGrabscreen : public CCommandBase
       
    23 	{
       
    24 public:
       
    25 	static CCommandBase* NewLC();
       
    26 	~CCmdGrabscreen();
       
    27 private:
       
    28 	enum TFormat
       
    29 		{
       
    30 		EJpeg,
       
    31 		EGif,
       
    32 		EBmp,
       
    33 		EPng,
       
    34 		ERaw
       
    35 		};
       
    36 private:
       
    37 	CCmdGrabscreen();
       
    38 	void WriteEncodedL(TUid aEncodingUid);
       
    39 	void WriteRawL();
       
    40 private: // From CCommandBase.
       
    41 	virtual const TDesC& Name() const;
       
    42 	virtual void DoRunL();
       
    43 	virtual void ArgumentsL(RCommandArgumentList& aArguments);
       
    44 	virtual void OptionsL(RCommandOptionList& aOptions);
       
    45 	
       
    46 	virtual void RunL();
       
    47 private:
       
    48 	TFileName2 iFileName;
       
    49 	CImageEncoder* iImageEncoder;
       
    50 	HBufC8* iImageData;
       
    51 	CFrameImageData* iFrameImageData;
       
    52 	RFile iFile;
       
    53 	TFormat iFormat;
       
    54 	RArray<TInt> iRect;
       
    55 	TInt iScreen;
       
    56 	CFbsBitmap* iBitMap;
       
    57 	CWsScreenDevice* iDev;
       
    58 	RWsSession iWsSession;
       
    59 	TInt iQuality;
       
    60 	TBool iGreyscale;
       
    61 	};
       
    62 
       
    63 
       
    64 CCommandBase* CCmdGrabscreen::NewLC()
       
    65 	{
       
    66 	CCmdGrabscreen* self = new(ELeave) CCmdGrabscreen();
       
    67 	CleanupStack::PushL(self);
       
    68 	self->BaseConstructL();
       
    69 	return self;
       
    70 	}
       
    71 
       
    72 CCmdGrabscreen::~CCmdGrabscreen()
       
    73 	{
       
    74 	delete iImageEncoder;
       
    75 	delete iFrameImageData;
       
    76 	delete iDev;
       
    77 	delete iBitMap;
       
    78 	delete iImageData;
       
    79 	iFile.Close();
       
    80 	iRect.Close();
       
    81 	iWsSession.Close();
       
    82 	REComSession::FinalClose();
       
    83 	}
       
    84 
       
    85 CCmdGrabscreen::CCmdGrabscreen() 
       
    86 	: CCommandBase(EManualComplete), iQuality(100)
       
    87 	{
       
    88 	}
       
    89 
       
    90 const TDesC& CCmdGrabscreen::Name() const
       
    91 	{
       
    92 	_LIT(KName, "grabscreen");	
       
    93 	return KName;
       
    94 	}
       
    95 
       
    96 void CCmdGrabscreen::DoRunL()
       
    97 	{
       
    98 	if ((iFormat == ERaw) && (!iArguments.IsPresent(0)))
       
    99 		{
       
   100 		PrintError(KErrArgument, _L("STDOUT writing is not supported for raw format; please specify a filename"));
       
   101 		DisplayHelp();
       
   102 		User::Leave(KErrArgument);
       
   103 		}
       
   104 	
       
   105 	LeaveIfErr(iWsSession.Connect(), _L("Couldn't connect to windowserver"));
       
   106 	iDev = new(ELeave) CWsScreenDevice(iWsSession);
       
   107 #ifdef SYMBIAN_WSERV_AND_CONE_MULTIPLE_SCREENS
       
   108 	const TInt numScreens = iWsSession.NumberOfScreens();
       
   109 	if (iScreen >= numScreens)
       
   110 		{
       
   111 		if (numScreens == 1)
       
   112 			{
       
   113 			LeaveIfErr(KErrArgument, _L("Invalid screen number - there is only 1 screen"));
       
   114 			}
       
   115 		else
       
   116 			{
       
   117 			LeaveIfErr(KErrArgument, _L("Invalid screen number - there are only %d screens"));
       
   118 			}
       
   119 		}
       
   120 #endif
       
   121 	LeaveIfErr(iDev->Construct(iScreen), _L("Couldn't construct CWsScreenDevice for screen %d"), iScreen);
       
   122 	iBitMap = new(ELeave) CFbsBitmap();
       
   123 
       
   124 	TRect rect;
       
   125 	if (iOptions.IsPresent(&iRect))
       
   126 		{
       
   127 		if (iRect.Count() != 4)
       
   128 			{
       
   129 			LeaveIfErr(KErrArgument, _L("Invalid --rect option - four integers must be specifed"));
       
   130 			}
       
   131 		rect.SetRect(iRect[0], iRect[1], iRect[2], iRect[3]);
       
   132 		}
       
   133 	else
       
   134 		{
       
   135 		rect.SetRect(TPoint(0, 0), iDev->SizeInPixels());
       
   136 		}
       
   137 	
       
   138 	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());
       
   139 	User::LeaveIfError(iDev->CopyScreenToBitmap(iBitMap, rect));
       
   140 
       
   141 	switch (iFormat)
       
   142 		{
       
   143 		case EJpeg:
       
   144 			WriteEncodedL(KImageTypeJPGUid);
       
   145 			break;
       
   146 		case EGif:
       
   147 			WriteEncodedL(KImageTypeGIFUid);
       
   148 			break;
       
   149 		case EBmp:
       
   150 			WriteEncodedL(KImageTypeBMPUid);
       
   151 			break;
       
   152 		case EPng:
       
   153 			WriteEncodedL(KImageTypePNGUid);
       
   154 			break;
       
   155 		case ERaw:
       
   156 			WriteRawL();
       
   157 			break;
       
   158 		}
       
   159 	}
       
   160 
       
   161 void CCmdGrabscreen::WriteEncodedL(TUid aEncodingUid)
       
   162 	{
       
   163 	if (aEncodingUid == KImageTypeJPGUid)
       
   164 		{
       
   165 		TJpegImageData* imageData = new(ELeave) TJpegImageData();
       
   166 		CleanupStack::PushL(imageData);
       
   167 		imageData->iSampleScheme = iGreyscale ? TJpegImageData::EMonochrome : TJpegImageData::EColor444;
       
   168 		imageData->iQualityFactor = iQuality;
       
   169 		iFrameImageData = CFrameImageData::NewL();
       
   170 		User::LeaveIfError(iFrameImageData->AppendImageData(imageData));
       
   171 		CleanupStack::Pop(imageData);
       
   172 		}
       
   173 	else if (aEncodingUid == KImageTypeGIFUid)
       
   174 		{
       
   175 		if (iGreyscale)
       
   176 			{
       
   177 			PrintWarning(_L("Greyscale not supported for GIF images."));
       
   178 			}
       
   179 		if (iOptions.IsPresent(&iQuality))
       
   180 			{
       
   181 			PrintWarning(_L("Quality control not supported for GIF images."));
       
   182 			}
       
   183 		}
       
   184 	else if (aEncodingUid == KImageTypeBMPUid)
       
   185 		{
       
   186 		if (iGreyscale)
       
   187 			{
       
   188 			PrintWarning(_L("Greyscale not supported for BMP images."));
       
   189 			}
       
   190 		if (iOptions.IsPresent(&iQuality))
       
   191 			{
       
   192 			PrintWarning(_L("Quality control not supported for BMP images."));
       
   193 			}
       
   194 		}
       
   195 	else if (aEncodingUid == KImageTypePNGUid)
       
   196 		{
       
   197 		if (iOptions.IsPresent(&iQuality))
       
   198 			{
       
   199 			PrintWarning(_L("Quality control not supported for PNG images."));
       
   200 			}
       
   201 
       
   202 		TPngEncodeData* imageData = new(ELeave) TPngEncodeData();
       
   203 		CleanupStack::PushL(imageData);
       
   204 		imageData->iBitsPerPixel = iGreyscale ? 4 : 8;
       
   205 		imageData->iColor = !iGreyscale;
       
   206 		imageData->iLevel = TPngEncodeData::EBestCompression;
       
   207 		imageData->iPaletted = EFalse;
       
   208 		iFrameImageData = CFrameImageData::NewL();
       
   209 		User::LeaveIfError(iFrameImageData->AppendFrameData(imageData));
       
   210 		CleanupStack::Pop(imageData);
       
   211 		}
       
   212 		
       
   213 	if (iArguments.IsPresent(0))
       
   214 		{
       
   215 		LeaveIfErr(iFile.Replace(FsL(), iFileName, EFileWrite), _L("Unable to open \"%S\" for writing"), &iFileName);
       
   216 		iImageEncoder = CImageEncoder::FileNewL(iFile, CImageEncoder::EOptionNone, aEncodingUid);
       
   217 		}
       
   218 	else
       
   219 		{
       
   220 		iImageEncoder = CImageEncoder::DataNewL(iImageData, CImageEncoder::EOptionNone, aEncodingUid);
       
   221 		}
       
   222 	iImageEncoder->Convert(&iStatus, *iBitMap, iFrameImageData);
       
   223 	SetActive();
       
   224 	}
       
   225 	
       
   226 void CCmdGrabscreen::RunL()
       
   227 	{
       
   228 	User::LeaveIfError(iStatus.Int());
       
   229 	if (!iArguments.IsPresent(0))
       
   230 		{
       
   231 		User::LeaveIfNull(iImageData);
       
   232 		
       
   233 		Stdout().SetModeL(RIoReadWriteHandle::EBinary);
       
   234 		
       
   235 		// we need to expand the 8 bit data when writing to stdout
       
   236 		static const TInt KBufferSize = 0x100;
       
   237 		TBuf<KBufferSize> buf;
       
   238 		TPtr8 imageData(iImageData->Des());
       
   239 		while (imageData.Length())
       
   240 			{
       
   241 			TInt thisCopyLen = Min(KBufferSize, imageData.Length());
       
   242 			buf.Copy(imageData.Left(thisCopyLen));
       
   243 			imageData.Set(imageData.MidTPtr(thisCopyLen));
       
   244 			Stdout().WriteL(buf);
       
   245 			}
       
   246 		}
       
   247 	Complete(KErrNone);
       
   248 	}
       
   249 
       
   250 void CCmdGrabscreen::WriteRawL()
       
   251 	{
       
   252 	if (iGreyscale)
       
   253 		{
       
   254 		PrintWarning(_L("Greyscale not supported for raw images."));
       
   255 		}
       
   256 	if (iOptions.IsPresent(&iQuality))
       
   257 		{
       
   258 		PrintWarning(_L("Quality control not supported for raw images."));
       
   259 		}
       
   260 	LeaveIfErr(iBitMap->Save(iFileName), _L("Unable to write \"%S\""), &iFileName);
       
   261 	Complete(KErrNone);
       
   262 	}
       
   263 
       
   264 void CCmdGrabscreen::ArgumentsL(RCommandArgumentList& aArguments)
       
   265 	{
       
   266 	_LIT(KArg, "file_name");
       
   267 	aArguments.AppendFileNameL(iFileName, KArg);
       
   268 	}
       
   269 
       
   270 void CCmdGrabscreen::OptionsL(RCommandOptionList& aOptions)
       
   271 	{
       
   272 	_LIT(KOptFormat, "format");
       
   273 	aOptions.AppendEnumL((TInt&)iFormat, KOptFormat);
       
   274 
       
   275 	_LIT(KOptRect, "rect");
       
   276 	aOptions.AppendIntL(iRect, KOptRect);
       
   277 
       
   278 	_LIT(KOptScreen, "screen");
       
   279 	aOptions.AppendIntL(iScreen, KOptScreen);
       
   280 
       
   281 	_LIT(KOptQuality, "quality");
       
   282 	aOptions.AppendIntL(iQuality, KOptQuality);
       
   283 
       
   284 	_LIT(KOptGreyscale, "greyscale");
       
   285 	aOptions.AppendBoolL(iGreyscale, KOptGreyscale);
       
   286 	}
       
   287 
       
   288 
       
   289 EXE_BOILER_PLATE(CCmdGrabscreen)
       
   290