examples/ForumNokia/ImageConverter/src/Imageconverterengine.cpp

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

Generated by  doxygen 1.6.2