00001 /* 00002 * Copyright © 2008 Nokia Corporation. 00003 */ 00004 00005 #include "ImageConverterEngine.h" 00006 00007 #include <fbs.h> 00008 #include <ImageConversion.h> 00009 #include <BitmapTransforms.h> 00010 00011 #include <eikdef.h> 00012 #include <eikenv.h> 00013 00014 const TInt KMaxInfoMsgLength = 50; 00015 const TInt KFixImageHeight = 70; 00016 const TInt KFixImageWidth = 10; 00017 00018 CImageConverterEngine* CImageConverterEngine::NewL( 00019 MConverterController* aController ) 00020 { 00021 CImageConverterEngine* self = 00022 new(ELeave) CImageConverterEngine( aController ); 00023 CleanupStack::PushL( self ); 00024 00025 self->ConstructL(); 00026 00027 CleanupStack::Pop(self); 00028 return self; 00029 } 00030 00031 CImageConverterEngine::CImageConverterEngine( 00032 MConverterController* aController ) : 00033 CActive( EPriorityStandard ), iController( aController ) 00034 { 00035 } 00036 00037 void CImageConverterEngine::ConstructL() 00038 { 00039 User::LeaveIfError( iFs.Connect() ); 00040 iRotator = CBitmapRotator::NewL(); 00041 iScaler = CBitmapScaler::NewL(); 00042 //iGlobalNote = CAknGlobalNote::NewL(); 00043 iState = EIdle; 00044 CActiveScheduler::Add( this ); 00045 } 00046 00047 CImageConverterEngine::~CImageConverterEngine() 00048 { 00049 Cancel(); 00050 delete iImageEncoder; 00051 delete iImageDecoder; // CImageDecoder must be deleted before the 00052 iFs.Close(); // related RFs is closed, 00053 delete iBitmap; // otherwise a related thread might panic 00054 delete iRotator; 00055 delete iScaler; 00056 //delete iGlobalNote; 00057 } 00058 00059 void CImageConverterEngine::StartToDecodeL( TFileName& aFileName ) 00060 { 00061 if (IsActive()) 00062 { 00063 return; 00064 } 00065 00066 delete iImageDecoder; iImageDecoder = NULL; 00067 delete iBitmap; iBitmap = NULL; 00068 00069 iFilename.Copy(aFileName); 00070 00071 // create the decoder 00072 iImageDecoder = CImageDecoder::FileNewL( iFs, aFileName ); 00073 00074 // create the destination bitmap 00075 iBitmap = new (ELeave) CFbsBitmap(); 00076 iBitmap->Create( iImageDecoder->FrameInfo().iOverallSizeInPixels, 00077 iImageDecoder->FrameInfo().iFrameDisplayMode ); 00078 00079 // start conversion to bitmap 00080 iState = EDecoding; 00081 iImageDecoder->Convert( &iStatus, *iBitmap ); 00082 SetActive(); 00083 } 00084 00085 void CImageConverterEngine::StartToEncodeL( 00086 TFileName& aFileName, TUid aImageType, TUid aImageSubType ) 00087 { 00088 if (!iBitmap) 00089 { 00090 return; 00091 } 00092 00093 if (iImageEncoder) 00094 { 00095 delete iImageEncoder; 00096 iImageEncoder = NULL; 00097 } 00098 00099 // create the encoder 00100 iImageEncoder = CImageEncoder::FileNewL( iFs, aFileName, 00101 CImageEncoder::EOptionNone, aImageType, aImageSubType ); 00102 00103 iState = EEncoding; 00104 iImageEncoder->Convert( &iStatus, *iBitmap ); 00105 SetActive(); 00106 00107 ShowProgress(); 00108 } 00109 00110 void CImageConverterEngine::DoCancel() 00111 { 00112 CancelProgress(); 00113 00114 if( iState == EDecoding ) 00115 { 00116 iImageDecoder->Cancel(); 00117 } 00118 else if( iState == EEncoding ) 00119 { 00120 iImageEncoder->Cancel(); 00121 } 00122 else if( iState == ERotating ) 00123 { 00124 iRotator->Cancel(); 00125 } 00126 else if( iState == EScaling ) 00127 { 00128 iScaler->Cancel(); 00129 } 00130 else 00131 { 00132 // State is EIdle, do nothing 00133 } 00134 } 00135 00136 00137 void CImageConverterEngine::RunL() 00138 { 00139 CancelProgress(); 00140 00141 switch( iState ) 00142 { 00143 case EDecoding: 00144 { 00145 iScaleDownCounter = 0; 00146 if( iStatus == KErrNone ) 00147 { 00148 if (FitToScreen()) 00149 { 00150 iState = EIdle; 00151 _LIT(KImageReady, "Image ready"); 00152 iController->NotifyCompletion( KErrNone, KImageReady ); 00153 } 00154 else 00155 { 00156 _LIT(KImageReady, "Image not ready"); 00157 iController->NotifyCompletion( KErrNotReady, KImageReady ); 00158 DoFitToScreen(); 00159 } 00160 break; 00161 } 00162 else if( iStatus == KErrUnderflow ) 00163 { 00164 ShowProgress(); 00165 iImageDecoder->ContinueConvert( &iStatus ); 00166 SetActive(); 00167 break; 00168 } 00169 else if ( iStatus == KErrCorrupt ) 00170 { 00171 iState = EIdle; 00172 _LIT(KImageCorrupt, "Image file corrupted"); 00173 iController->NotifyCompletion( KErrCorrupt, KImageCorrupt ); 00174 break; 00175 } 00176 else 00177 { 00178 // Unknown error 00179 iState = EIdle; 00180 _LIT( KErrorMsg, "Error while opening image:%d" ); 00181 TBuf<KMaxInfoMsgLength> buf; 00182 buf.Format( KErrorMsg, iStatus.Int() ); 00183 iController->NotifyCompletion( iStatus.Int(), KErrorMsg ); 00184 break; 00185 } 00186 } 00187 case EEncoding: 00188 { 00189 _LIT(KImageSaved, "Image saved"); 00190 iState = EIdle; 00191 iController->NotifyCompletion( iStatus.Int(), KImageSaved); 00192 break; 00193 } 00194 case EScaling: 00195 { 00196 iState = EIdle; 00197 iController->NotifyCompletion( iStatus.Int(), KNullDesC ); 00198 break; 00199 } 00200 default: 00201 case ERotating: 00202 { 00203 iState = EIdle; 00204 iController->NotifyCompletion( iStatus.Int(), KNullDesC ); 00205 break; 00206 } 00207 } 00208 } 00209 00210 TInt CImageConverterEngine::RunError(TInt /*aError*/) 00211 { 00212 CancelProgress(); 00213 // Our RunL does not contain any method calls that would leave, so this method 00214 // should never be called. 00215 return KErrNone; 00216 } 00217 00218 void CImageConverterEngine::GetEncoderImageTypesL( 00219 RImageTypeDescriptionArray& aImageTypeArray ) 00220 { 00221 CImageEncoder::GetImageTypesL( aImageTypeArray ); 00222 } 00223 00224 CFrameInfoStrings* CImageConverterEngine::GetImageInfoL() 00225 { 00226 // notice that the information is returned from the original image 00227 // hence the scaling of the bitmap does not affect the info until 00228 // the bitmap is encoded back to image file and opened again 00229 if( iImageDecoder ) 00230 { 00231 return( iImageDecoder->FrameInfoStringsL() ); 00232 } 00233 else 00234 { 00235 return NULL ; 00236 } 00237 } 00238 00239 void CImageConverterEngine::Rotate( TDirection aDirection ) 00240 { 00241 if (iState != EIdle || !iBitmap) 00242 { 00243 // Do nothing, if we are in the middle of processing a previous command 00244 return; 00245 } 00246 00247 if( aDirection == EClockwise90 ) 00248 { 00249 iRotator->Rotate( &iStatus, *iBitmap, 00250 CBitmapRotator::ERotation90DegreesClockwise ); 00251 } 00252 else 00253 { 00254 // 270 clockwise == 90 anticlockwise 00255 iRotator->Rotate( &iStatus, *iBitmap, 00256 CBitmapRotator::ERotation270DegreesClockwise ); 00257 } 00258 00259 iState = ERotating; 00260 SetActive(); 00261 00262 ShowProgress(); 00263 } 00264 00265 TBool CImageConverterEngine::FitToScreen() 00266 { 00267 TBool ret = ETrue; 00268 TPixelsTwipsAndRotation sizeAndRotation; 00269 CEikonEnv::Static()->ScreenDevice()->GetDefaultScreenSizeAndRotation(sizeAndRotation); 00270 if (iBitmap->SizeInPixels().iHeight > sizeAndRotation.iPixelSize.iHeight-KFixImageHeight || 00271 iBitmap->SizeInPixels().iWidth > sizeAndRotation.iPixelSize.iWidth-KFixImageWidth) 00272 { 00273 ret = EFalse; 00274 } 00275 return ret; 00276 } 00277 00278 void CImageConverterEngine::DoFitToScreen() 00279 { 00280 TPixelsTwipsAndRotation sizeAndRotation; 00281 CEikonEnv::Static()->ScreenDevice()->GetDefaultScreenSizeAndRotation(sizeAndRotation); 00282 00283 TInt newWidth = (sizeAndRotation.iPixelSize.iWidth-KFixImageWidth); 00284 TInt newHeight = (sizeAndRotation.iPixelSize.iHeight-KFixImageHeight); 00285 00286 // the maintain aspect ratio is by default set to true 00287 iScaler->Scale( &iStatus, *iBitmap, TSize(newWidth,newHeight) ); 00288 00289 iState = EScaling; 00290 SetActive(); 00291 } 00292 00293 TBool CImageConverterEngine::CanDownScaleMore() 00294 { 00295 if (iScaleDownCounter > 2) 00296 { 00297 return EFalse; 00298 } 00299 else 00300 { 00301 return ETrue; 00302 } 00303 } 00304 00305 TInt CImageConverterEngine::Scale( TInt aPercent ) 00306 { 00307 if (iState != EIdle || !iBitmap) 00308 { 00309 // Do nothing, if we are in the middle of processing a previous command 00310 return KErrNotReady; 00311 } 00312 00313 // Scaling down 00314 if (aPercent > 100) 00315 { 00316 if (!CanDownScaleMore()) 00317 { 00318 return KErrCancel; 00319 } 00320 iScaleDownCounter++; 00321 00322 TReal32 multiplier; 00323 00324 multiplier = aPercent/(TReal32)100.0; 00325 00326 TInt newWidth = (TInt)(iBitmap->SizeInPixels().iWidth * multiplier); 00327 TInt newHeight = (TInt)(iBitmap->SizeInPixels().iHeight * multiplier); 00328 00329 // the maintain aspect ratio is by default set to true 00330 iScaler->Scale( &iStatus, *iBitmap, TSize(newWidth,newHeight) ); 00331 00332 iState = EScaling; 00333 SetActive(); 00334 ShowProgress(); 00335 } 00336 // Scaling up gives original picture 00337 else 00338 { 00339 TRAPD(err, 00340 StartToDecodeL(iFilename)); 00341 if (err) 00342 { 00343 return err; 00344 } 00345 } 00346 00347 return KErrNone; 00348 } 00349 00350 CFbsBitmap* CImageConverterEngine::GetBitmap() 00351 { 00352 if (iState != EIdle) 00353 return NULL; 00354 else 00355 return iBitmap; 00356 } 00357 00358 void CImageConverterEngine::ShowProgress() 00359 { 00360 //TRAPD(err, 00361 // iNoteId = iGlobalNote->ShowNoteL(EAknGlobalWaitNote,_L("Working...")); 00362 // ); 00363 } 00364 00365 void CImageConverterEngine::CancelProgress() 00366 { 00367 //TRAPD(err, 00368 // iGlobalNote->CancelNoteL(iNoteId); 00369 // ); 00370 } 00371 00372 00373
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.