imagingandcamerafws/imaginginttest/Codecs/PPM1/PPM1Codec.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 1999-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 <fbs.h>
       
    17 #include "PPM1Codec.h"
       
    18 #include "pluginextensionmanager.h"
       
    19 
       
    20 const TInt KRAWBytesPerPixel = 3;
       
    21 
       
    22 // CPpmReadCodec
       
    23 
       
    24 CPpmReadCodec* CPpmReadCodec::NewL(CPpmDecoder& aDecoder)
       
    25 	{
       
    26 	CPpmReadCodec* result = new (ELeave) CPpmReadCodec(aDecoder);
       
    27 	CleanupStack::PushL(result);
       
    28 	result->ConstructL();
       
    29 	CleanupStack::Pop(result);
       
    30 	return result;
       
    31 	}
       
    32 
       
    33 
       
    34 CPpmReadCodec::CPpmReadCodec(CPpmDecoder& aDecoder):
       
    35 	iDecoder(&aDecoder)
       
    36 	{}
       
    37 
       
    38 CPpmReadCodec::~CPpmReadCodec()
       
    39 	{
       
    40 	}
       
    41 
       
    42 TFrameState CPpmReadCodec::ProcessFrameL(TBufPtr8& aSrc)
       
    43 	{
       
    44 	const TUint8* srcStart = aSrc.Ptr();
       
    45 	iDataPtr = srcStart;
       
    46 	iDataPtrLimit = srcStart + aSrc.Length();
       
    47 	
       
    48 	TInt bytesUsed = 0;
       
    49 	if(!iSeekRequested)
       
    50 		{
       
    51 		if (iDecoder->Compressed())
       
    52 			{
       
    53 			DoProcessCompressed();
       
    54 			bytesUsed = iDataPtr - srcStart;
       
    55 			}
       
    56 		else
       
    57 			{
       
    58 			TLex8 lex (aSrc);
       
    59 			TRAPD(error, DoProcessUncompressedL(lex));
       
    60 			if (error!=KErrNone && error!=KErrGeneral && error!=KErrUnderflow) // trap for insufficient data
       
    61 				{
       
    62 				User::Leave(error);
       
    63 				}
       
    64 			bytesUsed = lex.MarkedOffset();
       
    65 			}
       
    66 
       
    67 		aSrc.Shift(bytesUsed);
       
    68 		}
       
    69 
       
    70 	if (iPixelsProcessed >= iPixelsExpected)
       
    71 		{
       
    72 		return EFrameComplete;
       
    73 		}
       
    74 	
       
    75 	if(iSeekRequested)
       
    76 		{
       
    77 		/*
       
    78 		Move the pointer to the end of the buffer.  This is to 
       
    79 		workaround a problem with the ICL framework, where if we
       
    80 		choose to seek and haven't incremented the pointer, then
       
    81 		it returns KErrUnderflow.  Thus, the first seek (when 
       
    82 		cropping) will fail.
       
    83 		*/
       
    84 		TInt bytesRemainingInBuffer = Min(iNewBytePosition, iDataPtrLimit - iDataPtr);
       
    85 		aSrc.Shift(bytesRemainingInBuffer);
       
    86 		iNewBytePosition -= bytesRemainingInBuffer;
       
    87 		iSeekRequested = EFalse;
       
    88 		return EFrameIncompleteRepositionRequest;
       
    89 		}
       
    90 		
       
    91 	return EFrameIncomplete;
       
    92 	}
       
    93 
       
    94 void CPpmReadCodec::Complete()
       
    95 	{
       
    96 	ImageProcessor()->FlushPixels(); 
       
    97 	}
       
    98 
       
    99 void CPpmReadCodec::DoProcessUncompressedL(TLex8 &aLex)
       
   100 	{
       
   101 	CImageProcessor*const imageProc = ImageProcessor();
       
   102 	for (;;) // exit of this will be a leave
       
   103 		{
       
   104 		TUint rVal;
       
   105 		iDecoder->SkipCommentAndWhiteSpaceL(aLex);
       
   106 		ASSERT(!iDecoder->InComment());
       
   107 		User::LeaveIfError(aLex.Val(rVal));
       
   108 		TUint gVal;
       
   109 		iDecoder->SkipCommentAndWhiteSpaceL(aLex);
       
   110 		ASSERT(!iDecoder->InComment());
       
   111 		User::LeaveIfError(aLex.Val(gVal));
       
   112 		TUint bVal;
       
   113 		iDecoder->SkipCommentAndWhiteSpaceL(aLex);
       
   114 		ASSERT(!iDecoder->InComment());
       
   115 		User::LeaveIfError(aLex.Val(bVal));
       
   116 
       
   117 		TInt dataShift = iDecoder->DataShift();
       
   118 		TRgb rgb (rVal<<dataShift, gVal<<dataShift, bVal<<dataShift);
       
   119 
       
   120 		imageProc->SetPixel(rgb);
       
   121 
       
   122 		aLex.Mark(); // show we've got this far - on error, only wind back this far.
       
   123 
       
   124 		iPixelsProcessed += 1;
       
   125 		}
       
   126 	}
       
   127 
       
   128 void CPpmReadCodec::DoProcessCompressed()
       
   129 	{
       
   130 	CImageProcessor*const imageProc = ImageProcessor();
       
   131 	
       
   132 	while (iDataPtr < iDataPtrLimit-2)
       
   133 		{
       
   134 		TUint8 rVal = iDataPtr[0];
       
   135 		TUint8 gVal = iDataPtr[1];
       
   136 		TUint8 bVal = iDataPtr[2];
       
   137 		iDataPtr += KRAWBytesPerPixel;
       
   138 		
       
   139 		TInt dataShift = iDecoder->DataShift();
       
   140 		TRgb rgb (rVal<<dataShift, gVal<<dataShift, bVal<<dataShift);
       
   141 
       
   142 		imageProc->SetPos(iCurrentPosition);
       
   143 		imageProc->SetPixel(rgb);
       
   144 		iPixelsProcessed += 1;
       
   145 		
       
   146 		if(iXAxisFirst)
       
   147 			{
       
   148 			iCurrentPosition.iX += iXAxisIncrement;
       
   149 			if(iCurrentPosition.iX == iEndPosition.iX)
       
   150 				{
       
   151 				iCurrentPosition.iX = iStartPosition.iX;
       
   152 				iCurrentPosition.iY += iYAxisIncrement;
       
   153 				if(iExtensionManager->ClippingRectExtensionRequested())
       
   154 					{
       
   155 					// Clipping is required, so need to skip position in buffer
       
   156 					iSeekRequested = ETrue;
       
   157 					iNewBytePosition = iFrameInfo->iOverallSizeInPixels.iWidth - iExtensionManager->ClippingRect().Size().iWidth;
       
   158 					iNewBytePosition *= KRAWBytesPerPixel;
       
   159 					break;
       
   160 					}
       
   161 				}
       
   162 			}
       
   163 		else
       
   164 			{
       
   165 			iCurrentPosition.iY += iYAxisIncrement;
       
   166 			if(iCurrentPosition.iY == iEndPosition.iY)
       
   167 				{
       
   168 				iCurrentPosition.iY = iStartPosition.iY;
       
   169 				iCurrentPosition.iX += iXAxisIncrement;
       
   170 				if(iExtensionManager->ClippingRectExtensionRequested())
       
   171 					{
       
   172 					// Clipping is required, so need to skip position in buffer
       
   173 					iSeekRequested = ETrue;
       
   174 					iNewBytePosition = iFrameInfo->iOverallSizeInPixels.iWidth - iExtensionManager->ClippingRect().Size().iWidth;
       
   175 					iNewBytePosition *= KRAWBytesPerPixel;
       
   176 					break;
       
   177 					}
       
   178 				}
       
   179 			}
       
   180 		}
       
   181 	}
       
   182 
       
   183 void CPpmReadCodec::InitFrameL(TFrameInfo& /*aFrameInfo*/, CFrameImageData& /*aFrameImageData*/, TBool aDisableErrorDiffusion, CFbsBitmap& aFrame, CFbsBitmap* /*aDestinationMask*/)
       
   184 	{
       
   185 	ASSERT(iFrameInfo);
       
   186 	ASSERT(iExtensionManager);
       
   187 	
       
   188 	/*
       
   189 	This function is used by both compressed and uncompressed format, although some of the
       
   190 	calls aren't stricly necessary for the uncompressed format (since extensions are not
       
   191 	supported, except for the GetDestinationSize() call).
       
   192 	*/
       
   193 	
       
   194 	User::LeaveIfError(ValidateDestinationSize(aFrame.SizeInPixels()));
       
   195 	
       
   196 	TSize finalSize = iExtensionManager->ClippingRectExtensionRequested() ?
       
   197 					  iExtensionManager->ClippingRect().Size() : iFrameInfo->iOverallSizeInPixels;
       
   198 	if(iExtensionManager->DimensionsSwapped())
       
   199 		{
       
   200 		finalSize.SetSize(finalSize.iHeight, finalSize.iWidth);
       
   201 		}
       
   202 	
       
   203 	TInt scalingCoefficient = ScalingCoefficientL(finalSize, aFrame.SizeInPixels());
       
   204 	TInt reductionFactor = CPluginExtensionManager::ConvertScalingCoeffToReductionFactor(scalingCoefficient);
       
   205 	
       
   206 	CImageProcessorExtension* imageProc = 
       
   207 		ImageProcessorUtility::NewImageProcessorExtensionL(aFrame, reductionFactor, iFrameInfo->iFrameDisplayMode, aDisableErrorDiffusion);
       
   208 	SetImageProcessor(imageProc);
       
   209 
       
   210 	iExtensionManager->TransferExtensionDataL(imageProc);
       
   211 	// Pass in full size of image or clip rect
       
   212 	imageProc->PrepareL(aFrame, finalSize);
       
   213 	
       
   214 	// Set up member variables if Operations have been requested
       
   215 	SetOperationData(finalSize);
       
   216 
       
   217 	ClearBitmapL(aFrame, KRgbWhite);
       
   218 		// do something sensible for partial streamed decodes
       
   219 		
       
   220 	iPixelsProcessed = 0;
       
   221 	iPixelsExpected = finalSize.iWidth * finalSize.iHeight;
       
   222 
       
   223 	// Determine how many pixels to skip on the Y axis of the original, if any
       
   224 	TInt pixelsToSkip = iFrameInfo->iFrameCoordsInPixels.iBr.iX * iExtensionManager->ClippingRect().iTl.iY;
       
   225 	// Add X axis pixels on the left side of the crop rect, if any
       
   226 	pixelsToSkip += iExtensionManager->ClippingRect().iTl.iX - iFrameInfo->iFrameCoordsInPixels.iTl.iX;
       
   227 
       
   228 	iNewBytePosition = pixelsToSkip*KRAWBytesPerPixel;
       
   229 	iSeekRequested = iNewBytePosition > 0 ? ETrue : EFalse;	
       
   230 	
       
   231 	iDecoder->SetInComment(EFalse);
       
   232 	}
       
   233 	
       
   234 void CPpmReadCodec::InitFrameHeader(TFrameInfo& aFrameInfo, CFrameImageData& /*aFrameData*/)
       
   235 	{
       
   236 	ASSERT(aFrameInfo.CurrentFrameState() == TFrameInfo::EFrameInfoUninitialised);
       
   237 	iFrameInfo = &aFrameInfo;
       
   238 	aFrameInfo.SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingFrameHeader);
       
   239 	}
       
   240 
       
   241 TFrameState CPpmReadCodec::ProcessFrameHeaderL(TBufPtr8&/* aData*/)
       
   242 	{
       
   243 	ASSERT(iFrameInfo);
       
   244 	iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingComplete);
       
   245 	return EFrameComplete;
       
   246 	}
       
   247 
       
   248 void CPpmReadCodec::GetNewDataPosition(TInt &aPosition, TInt &/*aLength*/)
       
   249 	{
       
   250 	aPosition += iNewBytePosition;
       
   251 	}
       
   252 
       
   253 void CPpmReadCodec::SetExtensionManager(CPluginExtensionManager* aExtensionManager)
       
   254 	{
       
   255 	// Is owned by the plugin, not this codec
       
   256 	iExtensionManager = aExtensionManager;
       
   257 	}
       
   258 
       
   259 TInt CPpmReadCodec::ValidateDestinationSize(const TSize& aDestSize) const
       
   260 	{
       
   261 	ASSERT(iExtensionManager);
       
   262 	
       
   263 	TInt err = KErrNone;
       
   264 	if(iExtensionManager->ScalerExtensionRequested())
       
   265 		{
       
   266 		TSize destSizeCheck = iFrameInfo->iOverallSizeInPixels;
       
   267 		err = iExtensionManager->GetDestinationSize(destSizeCheck);
       
   268 		if(err == KErrNone)
       
   269 			{
       
   270 			// Mandatory check that the destination size matches the calculated size
       
   271 			if(destSizeCheck != aDestSize)
       
   272 				{
       
   273 				err = KErrArgument;
       
   274 				}	
       
   275 			}
       
   276 		}
       
   277 	return err;
       
   278 	}
       
   279 
       
   280 TInt CPpmReadCodec::ScalingCoefficientL(const TSize& aDestinationSize, const TSize& aFrameSize) const
       
   281 	{
       
   282 	ASSERT(iExtensionManager);
       
   283 	
       
   284 	TInt scalingCoefficient = -1; // initialise to full size
       
   285 	if(iExtensionManager->ScalerExtensionRequested())
       
   286 		{
       
   287 		// Explicit scaling
       
   288 		User::LeaveIfError(iExtensionManager->GetScalingCoefficient(scalingCoefficient, &aDestinationSize));
       
   289 		}
       
   290 	else
       
   291 		{
       
   292 		// Implicit scaling
       
   293 		scalingCoefficient = ScalingCoefficient(aDestinationSize, aFrameSize);
       
   294 		}
       
   295 	return scalingCoefficient;
       
   296 	}
       
   297 
       
   298 void CPpmReadCodec::SetOperationData(const TRect& aDestinationBitmap)
       
   299 	{
       
   300 	ASSERT(iExtensionManager);
       
   301 	ASSERT(!aDestinationBitmap.IsEmpty());
       
   302 	ASSERT(aDestinationBitmap.IsNormalized());
       
   303 
       
   304 	/*
       
   305 	Note that iStartPosition is the starting point and so needs to
       
   306 	be INSIDE the TRect, whereas iEndPosition is the end point and thus
       
   307 	lies diagonally opposite the start point, and OUTSIDE the TRect.
       
   308 	
       
   309 		-----------------
       
   310 		|tlo|   |   |tro
       
   311 		-----------------
       
   312 		|   |tli|tri|   |
       
   313 		-----------------
       
   314 		|   |bli|bri|   |
       
   315 		-----------------
       
   316 		|blo|   |   |bro|
       
   317 		-----------------
       
   318 		
       
   319 		tlo = top left outside image
       
   320 		tro = top right outside image
       
   321 		blo = bottom left outside image
       
   322 		bro = bottom right outside image (i.e. iBr)
       
   323 		
       
   324 		tli = top left inside image (i.e. iTl)
       
   325 		tri = top right inside image
       
   326 		bli = bottom left inside image
       
   327 		bri = bottom right inside image
       
   328 	*/
       
   329 	TPoint tlOutsideImageRegion(aDestinationBitmap.iTl.iX - 1, aDestinationBitmap.iTl.iY - 1);
       
   330 	TPoint trOutsideImageRegion(aDestinationBitmap.iBr.iX, aDestinationBitmap.iTl.iY - 1);
       
   331 	TPoint blOutsideImageRegion(aDestinationBitmap.iTl.iX - 1, aDestinationBitmap.iBr.iY);
       
   332 	TPoint brOutsideImageRegion(aDestinationBitmap.iBr.iX, aDestinationBitmap.iBr.iY);	
       
   333 	TPoint tlInsideImageRegion(aDestinationBitmap.iTl.iX, aDestinationBitmap.iTl.iY);
       
   334 	TPoint trInsideImageRegion(aDestinationBitmap.iBr.iX - 1, aDestinationBitmap.iTl.iY);
       
   335 	TPoint blInsideImageRegion(aDestinationBitmap.iTl.iX, aDestinationBitmap.iBr.iY - 1);
       
   336 	TPoint brInsideImageRegion(aDestinationBitmap.iBr.iX - 1, aDestinationBitmap.iBr.iY - 1);
       
   337 
       
   338 	switch(iExtensionManager->Operation())
       
   339 		{
       
   340 		case EDecodeNormal:
       
   341 			iStartPosition = tlInsideImageRegion;
       
   342 			iCurrentPosition = iStartPosition;
       
   343 			iEndPosition = brOutsideImageRegion;
       
   344 			iXAxisIncrement = 1;
       
   345 			iYAxisIncrement = 1;
       
   346 			iXAxisFirst = ETrue;
       
   347 			break;
       
   348 		case EDecodeRotate90:
       
   349 			iStartPosition = trInsideImageRegion;
       
   350 			iCurrentPosition = iStartPosition;
       
   351 			iEndPosition = blOutsideImageRegion;
       
   352 			iXAxisIncrement = -1;
       
   353 			iYAxisIncrement = 1;
       
   354 			iXAxisFirst = EFalse;
       
   355 			break;
       
   356 		case EDecodeRotate180:
       
   357 			iStartPosition = brInsideImageRegion;
       
   358 			iCurrentPosition = iStartPosition;
       
   359 			iEndPosition = tlOutsideImageRegion;
       
   360 			iXAxisIncrement = -1;
       
   361 			iYAxisIncrement = -1;
       
   362 			iXAxisFirst = ETrue;
       
   363 			break;
       
   364 		case EDecodeRotate270:
       
   365 			iStartPosition = blInsideImageRegion;
       
   366 			iCurrentPosition = iStartPosition;
       
   367 			iEndPosition = trOutsideImageRegion;
       
   368 			iXAxisIncrement = 1;
       
   369 			iYAxisIncrement = -1;
       
   370 			iXAxisFirst = EFalse;
       
   371 			break;
       
   372 		case EDecodeHorizontalFlip:
       
   373 			iStartPosition = blInsideImageRegion;
       
   374 			iCurrentPosition = iStartPosition;
       
   375 			iEndPosition = trOutsideImageRegion;
       
   376 			iXAxisIncrement = 1;
       
   377 			iYAxisIncrement = -1;
       
   378 			iXAxisFirst = ETrue;
       
   379 			break;
       
   380 		case EDecodeHorizontalFlipRotate90:
       
   381 			iStartPosition = tlInsideImageRegion;
       
   382 			iCurrentPosition = iStartPosition;
       
   383 			iEndPosition = brOutsideImageRegion;
       
   384 			iXAxisIncrement = 1;
       
   385 			iYAxisIncrement = 1;
       
   386 			iXAxisFirst = EFalse;
       
   387 			break;
       
   388 		case EDecodeVerticalFlip:
       
   389 			iStartPosition = trInsideImageRegion;
       
   390 			iCurrentPosition = iStartPosition;
       
   391 			iEndPosition = blOutsideImageRegion;
       
   392 			iXAxisIncrement = -1;
       
   393 			iYAxisIncrement = 1;
       
   394 			iXAxisFirst = ETrue;
       
   395 			break;
       
   396 		case EDecodeVerticalFlipRotate90:
       
   397 			iStartPosition = brInsideImageRegion;
       
   398 			iCurrentPosition = iStartPosition;
       
   399 			iEndPosition = tlOutsideImageRegion;
       
   400 			iXAxisIncrement = -1;
       
   401 			iYAxisIncrement = -1;
       
   402 			iXAxisFirst = EFalse;
       
   403 			break;
       
   404 		default:
       
   405 			{
       
   406 			ASSERT(EFalse);
       
   407 			}
       
   408 		}
       
   409 	}
       
   410 
       
   411 // CPpm1WriteCodec
       
   412 
       
   413 const TInt KMaxColourValue = 255;
       
   414 
       
   415 CPpm1WriteCodec::CPpm1WriteCodec()
       
   416 	{}
       
   417 
       
   418 CPpm1WriteCodec::~CPpm1WriteCodec()
       
   419 	{}
       
   420 
       
   421 void CPpm1WriteCodec::ConstructL()
       
   422 	{
       
   423 	CImageWriteCodec::ConstructL();
       
   424 	}
       
   425 
       
   426 CPpm1WriteCodec* CPpm1WriteCodec::NewL()
       
   427 	{
       
   428 	CPpm1WriteCodec* result = new (ELeave) CPpm1WriteCodec;
       
   429 	CleanupStack::PushL(result);
       
   430 	result->ConstructL();
       
   431 	CleanupStack::Pop(result);
       
   432 	return result;
       
   433 	}
       
   434 
       
   435 void CPpm1WriteCodec::InitFrameL(TBufPtr8& aDst, const CFbsBitmap& aSource)
       
   436 	{
       
   437 	SetSource(&aSource);
       
   438 	iDestStartPtr = const_cast<TUint8*>(aDst.Ptr());
       
   439 	iDestPtr = iDestStartPtr;
       
   440 	iDestPtrLimit = iDestPtr + aDst.MaxLength();
       
   441 
       
   442 	TSize size = aSource.SizeInPixels();
       
   443 	iSourceRect = TRect(size);
       
   444 	iPos.SetXY(0,0);
       
   445 
       
   446 	TBuf8<256> header; // set up header in buffer
       
   447 	header.Zero();
       
   448 
       
   449 	// now the standard header lines
       
   450 	_LIT8(KMagicHeader, "P6\n");
       
   451 	header.AppendFormat(KMagicHeader); // ppm magic for compressed
       
   452 	_LIT8(KSizeHeader, "%d %d\n");
       
   453 	header.AppendFormat(KSizeHeader, size.iWidth, size.iHeight);
       
   454 	_LIT8(KMaxValueHeader, "%d\n");
       
   455 	header.AppendFormat(KMaxValueHeader, KMaxColourValue);
       
   456 
       
   457 	TInt headerSize = header.Length();
       
   458 	aDst.Copy(header);
       
   459 	iDestPtr+=headerSize;
       
   460 
       
   461 	ASSERT(iDestPtr < iDestPtrLimit); // should always be true
       
   462 	}
       
   463 
       
   464 TFrameState CPpm1WriteCodec::ProcessFrameL(TBufPtr8& aDst)
       
   465 	{
       
   466 	//Setup buffer to use all available space
       
   467 	TUint8* destStartPtr = CONST_CAST(TUint8*,aDst.Ptr());
       
   468 	iDestPtr = destStartPtr;
       
   469 	iDestPtrLimit = iDestPtr + aDst.MaxLength();
       
   470 
       
   471 	DoProcessL(*Source());
       
   472 
       
   473 	aDst.SetLength(iDestPtr - destStartPtr);
       
   474 
       
   475 	// If processed all pixels
       
   476 	if (iPos.iY < iSourceRect.iTl.iY)
       
   477 		{
       
   478 		return EFrameComplete;
       
   479 		}
       
   480 		
       
   481 	return EFrameIncomplete;
       
   482 	}
       
   483 
       
   484 void CPpm1WriteCodec::DoProcessL(const CFbsBitmap& aFrame)
       
   485 	{
       
   486 	TUint8* safeDestPtrLimit = iDestPtrLimit - 2;
       
   487 
       
   488 	while (iDestPtr < safeDestPtrLimit)
       
   489 		{
       
   490 		if (iPos.iY >= iSourceRect.iBr.iY)
       
   491 			{
       
   492 			break;
       
   493 			}
       
   494 			
       
   495 		TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) / 3);
       
   496 		TInt dstLength = scanLength * 3;
       
   497 		TPtr8 dstBuf(iDestPtr, dstLength, dstLength);
       
   498 
       
   499 		aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor16M);
       
   500 		// this comes out in order BGR, so switch
       
   501 		SwitchRGB(dstBuf);
       
   502 
       
   503 		iPos.iX += scanLength;
       
   504 		iDestPtr += dstLength;
       
   505 
       
   506 		if (iPos.iX == iSourceRect.iBr.iX)
       
   507 			{
       
   508 			iPos.iX = iSourceRect.iTl.iX;
       
   509 			iPos.iY++;
       
   510 			}
       
   511 		}
       
   512 	}
       
   513 
       
   514 // Assume original has pixels with BGR in order - switch to RGB
       
   515 void CPpm1WriteCodec::SwitchRGB(TDes8 &aBuf)
       
   516 	{
       
   517 	TUint8* buf = const_cast<TUint8*>(aBuf.Ptr());
       
   518 	TUint8* bufMax = buf + aBuf.Length();
       
   519 
       
   520 	while (buf<bufMax)
       
   521 		{
       
   522 		TUint8 b = buf[0];
       
   523 		TUint8 g = buf[1];
       
   524 		TUint8 r = buf[2];
       
   525 		buf[0] = r;
       
   526 		buf[1] = g;
       
   527 		buf[2] = b;
       
   528 
       
   529 		buf += 3; 
       
   530 		}
       
   531 	}
       
   532 
       
   533