|
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 |