mmplugins/imagingplugins/codecs/JPEGCodec/JPGQUANT.CPP
changeset 0 40261b775718
child 14 cd271b19d824
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <e32base.h>
       
    17 
       
    18 #include "JpegTypes.h"
       
    19 
       
    20 const TInt KShift = 14;
       
    21 
       
    22 // TQTable
       
    23 TInt TQTable::Set(const TUint8* aData,const TBool aSixteenBitPrecision)
       
    24 	{
       
    25 	iSixteenBitPrecision = aSixteenBitPrecision;
       
    26 
       
    27 	if (iSixteenBitPrecision)
       
    28 		{
       
    29 		TUint16* sixteenBitPtr = reinterpret_cast<TUint16*>(iValues);
       
    30 		const TUint16* sixteenBitPtrLimit = sixteenBitPtr + KJpgQTableEntries;
       
    31 		while (sixteenBitPtr < sixteenBitPtrLimit)
       
    32 		    {
       
    33 		    *sixteenBitPtr++ = ReadBigEndianUint16(aData);
       
    34 		    }
       
    35 			
       
    36 		return KJpgQTableEntries * 2;
       
    37 		}
       
    38 
       
    39     Mem::Copy(iValues, aData, KJpgQTableEntries);
       
    40     Mem::FillZ(iValues + KJpgQTableEntries,KJpgQTableEntries);
       
    41 	CalcQualityFactor();
       
    42 
       
    43 	return KJpgQTableEntries;
       
    44 	}
       
    45 
       
    46 TInt TQTable::Get(TUint8* aData) const
       
    47 	{
       
    48 	const TInt valuesSize = KJpgQTableEntries * (iSixteenBitPrecision ? sizeof(TUint16) : sizeof(TUint8));
       
    49 
       
    50 	if (iSixteenBitPrecision)
       
    51 		{
       
    52 		TUint16* sixteenBitPtr = (TUint16*)iValues;
       
    53 		const TUint16* sixteenBitPtrLimit = sixteenBitPtr + KJpgQTableEntries;
       
    54 		while (sixteenBitPtr < sixteenBitPtrLimit)
       
    55 		    {
       
    56 		    WriteBigEndianUint16(aData,*sixteenBitPtr++);
       
    57 		    }
       
    58 		}
       
    59 	else
       
    60 	    {
       
    61 	    Mem::Copy(aData,iValues,valuesSize);
       
    62 	    }
       
    63 
       
    64 	return valuesSize;
       
    65 	}
       
    66 
       
    67 void TQTable::SetQualityFactor(TInt aQualityFactor)
       
    68 	{
       
    69 	TInt scaleFactor = 0;
       
    70 	if (aQualityFactor < 50)
       
    71 		{
       
    72 		aQualityFactor = Max(aQualityFactor,1);
       
    73 		scaleFactor = 5000 / aQualityFactor;
       
    74 		}
       
    75 	else
       
    76 		{
       
    77 		aQualityFactor = Min(aQualityFactor,100);
       
    78 		scaleFactor = 200 - (aQualityFactor * 2);
       
    79 		}
       
    80 
       
    81 	if (iSixteenBitPrecision)
       
    82 		{
       
    83 		TUint16* qPtr = (TUint16*)iValues;
       
    84 		const TUint16* qPtrLimit = qPtr + KJpgDCTBlockSize;
       
    85 		while (qPtr < qPtrLimit)
       
    86 			{
       
    87 			TInt qValue = (qPtr[0] * scaleFactor + 50) / 100;
       
    88 			if (qValue <= 0)
       
    89 				qValue = 1;
       
    90 			if (qValue > KMaxTInt16)
       
    91 				qValue = KMaxTInt16;
       
    92 			*qPtr++ = TUint16(qValue);
       
    93 			}
       
    94 		}
       
    95 	else
       
    96 		{
       
    97         TUint8* qPtr = iValues;
       
    98         const TUint8* qPtrLimit = qPtr + KJpgDCTBlockSize;
       
    99 
       
   100 		TInt* qPtrM = iValues2;
       
   101 
       
   102 		while (qPtr < qPtrLimit)
       
   103 			{
       
   104 			TInt qValue = (qPtr[0] * scaleFactor + 50) / 100;
       
   105 			if (qValue <= 0)
       
   106 			    {
       
   107 			    qValue = 1;
       
   108 			    }
       
   109 			if (qValue > TInt(KMaxTUint8) )
       
   110 			    {
       
   111 			    qValue = KMaxTUint8;
       
   112 			    }
       
   113             *qPtrM++ = TUint16( (1 << KShift) / qValue );
       
   114 			*qPtr++ = TUint8(qValue);
       
   115 			}
       
   116 		}
       
   117 	}
       
   118 
       
   119 void TQTable::CalcQualityFactor() // Assumes the default tables have been used
       
   120 	{
       
   121 	TInt scaleFactor = 0;
       
   122 
       
   123 	if (iSixteenBitPrecision)
       
   124 		{
       
   125 		TUint16* qPtr = (TUint16*)iValues;
       
   126 		scaleFactor = qPtr[KJpgQTableEntries - 1];
       
   127 		}
       
   128 	else
       
   129 	    {
       
   130 	    scaleFactor = iValues[KJpgQTableEntries - 1];
       
   131 	    }
       
   132 		
       
   133 	if (scaleFactor > 100)
       
   134 	    {
       
   135 	    iQualityFactor = 5000 / scaleFactor;
       
   136 	    }
       
   137 	else
       
   138 	    {
       
   139 	    iQualityFactor = 100 - (scaleFactor / 2);
       
   140 	    }
       
   141 	}
       
   142 
       
   143 //
       
   144 // this section contains many performance-critical code, so use ARM instruction set for it
       
   145 //
       
   146 #ifdef __ARMCC__
       
   147 #pragma push
       
   148 #pragma arm 
       
   149 #pragma O3 
       
   150 #pragma Otime
       
   151 #endif
       
   152 
       
   153 template <class T>
       
   154 inline
       
   155 void TQTable::DoQuantize(TDataUnit& aDestination, const TDataUnit& aSource) const
       
   156     {
       
   157 	const TInt16* srcPtr = aSource.iCoeff;
       
   158 	TInt16* dstPtr = aDestination.iCoeff;
       
   159 
       
   160 	const TUint8* zigZagPtr     = KZigZagSequence.iZigZag;
       
   161 	const TUint8* zigZagPtrLimit= zigZagPtr + KJpgDCTBlockSize;
       
   162 		
       
   163 	register const T* qPtr = reinterpret_cast<const T*>(iValues);
       
   164 	
       
   165 	do 
       
   166         {
       
   167         register TInt qValue = *qPtr++;
       
   168         register TInt dstValue = srcPtr[*zigZagPtr++];
       
   169         if (dstValue > 0)
       
   170             {
       
   171             dstValue += (qValue >> 1);
       
   172             if (dstValue >= qValue)
       
   173                 {
       
   174                 dstValue /= qValue;
       
   175                 }
       
   176             else
       
   177                 {
       
   178                 dstValue = 0;
       
   179                 }
       
   180             }
       
   181         	
       
   182         else
       
   183             {
       
   184             dstValue -= (qValue >> 1);
       
   185             dstValue = -dstValue;
       
   186             if (dstValue >= qValue)
       
   187                 {
       
   188                 dstValue /= qValue;
       
   189                 dstValue = -dstValue;
       
   190                 }
       
   191             else
       
   192                 {
       
   193                 dstValue = 0;
       
   194                 }
       
   195             }
       
   196         	
       
   197         *dstPtr++ = TInt16(dstValue);
       
   198 
       
   199         } while (zigZagPtr < zigZagPtrLimit);
       
   200     }
       
   201     
       
   202 void TQTable::Quantize(TDataUnit& aDestination,const TDataUnit& aSource, TBool aHighSpeedMode) const
       
   203 	{
       
   204 	if (iSixteenBitPrecision)
       
   205 		{
       
   206 		DoQuantize<TUint16>(aDestination, aSource);
       
   207 		}
       
   208 	else
       
   209 	    {
       
   210 	    if (!aHighSpeedMode)
       
   211 	        {
       
   212 	        DoQuantize<TUint8>(aDestination, aSource);
       
   213 	        }
       
   214 	    else
       
   215 	        {
       
   216             const TInt16* srcPtr = aSource.iCoeff;
       
   217             TUint64* dstPtr = reinterpret_cast<TUint64*>(aDestination.iCoeff);
       
   218 
       
   219             const TUint8* zigZagPtr     = KZigZagSequence.iZigZag;
       
   220             const TUint8* zigZagPtrLimit= zigZagPtr + KJpgDCTBlockSize;
       
   221                   
       
   222             const TUint64* qPtr = &iValues2Aligment;
       
   223             // we do 2 values per loop iteration
       
   224             do 
       
   225                 {
       
   226                 register TAligned64Value dstValue;
       
   227 				register TAligned64Value qValue;
       
   228 				register TAligned64Value zValue;
       
   229 				zValue.iAligment = *reinterpret_cast<const TUint64*>(zigZagPtr);
       
   230                 
       
   231 				qValue.iAligment = *qPtr++;                
       
   232                                 
       
   233                 dstValue.iWord[0] = TUint16(DESCALE(srcPtr[ zValue.iByte[0] ] * qValue.iInt[0], KShift));
       
   234                 dstValue.iWord[1] = TUint16(DESCALE(srcPtr[ zValue.iByte[1] ] * qValue.iInt[1], KShift));
       
   235 
       
   236 				qValue.iAligment = *qPtr++;
       
   237 				
       
   238 				dstValue.iWord[2] = TUint16(DESCALE(srcPtr[ zValue.iByte[2] ] * qValue.iInt[0], KShift));
       
   239                 dstValue.iWord[3] = TUint16(DESCALE(srcPtr[ zValue.iByte[3] ] * qValue.iInt[1], KShift));
       
   240 
       
   241 				*dstPtr++ = dstValue.iAligment;
       
   242                 
       
   243 				qValue.iAligment = *qPtr++;                
       
   244                                 
       
   245                 dstValue.iWord[0] = TUint16(DESCALE(srcPtr[ zValue.iByte[4] ] * qValue.iInt[0], KShift));
       
   246                 dstValue.iWord[1] = TUint16(DESCALE(srcPtr[ zValue.iByte[5] ] * qValue.iInt[1], KShift));
       
   247 
       
   248 				qValue.iAligment = *qPtr++;
       
   249 				
       
   250 				dstValue.iWord[2] = TUint16(DESCALE(srcPtr[ zValue.iByte[6] ] * qValue.iInt[0], KShift));
       
   251                 dstValue.iWord[3] = TUint16(DESCALE(srcPtr[ zValue.iByte[7] ] * qValue.iInt[1], KShift));
       
   252 
       
   253 				*dstPtr++ = dstValue.iAligment;
       
   254                 
       
   255 				zigZagPtr += 8;
       
   256 				} while (zigZagPtr < zigZagPtrLimit);
       
   257 	        }
       
   258         }
       
   259 	}
       
   260 	
       
   261 void TQTable::FastHalfDeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,TInt aNumNonZeroValues) const
       
   262 	{
       
   263 	DoDeQuantize(aDestination,aSource,Min(KJpgDCTBlockSize/2, aNumNonZeroValues), KJpgDCTBlockSize/2);
       
   264 	}
       
   265 
       
   266 
       
   267 void TQTable::DeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,TInt aNumNonZeroValues) const
       
   268 	{
       
   269 	DoDeQuantize(aDestination,aSource, aNumNonZeroValues, KJpgDCTBlockSize);
       
   270 	}
       
   271 
       
   272 void TQTable::DoDeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,
       
   273 								TInt aNumNonZeroValues, TInt aBlockLen) const
       
   274 	{
       
   275 	FillCompZ(aDestination, aBlockLen );
       
   276 		
       
   277 	const TInt16* srcPtr = aSource.iCoeff;
       
   278 	const TInt16* const srcPtrLimit = srcPtr + aNumNonZeroValues;
       
   279 	TInt16* dstPtr = aDestination.iCoeff;
       
   280 	const TUint8* zigZagPtr = KZigZagSequence.iZigZag;
       
   281 	
       
   282 	if (iSixteenBitPrecision)
       
   283 		{
       
   284 		const TUint16* qPtr = (const TUint16*)iValues;
       
   285 		while (srcPtr < srcPtrLimit)
       
   286 			{
       
   287 			TInt16 v=(*srcPtr++);
       
   288 			if (v)
       
   289 				{
       
   290 				dstPtr[*zigZagPtr] = TInt16(v * (*qPtr));
       
   291 				}
       
   292 			++qPtr;
       
   293 			++zigZagPtr;
       
   294 			}
       
   295 		}
       
   296 	else
       
   297 		{
       
   298 		const TUint8* qPtr = iValues;
       
   299 		while (srcPtr < srcPtrLimit)
       
   300 			{
       
   301 			TInt16 v=*srcPtr++;
       
   302 			if (v)
       
   303 				{
       
   304 				dstPtr[*zigZagPtr] = TInt16(v* (*qPtr));
       
   305 				}
       
   306 			++zigZagPtr;
       
   307 			++qPtr;
       
   308 			}
       
   309 		}
       
   310 	}
       
   311 	
       
   312 void TQTable::FastQuarterDeQuantize(TDataUnit& aDestination,const TDataUnit& aSource,TInt /*aNumNonZeroValues*/) const
       
   313 	{
       
   314 // we're interested only in result at indeces 0,1 and 8,9 for fast 1/4 iDCT, 
       
   315 // so use excerpt of the ZigZag table:
       
   316 // 0, 1, 8,	16,	9
       
   317 //	
       
   318 	const TInt16* srcPtr = aSource.iCoeff;
       
   319 					
       
   320 	TInt16* dstPtr = aDestination.iCoeff;
       
   321 	
       
   322 	if (iSixteenBitPrecision)
       
   323 		{
       
   324 		const TUint16* qPtr = (const TUint16*)iValues;
       
   325 
       
   326 		dstPtr[0] = TInt16(srcPtr[0] * qPtr[0]);
       
   327 		dstPtr[1] = TInt16(srcPtr[1] * qPtr[1]);
       
   328 		dstPtr[8] = TInt16(srcPtr[2] * qPtr[2]);
       
   329 		dstPtr[9] = TInt16(srcPtr[4] * qPtr[4]);
       
   330 
       
   331 		}
       
   332 	else
       
   333 		{
       
   334 		const TUint8* qPtr = iValues;
       
   335 		dstPtr[0] = TInt16(srcPtr[0] * qPtr[0]);
       
   336 		dstPtr[1] = TInt16(srcPtr[1] * qPtr[1]);
       
   337 		dstPtr[8] = TInt16(srcPtr[2] * qPtr[2]);
       
   338 		dstPtr[9] = TInt16(srcPtr[4] * qPtr[4]);
       
   339 		}	
       
   340 	}
       
   341 
       
   342 #ifdef __ARMCC__
       
   343 #pragma pop
       
   344 #endif
       
   345