--- /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 <barsc.h>
+#include <barsread.h>
+#include <bautils.h>
+#include <imageconversion.h>
+#include "ImageClientMain.h"
+#include "ImageUtils.h"
+#include <101F45C7_extra.rsg>
+#include "icl/ICL_UIDS.hrh"
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <icl/icl_uids_const.hrh>
+#include <icl/icl_uids_def.hrh>
+#include <icl/imagecodecdef.h>
+#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<KCodecResourceStringMax> info;
+ TBuf<KCodecResourceStringMax> 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<CPngReadCodec*>(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<const TPngEncodeData*>(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<CPngWriteCodec*>(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;
+ }
+