mmplugins/imagingplugins/codecs/JPEGCodec/JPGQUANT.CPP
changeset 0 40261b775718
child 14 cd271b19d824
--- /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
+