mmplugins/imagingplugins/codecs/PNGCodec/PNGConvert.cpp
branchRCL_3
changeset 50 948c7f65f6d4
parent 0 40261b775718
--- /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;
+	}
+