--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/codecs/JPEGCodec/JPGQUANT.CPP Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,345 @@
+// 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:
+//
+
+#include <e32base.h>
+
+#include "JpegTypes.h"
+
+const TInt KShift = 14;
+
+// TQTable
+TInt TQTable::Set(const TUint8* aData,const TBool aSixteenBitPrecision)
+ {
+ iSixteenBitPrecision = aSixteenBitPrecision;
+
+ if (iSixteenBitPrecision)
+ {
+ TUint16* sixteenBitPtr = reinterpret_cast<TUint16*>(iValues);
+ const TUint16* sixteenBitPtrLimit = sixteenBitPtr + KJpgQTableEntries;
+ while (sixteenBitPtr < sixteenBitPtrLimit)
+ {
+ *sixteenBitPtr++ = ReadBigEndianUint16(aData);
+ }
+
+ return KJpgQTableEntries * 2;
+ }
+
+ Mem::Copy(iValues, aData, KJpgQTableEntries);
+ Mem::FillZ(iValues + KJpgQTableEntries,KJpgQTableEntries);
+ CalcQualityFactor();
+
+ return KJpgQTableEntries;
+ }
+
+TInt TQTable::Get(TUint8* aData) const
+ {
+ const TInt valuesSize = KJpgQTableEntries * (iSixteenBitPrecision ? sizeof(TUint16) : sizeof(TUint8));
+
+ if (iSixteenBitPrecision)
+ {
+ TUint16* sixteenBitPtr = (TUint16*)iValues;
+ const TUint16* sixteenBitPtrLimit = sixteenBitPtr + KJpgQTableEntries;
+ while (sixteenBitPtr < sixteenBitPtrLimit)
+ {
+ WriteBigEndianUint16(aData,*sixteenBitPtr++);
+ }
+ }
+ else
+ {
+ Mem::Copy(aData,iValues,valuesSize);
+ }
+
+ return valuesSize;
+ }
+
+void TQTable::SetQualityFactor(TInt aQualityFactor)
+ {
+ TInt scaleFactor = 0;
+ if (aQualityFactor < 50)
+ {
+ aQualityFactor = Max(aQualityFactor,1);
+ scaleFactor = 5000 / aQualityFactor;
+ }
+ else
+ {
+ aQualityFactor = Min(aQualityFactor,100);
+ scaleFactor = 200 - (aQualityFactor * 2);
+ }
+
+ if (iSixteenBitPrecision)
+ {
+ TUint16* qPtr = (TUint16*)iValues;
+ const TUint16* qPtrLimit = qPtr + KJpgDCTBlockSize;
+ while (qPtr < qPtrLimit)
+ {
+ TInt qValue = (qPtr[0] * scaleFactor + 50) / 100;
+ if (qValue <= 0)
+ qValue = 1;
+ if (qValue > KMaxTInt16)
+ qValue = KMaxTInt16;
+ *qPtr++ = TUint16(qValue);
+ }
+ }
+ else
+ {
+ TUint8* qPtr = iValues;
+ const TUint8* qPtrLimit = qPtr + KJpgDCTBlockSize;
+
+ TInt* qPtrM = iValues2;
+
+ while (qPtr < qPtrLimit)
+ {
+ TInt qValue = (qPtr[0] * scaleFactor + 50) / 100;
+ if (qValue <= 0)
+ {
+ qValue = 1;
+ }
+ if (qValue > TInt(KMaxTUint8) )
+ {
+ qValue = KMaxTUint8;
+ }
+ *qPtrM++ = TUint16( (1 << KShift) / qValue );
+ *qPtr++ = TUint8(qValue);
+ }
+ }
+ }
+
+void TQTable::CalcQualityFactor() // Assumes the default tables have been used
+ {
+ TInt scaleFactor = 0;
+
+ if (iSixteenBitPrecision)
+ {
+ TUint16* qPtr = (TUint16*)iValues;
+ scaleFactor = qPtr[KJpgQTableEntries - 1];
+ }
+ else
+ {
+ scaleFactor = iValues[KJpgQTableEntries - 1];
+ }
+
+ if (scaleFactor > 100)
+ {
+ iQualityFactor = 5000 / scaleFactor;
+ }
+ else
+ {
+ iQualityFactor = 100 - (scaleFactor / 2);
+ }
+ }
+
+//
+// this section contains many performance-critical code, so use ARM instruction set for it
+//
+#ifdef __ARMCC__
+#pragma push
+#pragma arm
+#pragma O3
+#pragma Otime
+#endif
+
+template <class T>
+inline
+void TQTable::DoQuantize(TDataUnit& aDestination, const TDataUnit& aSource) const
+ {
+ const TInt16* srcPtr = aSource.iCoeff;
+ TInt16* dstPtr = aDestination.iCoeff;
+
+ const TUint8* zigZagPtr = KZigZagSequence.iZigZag;
+ const TUint8* zigZagPtrLimit= zigZagPtr + KJpgDCTBlockSize;
+
+ register const T* qPtr = reinterpret_cast<const T*>(iValues);
+
+ do
+ {
+ register TInt qValue = *qPtr++;
+ register TInt dstValue = srcPtr[*zigZagPtr++];
+ if (dstValue > 0)
+ {
+ dstValue += (qValue >> 1);
+ if (dstValue >= qValue)
+ {
+ dstValue /= qValue;
+ }
+ else
+ {
+ dstValue = 0;
+ }
+ }
+
+ else
+ {
+ dstValue -= (qValue >> 1);
+ dstValue = -dstValue;
+ if (dstValue >= qValue)
+ {
+ dstValue /= qValue;
+ dstValue = -dstValue;
+ }
+ else
+ {
+ dstValue = 0;
+ }
+ }
+
+ *dstPtr++ = TInt16(dstValue);
+
+ } while (zigZagPtr < zigZagPtrLimit);
+ }
+
+void TQTable::Quantize(TDataUnit& aDestination,const TDataUnit& aSource, TBool aHighSpeedMode) const
+ {
+ if (iSixteenBitPrecision)
+ {
+ DoQuantize<TUint16>(aDestination, aSource);
+ }
+ else
+ {
+ if (!aHighSpeedMode)
+ {
+ DoQuantize<TUint8>(aDestination, aSource);
+ }
+ else
+ {
+ const TInt16* srcPtr = aSource.iCoeff;
+ TUint64* dstPtr = reinterpret_cast<TUint64*>(aDestination.iCoeff);
+
+ const TUint8* zigZagPtr = KZigZagSequence.iZigZag;
+ const TUint8* zigZagPtrLimit= zigZagPtr + KJpgDCTBlockSize;
+
+ const TUint64* qPtr = &iValues2Aligment;
+ // we do 2 values per loop iteration
+ do
+ {
+ register TAligned64Value dstValue;
+ register TAligned64Value qValue;
+ register TAligned64Value zValue;
+ zValue.iAligment = *reinterpret_cast<const TUint64*>(zigZagPtr);
+
+ qValue.iAligment = *qPtr++;
+
+ dstValue.iWord[0] = TUint16(DESCALE(srcPtr[ zValue.iByte[0] ] * qValue.iInt[0], KShift));
+ dstValue.iWord[1] = TUint16(DESCALE(srcPtr[ zValue.iByte[1] ] * qValue.iInt[1], KShift));
+
+ qValue.iAligment = *qPtr++;
+
+ dstValue.iWord[2] = TUint16(DESCALE(srcPtr[ zValue.iByte[2] ] * qValue.iInt[0], KShift));
+ dstValue.iWord[3] = TUint16(DESCALE(srcPtr[ zValue.iByte[3] ] * qValue.iInt[1], KShift));
+
+ *dstPtr++ = dstValue.iAligment;
+
+ qValue.iAligment = *qPtr++;
+
+ dstValue.iWord[0] = TUint16(DESCALE(srcPtr[ zValue.iByte[4] ] * qValue.iInt[0], KShift));
+ dstValue.iWord[1] = TUint16(DESCALE(srcPtr[ zValue.iByte[5] ] * qValue.iInt[1], KShift));
+
+ qValue.iAligment = *qPtr++;
+
+ dstValue.iWord[2] = TUint16(DESCALE(srcPtr[ zValue.iByte[6] ] * qValue.iInt[0], KShift));
+ dstValue.iWord[3] = TUint16(DESCALE(srcPtr[ zValue.iByte[7] ] * qValue.iInt[1], KShift));
+
+ *dstPtr++ = dstValue.iAligment;
+
+ zigZagPtr += 8;
+ } while (zigZagPtr < zigZagPtrLimit);
+ }
+ }
+ }
+
+void TQTable::FastHalfDeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,TInt aNumNonZeroValues) const
+ {
+ DoDeQuantize(aDestination,aSource,Min(KJpgDCTBlockSize/2, aNumNonZeroValues), KJpgDCTBlockSize/2);
+ }
+
+
+void TQTable::DeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,TInt aNumNonZeroValues) const
+ {
+ DoDeQuantize(aDestination,aSource, aNumNonZeroValues, KJpgDCTBlockSize);
+ }
+
+void TQTable::DoDeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,
+ TInt aNumNonZeroValues, TInt aBlockLen) const
+ {
+ FillCompZ(aDestination, aBlockLen );
+
+ const TInt16* srcPtr = aSource.iCoeff;
+ const TInt16* const srcPtrLimit = srcPtr + aNumNonZeroValues;
+ TInt16* dstPtr = aDestination.iCoeff;
+ const TUint8* zigZagPtr = KZigZagSequence.iZigZag;
+
+ if (iSixteenBitPrecision)
+ {
+ const TUint16* qPtr = (const TUint16*)iValues;
+ while (srcPtr < srcPtrLimit)
+ {
+ TInt16 v=(*srcPtr++);
+ if (v)
+ {
+ dstPtr[*zigZagPtr] = TInt16(v * (*qPtr));
+ }
+ ++qPtr;
+ ++zigZagPtr;
+ }
+ }
+ else
+ {
+ const TUint8* qPtr = iValues;
+ while (srcPtr < srcPtrLimit)
+ {
+ TInt16 v=*srcPtr++;
+ if (v)
+ {
+ dstPtr[*zigZagPtr] = TInt16(v* (*qPtr));
+ }
+ ++zigZagPtr;
+ ++qPtr;
+ }
+ }
+ }
+
+void TQTable::FastQuarterDeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,TInt /*aNumNonZeroValues*/) const
+ {
+// we're interested only in result at indeces 0,1 and 8,9 for fast 1/4 iDCT,
+// so use excerpt of the ZigZag table:
+// 0, 1, 8, 16, 9
+//
+ const TInt16* srcPtr = aSource.iCoeff;
+
+ TInt16* dstPtr = aDestination.iCoeff;
+
+ if (iSixteenBitPrecision)
+ {
+ const TUint16* qPtr = (const TUint16*)iValues;
+
+ dstPtr[0] = TInt16(srcPtr[0] * qPtr[0]);
+ dstPtr[1] = TInt16(srcPtr[1] * qPtr[1]);
+ dstPtr[8] = TInt16(srcPtr[2] * qPtr[2]);
+ dstPtr[9] = TInt16(srcPtr[4] * qPtr[4]);
+
+ }
+ else
+ {
+ const TUint8* qPtr = iValues;
+ dstPtr[0] = TInt16(srcPtr[0] * qPtr[0]);
+ dstPtr[1] = TInt16(srcPtr[1] * qPtr[1]);
+ dstPtr[8] = TInt16(srcPtr[2] * qPtr[2]);
+ dstPtr[9] = TInt16(srcPtr[4] * qPtr[4]);
+ }
+ }
+
+#ifdef __ARMCC__
+#pragma pop
+#endif
+