diff -r 735348f59235 -r 948c7f65f6d4 mmplugins/imagingplugins/codecs/PNGCodec/PNGConvert.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmplugins/imagingplugins/codecs/PNGCodec/PNGConvert.cpp Wed Sep 01 12:38:50 2010 +0100 @@ -0,0 +1,347 @@ +// Copyright (c) 1999-2009 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 +#include +#include +#include +#include "ImageClientMain.h" +#include "ImageUtils.h" +#include <101F45C7_extra.rsg> +#include "icl/ICL_UIDS.hrh" +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include +#include +#include +#endif +#include "PNGCodec.h" + + +_LIT(KPNGPanicCategory, "PNGConvertPlugin"); + +// Global panic function +GLDEF_C void Panic(TIclPanic aError) + { + User::Panic(KPNGPanicCategory, aError); + } + + +// Png decoder. +CPngDecoder* CPngDecoder::NewL() + { + return new(ELeave) CPngDecoder; + } + +CPngDecoder::CPngDecoder() + {} + +CPngDecoder::~CPngDecoder() + { + Cleanup(); + } + +void CPngDecoder::ImageType(TInt aFrameNumber, TUid& aImageType, TUid& aImageSubType) const + { + __ASSERT_ALWAYS(aFrameNumber == 0, Panic(EFrameNumberOutOfRange)); + aImageType = KImageTypePNGUid; + aImageSubType = KNullUid; + } + +// Scan header. +// Validate that format is correct. +// Create codec. +// Fill in image info. (All frames) +void CPngDecoder::ScanDataL() + { + ReadFormatL(); + + ASSERT(ImageReadCodec() == NULL); + + CPngReadCodec* imageReadCodec; + + imageReadCodec = CPngReadCodec::NewL(*this); + imageReadCodec->SetMissingiENDChunkFail(DecoderOptions() & CImageDecoder::EOptionPngMissingiENDFail); + SetImageReadCodec(imageReadCodec); // takes ownership of imageReadCodec + + ReadFrameHeadersL(); + } + +void CPngDecoder::ReadFormatL() + { + TPtrC8 bufferDes; + + ReadDataL(0, bufferDes, KPngFileSignatureLength); + + // Validate the header. + if (bufferDes.Length() < KPngFileSignatureLength) + User::Leave(KErrUnderflow); + + const TUint8* ptr = bufferDes.Ptr(); + if (Mem::Compare(ptr, KPngFileSignatureLength, KPngSignature, KPngFileSignatureLength)!=0) + User::Leave(KErrCorrupt); + + // Set start position. + SetStartPosition(KPngFileSignatureLength); + + // Get this from the header? + SetDataLength(KMaxTInt); + } + +CFrameInfoStrings* CPngDecoder::FrameInfoStringsL(RFs& aFs, TInt aFrameNumber) + { + + const TUid KPngCodecDllUid = {KPNGCodecDllUidValue}; + + RResourceFile resourceFile; + OpenExtraResourceFileLC(aFs,KPngCodecDllUid,resourceFile); + + HBufC8* resourceInfo = resourceFile.AllocReadLC(THEDECODERINFO); + TResourceReader resourceReader; + resourceReader.SetBuffer(resourceInfo); + + TBuf info; + TBuf templte; + + const TFrameInfo& frameInfo = FrameInfo(aFrameNumber); + CFrameInfoStrings* frameInfoStrings = CFrameInfoStrings::NewLC(); + + info = resourceReader.ReadTPtrC(); + frameInfoStrings->SetDecoderL(info); + + info = resourceReader.ReadTPtrC(); + frameInfoStrings->SetFormatL(info); + + TInt width = frameInfo.iOverallSizeInPixels.iWidth; + TInt height = frameInfo.iOverallSizeInPixels.iHeight; + TInt depth = frameInfo.iBitsPerPixel; + + templte = resourceReader.ReadTPtrC(); + info.Format(templte, width, height); + frameInfoStrings->SetDimensionsL(info); + + CDesCArrayFlat* resourceArray = resourceReader.ReadDesCArrayL(); + CleanupStack::PushL(resourceArray); + TUint formatIndex = (frameInfo.iFlags & TFrameInfo::EColor) ? 1 : 0; + templte = (*resourceArray)[formatIndex]; + CleanupStack::PopAndDestroy(resourceArray); + info.Format(templte, depth); + frameInfoStrings->SetDepthL(info); + + if(frameInfo.iFlags & TFrameInfo::ETransparencyPossible) + { + resourceArray = resourceReader.ReadDesCArrayL(); + CleanupStack::PushL(resourceArray); + formatIndex = (frameInfo.iFlags & TFrameInfo::EAlphaChannel) ? 1 : 0; + info = (*resourceArray)[formatIndex]; + frameInfoStrings->SetDetailsL(info); + CleanupStack::PopAndDestroy(resourceArray); + } + + CleanupStack::Pop(frameInfoStrings); + CleanupStack::PopAndDestroy(2); // resourceInfo + resourceFile + return frameInfoStrings; + } + +void CPngDecoder::InitConvertL() + { + iState = EStateStart; // when starting convert, always start from the top + CImageDecoderPlugin::InitConvertL(); + } + +void CPngDecoder::NotifyComplete() + { + iState = EStateStart; // ensure that however we exit one run, start at top of next DoConvert() + } + +void CPngDecoder::DoConvert() + { + switch (iState) + { + case EStateStart: + { + TRAPD(errCode, PrepareForProcessFrameL()); + + if (errCode!=KErrNone) + { + RequestComplete(errCode); + return; + } + iState = EStateNormalProcess; + } + // fall through + case EStateNormalProcess: + { + TFrameState codecState = EFrameIncomplete; + + TBufPtr8& sourceData = SourceData(); + TInt errCode=KErrNone; + if (sourceData.Length()!=0) + TRAP(errCode, codecState = ImageReadCodec()->ProcessFrameL(sourceData)); + + ASSERT(iState==EStateNormalProcess || iState==EStateDataProcess); // only valid states + if (errCode!=KErrNone || iState==EStateNormalProcess) + { + HandleProcessFrameResult(errCode, codecState); + iState = EStateStart; + } + else + { + ASSERT(iState==EStateDataProcess); // kick off a data process + SelfComplete(KErrNone); // ask for next run + } + } + break; + case EStateDataProcess: + { + TBool finished = EFalse; + CPngReadCodec* readCodec = static_cast(ImageReadCodec()); + TRAPD(error, finished = readCodec->DoProcessDataL()); + if (error!=KErrNone) + { + ASSERT(error!=KErrUnderflow); // underflow should happen later + RequestComplete(error); // will reset state + return; + } + + if (finished) + { + iState = EStateNormalProcess; + } + SelfComplete(KErrNone); // ask for next run, whatever we do + } + break; + default: + ASSERT(EFalse); // should not occur + } + } + +// Called from codec when we need to swith to EStateDataProcess +void CPngDecoder::GoToProcessDataState() + { + ASSERT(iState==EStateNormalProcess); // should be in this state if we get here + iState = EStateDataProcess; + } + +// PNG encoder +CPngEncoder* CPngEncoder::NewL() + { + return new(ELeave) CPngEncoder; + } + +CPngEncoder::CPngEncoder() + { + } + +CPngEncoder::~CPngEncoder() + { + CImageEncoderPlugin::Cleanup(); + } + +void CPngEncoder::PrepareEncoderL(const CFrameImageData* aFrameImageData) + { + // Default encode params + TInt bpp = 24; + TBool color = ETrue; + TBool paletted = EFalse; + TInt compressionLevel = TPngEncodeData::EDefaultCompression; + + // Use encode params in aFrameImageData, if present + const TInt count = (aFrameImageData) ? aFrameImageData->FrameDataCount() : 0; + for (TInt i=0; i < count; i++) + { + const TFrameDataBlock* encoderData = aFrameImageData->GetFrameData(i); + if (encoderData->DataType() == KPNGEncodeDataUid) + { + const TPngEncodeData* pngEncodeData = static_cast(encoderData); + bpp = pngEncodeData->iBitsPerPixel; + color = pngEncodeData->iColor; + paletted = pngEncodeData->iPaletted; + compressionLevel = pngEncodeData->iLevel; + } + } + + // Create the codec + CPngWriteCodec* codec = CPngWriteCodec::NewL(*this, bpp, color, paletted, compressionLevel); + + SetImageWriteCodec(codec); // takes ownership of imageReadCodec + + } + +void CPngEncoder::InitConvertL() + { + iState = EStateNormalProcess; // when starting convert, always start from the top + CImageEncoderPlugin::InitConvertL(); + } + +void CPngEncoder::NotifyComplete() + { + iState = EStateNormalProcess; // ensure that however we exit one run, start at top of next DoConvert() + } + +void CPngEncoder::DoConvert() + { + switch(iState) + { + case EStateNormalProcess: + { + TFrameState codecState = EFrameIncomplete; + + TBufPtr8& destData = DestinationData(); + TRAPD(error, codecState = ImageWriteCodec()->ProcessFrameL(destData)); + + if(error!=KErrNone || iState==EStateNormalProcess) + HandleProcessFrameResult(error, codecState); + else + { + ASSERT(iState==EStateDataProcess); // kick off a data process + SelfComplete(KErrNone); // ask for next run + } + } + break; + + case EStateDataProcess: + { + TBool finished = EFalse; + CPngWriteCodec* writeCodec = static_cast(ImageWriteCodec()); + + TRAPD(error, finished = writeCodec->DeflateEncodedDataL()); + + if(error!=KErrNone) + { + RequestComplete(error); // will reset state + return; + } + + if(finished) + iState = EStateNormalProcess; + + SelfComplete(KErrNone); // ask for next run, whatever we do + } + break; + + default: + ASSERT(EFalse); // invalid state + } + } + +void CPngEncoder::UpdateHeaderL() + { + } + +void CPngEncoder::GoToProcessDataState() + { + iState = EStateDataProcess; + } +