diff -r ae942d28ec0e -r 2455ef1f5bbc javauis/lcdui_akn/lcdgr/src/CMIDImageDecoder.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/lcdgr/src/CMIDImageDecoder.cpp Wed Sep 01 12:33:18 2010 +0100 @@ -0,0 +1,232 @@ +/* +* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include "CMIDImageDecoder.h" +#include "LcdFbsImage.h" +#include + +CMIDImageDecoder::CMIDImageDecoder(RFs& aFsSession, TDisplayMode aDisplayMode) + : CActive(CActive::EPriorityStandard), iRFsSession(aFsSession), iDisplayMode(aDisplayMode) +{ + CActiveScheduler::Add(this); + iRFsSession = aFsSession; +} + +void CMIDImageDecoder::ConstructL() +{ + iDecoder = CBufferedImageDecoder::NewL(iRFsSession); +} + +CMIDImageDecoder::~CMIDImageDecoder() +{ + Cancel(); + ASSERT(NULL == iCallback); + delete iBitmapImage; + delete iDecoder; +} + +void CMIDImageDecoder::AppendL(const TDesC8& aBuffer) +{ + TInt err = KErrNone; + + if (iState == EStart) + { + TRAP(err, iDecoder->OpenL(aBuffer, CImageDecoder::EOptionPngMissingiENDFail)); + + if (err == KEComErrNoInterfaceIdentified || err == KErrNotFound) + { + // If the format is unrecognised AND the first 2 bytes are 0 then we assume it + // is a WBMP. This is a requirement of the below defect. + // The first two bytes of other formats (e.g. ico) may also begin with 0, 0 + // but they should have already been recognised by the first call to OpenL + if (aBuffer[0] == 0 && aBuffer[1] == 0) + { + delete iDecoder; + iDecoder = NULL; + iDecoder = CBufferedImageDecoder::NewL(iRFsSession); + DEBUG("* CMIDImageDecoder::AppendL - Format can't be fully identified, assuming this is WBMP"); + _LIT8(KWBMPMimeType, "image/vnd.wap.wbmp"); + TRAP(err, iDecoder->OpenL(aBuffer, KWBMPMimeType, CImageDecoder::EOptionPngMissingiENDFail)); + } + } + + if ((err != KErrUnderflow) && (err != KEComErrNoInterfaceIdentified) && (err != KErrNotFound)) + { + // + // something's gone wrong that we can't fix by appending more data + // + User::LeaveIfError(err); + } + iState = EOpenPending; + } + else + { + iDecoder->AppendDataL(aBuffer); + + if (!iDecoder->ValidDecoder()) + { + TRAP(err, iDecoder->ContinueOpenL()); + if ((err == KErrUnderflow) || (err == KEComErrNoInterfaceIdentified) || (err == KErrNotFound)) + { + // decoder or framework needs more data to determine codec. + return; + } + + // + // If something else has gone wrong then we can't fix by appending more data + // + User::LeaveIfError(err); + } + } + + if (iDecoder->ValidDecoder()) + { + if (!iDecoder->IsImageHeaderProcessingComplete()) + { + iDecoder->ContinueProcessingHeaderL(); + if (iDecoder->IsImageHeaderProcessingComplete()) + { + iState = EOpenComplete; + } + } + else + { + iState = EOpenComplete; + } + } +} + +void NullPointer(TAny* aPtr) +{ + * static_cast(aPtr) = NULL; +} + +void CMIDImageDecoder::DecodeL(MMIDImageObserver* aCallback) +{ + // + // If we are asked to decode, but have not yet managed to process the + // image header we leave with KErrCorrrupt indicating that we think + // the encoded image data is corrupt. + // + if (iState < EOpenComplete) + { + User::Leave(KErrCorrupt); + } + ASSERT(NULL == iCallback); + CleanupStack::PushL(TCleanupItem(NullPointer, &iCallback)); + iCallback = aCallback; + ConvertL(); + CleanupStack::Pop(); +} + +void CMIDImageDecoder::Complete(TInt aResult) +{ + if (iCallback) + { + iCallback->DecodeComplete(aResult); + iCallback = NULL; + } +} + +void CMIDImageDecoder::ConvertL() +{ + iState = EConvertPending; + + if (NULL == iBitmapImage) + { + const TFrameInfo& frameInfo = iDecoder->FrameInfo(); + + TSize size = frameInfo.iOverallSizeInPixels; + + // S60: Set the colormode of the bitmap to be exactly as the phone's display. + // This will cause CLcdImage class just to duplicate the handle of this image, + // and not converting the pixels from the image's original color format to phone's color format. + // The image is needed to be in the same color format as the phone's display so BitBlt() is the most efficient. + // + // Decoding directly to 16MA does not work in 5.0 HW. It works only in emulator and not for JPEG. + // The image decoders need to fix this. + // We decode to 16MU still and then a conversion from 16MU->16MA will be done + // + // Insufficient information available to load image in its natural format. + + TDisplayMode colorMode = frameInfo.iFrameDisplayMode; + TDisplayMode alphaMode = ENone; + + if (frameInfo.iFlags & TFrameInfo::ETransparencyPossible) + { + if (frameInfo.iFlags & TFrameInfo::EAlphaChannel) + { + alphaMode = EGray256; + } + else + { + alphaMode = EGray2; + } + } + + // + // This step is the most likely to fail in low memory conditions. + // + CLcdFbsImage* fbsImage = CLcdFbsImage::NewL(size, colorMode, alphaMode); + CleanupStack::PushL(fbsImage); + iBitmapImage = new(ELeave) CMIDBitmapImage(*fbsImage); + CleanupStack::Pop(fbsImage); + } + + CFbsBitmap* colorBitmap = iBitmapImage->ColorBitmap(); + CFbsBitmap* alphaBitmap = iBitmapImage->AlphaBitmap(); + + if (alphaBitmap) + { + iDecoder->Convert(&iStatus, *colorBitmap, *alphaBitmap, 0); + } + else + { + iDecoder->Convert(&iStatus, *colorBitmap, 0); + } + SetActive(); +} + +void CMIDImageDecoder::Dispose() +{ + delete this; +} + +MMIDBitmapImage* CMIDImageDecoder::BitmapImage() const +{ + return iBitmapImage; +} + +void CMIDImageDecoder::RunL() +{ + ASSERT(iState == EConvertPending); + Complete(iStatus.Int()); +} + +TInt CMIDImageDecoder::RunError(TInt aError) +{ + ASSERT(KErrNone == aError); // should never happen + return aError; +} + +void CMIDImageDecoder::DoCancel() +{ + ASSERT(iState == EConvertPending); + iDecoder->Cancel(); +} + +