--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/codecs/GifCodec/GIFConvert.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,458 @@
+// Copyright (c) 1997-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:
+// Licensed under US Patent No 4,558,302 and foreign counterparts
+//
+//
+
+#include <imageconversion.h>
+#include "ImageClientMain.h"
+#include "ImageUtils.h"
+#include <barsc.h>
+#include <barsread.h>
+#include <bautils.h>
+#include <101F45B1_extra.rsg>
+#include "GIFConvert.h"
+#include "icl/ICL_UIDS.hrh"
+#include <gifscaler.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <icl/icl_uids_const.hrh>
+#include <icl/icl_uids_def.hrh>
+#include <icl/imagecodecdef.h>
+#endif
+
+_LIT(KGIFPanicCategory, "GIFConvertPlugin");
+
+// Global panic function
+GLDEF_C void Panic(TIclPanic aError)
+ {
+ User::Panic(KGIFPanicCategory, aError);
+ }
+
+CGifDecoder* CGifDecoder::NewL()
+ {
+ return new(ELeave) CGifDecoder;
+ }
+
+CGifDecoder::CGifDecoder()
+ {
+ }
+
+CGifDecoder::~CGifDecoder()
+ {
+ CImageDecoderPlugin::Cleanup();
+ }
+
+void CGifDecoder::ImageType(TInt aFrameNumber, TUid& aImageType, TUid& aImageSubType) const
+ {
+ __ASSERT_ALWAYS((aFrameNumber >= 0) && (aFrameNumber < NumberOfFrames()), Panic(EFrameNumberOutOfRange));
+ aImageType = KImageTypeGIFUid;
+ aImageSubType = KNullUid;
+ }
+
+TInt CGifDecoder::NumberOfImageComments() const
+ {
+ __ASSERT_ALWAYS(IsImageHeaderProcessingComplete(), Panic(EHeaderProcessingNotComplete));
+ const CFrameImageData& frameImageData = FrameData(0);
+ TInt imageCommentCount = 0;
+ const TInt imageDataCount = frameImageData.ImageDataCount();
+ for (TInt count = 0; count < imageDataCount; count++)
+ {
+ const TImageDataBlock* imageData = frameImageData.GetImageData(count);
+ if (imageData->DataType() == KGIFCommentUid)
+ imageCommentCount++;
+ }
+
+ return imageCommentCount;
+ }
+
+HBufC* CGifDecoder::ImageCommentL(TInt aCommentNumber) const
+ {
+ __ASSERT_ALWAYS(IsImageHeaderProcessingComplete(), Panic(EHeaderProcessingNotComplete));
+ __ASSERT_ALWAYS((aCommentNumber >= 0) && (aCommentNumber < NumberOfImageComments()), Panic(ECommentNumberOutOfRange));
+
+ const CFrameImageData& frameImageData = FrameData(0);
+ TInt commentCount = 0;
+ TInt imageDataCount = frameImageData.ImageDataCount();
+ const TImageDataBlock* imageData = NULL;
+ for (TInt count = 0; count < imageDataCount; count++)
+ {
+ imageData = frameImageData.GetImageData(count);
+ if (imageData->DataType() == KGIFCommentUid)
+ {
+ if (commentCount == aCommentNumber)
+ {
+ break;
+ }
+ commentCount++;
+ }
+ }
+
+ const TGifComment* gifComment = STATIC_CAST(const TGifComment*,imageData);
+ HBufC* comment = NULL;
+ if (gifComment)
+ {
+ comment = HBufC::NewL(gifComment->iComment->Length());
+ comment->Des().Copy(*(gifComment->iComment)); // Create a 16 bit copy of the 8 bit original
+ }
+
+ return comment;
+ }
+
+void CGifDecoder::ScanDataL()
+ {
+ ReadFormatL();
+
+ ASSERT(ImageReadCodec()==NULL);
+ CGifReadCodec* imageReadCodec = CGifReadCodec::NewL(iGlobalPalette, iFileInfo.iBackgroundColorIndex, iFileInfo.iScreenSize,
+ ( (DecoderOptions() & CImageDecoder::EPreferFastDecode) == CImageDecoder::EPreferFastDecode)
+ );
+
+ SetImageReadCodec(imageReadCodec);
+
+ if((DecoderOptions()&CImageDecoder::EOptionUseFrameSizeInPixels) == CImageDecoder::EOptionUseFrameSizeInPixels)
+ {
+ imageReadCodec->SetUseFrameSizeInPixels(ETrue);
+ }
+
+ ReadFrameHeadersL();
+ }
+
+void CGifDecoder::ReadFormatL()
+ {
+ TPtrC8 bufferDes;
+
+ // Read the header (+ 1 extra byte, so that we can check the first block id is valid)
+ ReadDataL(0, bufferDes, (KGifFileInformationSize + (KGifColorTableMaxEntries * KGifPaletteEntrySize) + 1));
+
+ // Validate the header.
+ if (bufferDes.Length() < KGifFileInformationSize)
+ User::Leave(KErrUnderflow);
+
+ iFileInfo.iSignature = bufferDes.Left(KGifSignatureLength);
+ if (iFileInfo.iSignature != KGif87aFileSignature &&
+ iFileInfo.iSignature != KGif89aFileSignature)
+ User::Leave(KErrCorrupt);
+
+ const TUint8* ptr = &bufferDes[KGifSignatureLength];
+ iFileInfo.iScreenSize.iWidth = PtrReadUtil::ReadUint16(ptr);
+ ptr+=2;
+
+ iFileInfo.iScreenSize.iHeight = PtrReadUtil::ReadUint16(ptr);
+ ptr+=2;
+
+ TUint8 flags = *ptr++;
+ iFileInfo.iBitsPerPixel = (flags & 0x07) + 1;
+ iFileInfo.iColorResolutionBits = ((flags & 0x70) >> 4) + 1;
+ iFileInfo.iGlobalColorMap = flags & 0x80;
+ if (iFileInfo.iSignature == KGif89aFileSignature)
+ iFileInfo.iSortedGlobalMap = flags & 0x08;
+
+ if (iFileInfo.iGlobalColorMap)
+ {
+ iFileInfo.iBackgroundColorIndex = *ptr;
+ iGlobalPaletteEntries = 1 << iFileInfo.iBitsPerPixel;
+ }
+ else
+ {
+ iFileInfo.iBackgroundColorIndex = KErrNotFound;
+ iGlobalPaletteEntries = 0;
+ }
+
+ ptr++;
+ TUint8 pixelAspectRatio = *ptr;
+ if (iFileInfo.iSignature == KGif87aFileSignature)
+ {
+ iFileInfo.iPixelAspectRatio = pixelAspectRatio & 0x7f;
+ iFileInfo.iSortedGlobalMap = pixelAspectRatio & 0x80;
+ }
+ else
+ iFileInfo.iPixelAspectRatio = pixelAspectRatio;
+
+ if (iFileInfo.iGlobalColorMap)
+ {
+ if (bufferDes.Length() < (KGifFileInformationSize + iGlobalPaletteEntries * KGifPaletteEntrySize))
+ User::Leave(KErrUnderflow);
+
+ const TUint8* ptr = &bufferDes[KGifFileInformationSize];
+ TRgb* palettePtr = iGlobalPalette;
+ TRgb* palettePtrLimit = iGlobalPalette + iGlobalPaletteEntries;
+
+ while (palettePtr < palettePtrLimit)
+ {
+ *palettePtr++ = TRgb(ptr[0],ptr[1],ptr[2]);
+ ptr += KGifPaletteEntrySize;
+ }
+
+ palettePtrLimit = iGlobalPalette + KGifColorTableMaxEntries;
+ while (palettePtr < palettePtrLimit)
+ *palettePtr++ = KRgbWhite;
+
+ TGifBackgroundColor* gifBackgroundColor = new(ELeave) TGifBackgroundColor;
+ gifBackgroundColor->iBackgroundColorIndex = iFileInfo.iBackgroundColorIndex;
+ gifBackgroundColor->iBackgroundColor = iGlobalPalette[iFileInfo.iBackgroundColorIndex];
+ CleanupStack::PushL(gifBackgroundColor);
+
+ User::LeaveIfError(AppendImageData(gifBackgroundColor));
+ CleanupStack::Pop(); // gifBackgroundColor
+ }
+
+ if (bufferDes.Length() < (KGifFileInformationSize + (iGlobalPaletteEntries * KGifPaletteEntrySize)) + 1)
+ User::Leave(KErrUnderflow);
+
+ // Check that first byte after the global color table is a valid block id
+ TUint8 nextBlockId = bufferDes[KGifFileInformationSize + (iGlobalPaletteEntries * KGifPaletteEntrySize)];
+ switch (nextBlockId)
+ {
+ case KGifExtensionId:
+ case KGifImageDescriptorId:
+ case KGifPlainTextExtensionId:
+ case KGifGraphicControlExtensionId:
+ case KGifCommentExtensionId:
+ case KGifApplicationExtensionId:
+ break;
+
+ default:
+ User::Leave(KErrCorrupt);
+ }
+
+ TInt startPosition = KGifFileInformationSize;
+ if (iFileInfo.iGlobalColorMap)
+ startPosition += iGlobalPaletteEntries * KGifPaletteEntrySize;
+ SetStartPosition(startPosition);
+
+ TFrameInfo imageInfo;
+ imageInfo = ImageInfo();
+ imageInfo.iOverallSizeInPixels = iFileInfo.iScreenSize;
+ imageInfo.iBitsPerPixel = iFileInfo.iBitsPerPixel;
+ imageInfo.iFrameSizeInTwips.SetSize(0,0);
+ if (iFileInfo.iGlobalColorMap)
+ {
+ imageInfo.iBackgroundColor = iGlobalPalette[iFileInfo.iBackgroundColorIndex];
+ if (iFileInfo.iColorResolutionBits<=4)
+ imageInfo.iFrameDisplayMode = EColor4K;
+ else
+ imageInfo.iFrameDisplayMode = EColor16M;
+ }
+ else
+ imageInfo.iFrameDisplayMode = EColor256;
+ imageInfo.iDelay = KErrNotFound;
+
+ SetImageInfo(imageInfo);
+ SetDataLength(KMaxTInt); // Set default data length in case format header doesn't contain this information
+ }
+
+CFrameInfoStrings* CGifDecoder::FrameInfoStringsL(RFs& aFs, TInt aFrameNumber)
+ {
+ const TUid KGifCodecDllUid = {KGIFCodecDllUidValue};
+
+ RResourceFile resourceFile;
+ OpenExtraResourceFileLC(aFs,KGifCodecDllUid,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);
+
+ CDesCArrayFlat* resourceArray = resourceReader.ReadDesCArrayL();
+ CleanupStack::PushL(resourceArray);
+ TUint formatIndex = (iFileInfo.iSignature == KGif87aFileSignature) ? 0 : 1;
+ info = (*resourceArray)[formatIndex];
+ CleanupStack::PopAndDestroy(resourceArray);
+ 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);
+
+ templte = resourceReader.ReadTPtrC();
+ info.Format(templte, depth);
+ frameInfoStrings->SetDepthL(info);
+
+ // leave details blank
+
+ CleanupStack::Pop(frameInfoStrings);
+ CleanupStack::PopAndDestroy(2); // resourceInfo + resourceFile
+ return frameInfoStrings;
+ }
+
+// Gif encoder.
+CGifEncoder* CGifEncoder::NewL()
+ {
+ CGifEncoder* self = new(ELeave) CGifEncoder;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+
+ }
+
+CGifEncoder::CGifEncoder()
+ {
+ }
+
+void CGifEncoder::ConstructL()
+ {
+ iPalette = CPalette::NewDefaultL(EColor256);
+ }
+
+CGifEncoder::~CGifEncoder()
+ {
+ if (iGifScaler)
+ {
+ iGifScaler->Cancel();
+ delete iGifScaler;
+ }
+ delete iPalette;
+ delete iDest;
+ CImageEncoderPlugin::Cleanup();
+ }
+
+const CPalette* CGifEncoder::Palette() const
+ {
+ return iPalette;
+ }
+
+void CGifEncoder::WriteExifDataL(TRequestStatus*& aScaleCompletionStatus)
+ {
+ if ((EncoderOptions() & CImageEncoder::EOptionGenerateAdaptivePalette) == CImageEncoder::EOptionGenerateAdaptivePalette)
+ {
+ if (!iPalette)
+ {
+ iPalette = CPalette::NewL(KGifColorTableMaxEntries);
+ }
+ iGifScaler->Scale(aScaleCompletionStatus, *iDest, *iPalette);
+ }
+ else
+ {
+ // the framework waits for aScaleCompletionStatus to complete
+ SelfComplete(KErrNone);
+ }
+ }
+
+void CGifEncoder::PrepareEncoderL(const CFrameImageData* aFrameImageData)
+ {
+ // Create the codec.
+ StartPosition() = KGifFileInformationSize;
+ StartPosition() += KGifColorTableMaxEntries * KGifPaletteEntrySize;
+ ASSERT(ImageWriteCodec() == NULL);
+
+ // ensure iPalette is NULL to start with since CGifWriteCodec::FillBufferL() behaviour depends on it
+ delete iPalette;
+ iPalette = NULL;
+
+ // check to see if client has supplied a palette
+ if (aFrameImageData)
+ {
+ TInt frameDataCount = aFrameImageData->FrameDataCount();
+ TGifColorTable* gifColorTable = NULL;
+ for (TInt frameDataIndex = 0; frameDataIndex < frameDataCount; frameDataIndex++)
+ {
+ TFrameDataBlock* frameData = const_cast<TFrameDataBlock*>(aFrameImageData->GetFrameData(frameDataIndex));
+ if (frameData->DataType() == KGIFColorTableUid)
+ {
+ gifColorTable = static_cast<TGifColorTable*>(frameData);
+ }
+ }
+
+ if (gifColorTable)
+ {
+ if (!iPalette)
+ {
+ iPalette = CPalette::NewL(KGifColorTableMaxEntries);
+ }
+ for (TInt i = 0; i < KGifColorTableMaxEntries; i++)
+ {
+ iPalette->SetEntry(i, gifColorTable->iPalette[i]);
+ }
+ }
+ }
+
+ if ((EncoderOptions() & CImageEncoder::EOptionGenerateAdaptivePalette) == CImageEncoder::EOptionGenerateAdaptivePalette)
+ {
+ CFbsBitmap* sourceBitmap = const_cast<CFbsBitmap*>(&Source());
+ delete iGifScaler;
+ iGifScaler = NULL;
+ iGifScaler = CGifScaler::NewL(*sourceBitmap);
+
+ delete iDest;
+ iDest = NULL;
+ iDest = new (ELeave) CFbsBitmap;
+ User::LeaveIfError(iDest->Create(sourceBitmap->SizeInPixels(), EColor256));
+ }
+
+ CGifWriteCodec* imageWriteCodec = CGifWriteCodec::NewL(*this);
+
+ SetImageWriteCodec(imageWriteCodec);
+
+ }
+
+void CGifEncoder::UpdateHeaderL()
+ {
+ TInt headerSize = KGifFileInformationSize + (KGifColorTableMaxEntries * KGifPaletteEntrySize);
+
+ HBufC8* gifHeaderPtr = HBufC8::NewMaxLC(headerSize);
+ TUint8* headerPtr = &gifHeaderPtr->Des()[0];
+
+ Mem::Copy(headerPtr,&KGif87aFileSignature()[0],KGifSignatureLength); headerPtr += KGifSignatureLength;
+
+ TInt width = Source().SizeInPixels().iWidth;
+ TInt height = Source().SizeInPixels().iHeight;
+ PtrWriteUtil::WriteInt16(headerPtr, width);
+ headerPtr+=2;
+ PtrWriteUtil::WriteInt16(headerPtr, height);
+ headerPtr+=2;
+ TUint8 resolutionFlag = 0;
+ resolutionFlag |= 8 - 1; // Bpp - 1
+ resolutionFlag |= (8 - 1) << 4; // Color Resolution
+ resolutionFlag |= 0x80; // Global Color Table Flag
+ *headerPtr++ = resolutionFlag;
+ *headerPtr++ = 255; // Background Color Index
+ *headerPtr++ = 0; // Pixel Aspect Ratio
+
+ for (TInt paletteIndex = 0; paletteIndex < KGifColorTableMaxEntries; paletteIndex++)
+ {
+ TRgb entry;
+ if (iPalette)
+ {
+ entry = iPalette->GetEntry(paletteIndex);
+ }
+ else
+ {
+ entry = TRgb::Color256(paletteIndex);
+ }
+
+ headerPtr[0] = (TUint8)entry.Red();
+ headerPtr[1] = (TUint8)entry.Green();
+ headerPtr[2] = (TUint8)entry.Blue();
+ headerPtr += 3;
+ }
+
+ TPtr8 bufferDes(gifHeaderPtr->Des());
+ WriteDataL(0,bufferDes);
+
+ CleanupStack::PopAndDestroy(); // gifHeaderPtr
+ }
+