imaging/imagingplugins/codecs/ICOCodec/icomaskprocessor.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     1 // Copyright (c) 2008-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 "icomaskprocessor.h"
       
    18 
       
    19 const TInt 	KIcoMaskProcessorBufferSize = 1024; // size matches that of the CPixelWriter buffer
       
    20 const TUint KRGBMask = 0x00FFFFFF;
       
    21 const TInt	KAlphaShift = 24;
       
    22 
       
    23 CIcoMaskProcessor* CIcoMaskProcessor::NewL(TInt aReductionFactor)
       
    24 	{
       
    25 	return new (ELeave) CIcoMaskProcessor(aReductionFactor);
       
    26 	}
       
    27 
       
    28 CIcoMaskProcessor::CIcoMaskProcessor(TInt aReductionFactor)
       
    29 :iReductionFactor(aReductionFactor)
       
    30 	{
       
    31 	}
       
    32 
       
    33 CIcoMaskProcessor::~CIcoMaskProcessor()
       
    34 	{
       
    35 	Reset();
       
    36 	}
       
    37 
       
    38 void CIcoMaskProcessor::Reset()
       
    39 	{
       
    40 	iReductionFactor = 0;
       
    41 	iImageRegion.SetRect(0,0,0,0);
       
    42 	iPosition.SetXY(0,0);
       
    43 	iScaledPosition.SetXY(0,0);
       
    44 	iYIncrement = 0;
       
    45 	iPixelPadding = 0;
       
    46 	iPixelsToSkip = 0;
       
    47 	delete[] iMaskBuffer;
       
    48 	iMaskBuffer = NULL;
       
    49 	delete[] iScaledMaskBuffer;
       
    50 	iScaledMaskBuffer = NULL;
       
    51 	}
       
    52 
       
    53 void CIcoMaskProcessor::PrepareL(CFbsBitmap& aBitmap,const TRect& aImageRect)
       
    54 	{
       
    55 	ASSERT(aImageRect.Width() != 0);
       
    56 	ASSERT(aImageRect.Height() != 0);
       
    57 	ASSERT(iMaskBuffer == NULL);
       
    58 	
       
    59 	iDestBitmap = &aBitmap;
       
    60 	iImageRegion = aImageRect;
       
    61 	
       
    62 	if(iReductionFactor)
       
    63 		{
       
    64 		// Create the buffer to hold the unscaled pixels.
       
    65 		iMaskBuffer = new (ELeave) TRgb[KIcoMaskProcessorBufferSize >> iReductionFactor];
       
    66 		iMaskBufferPtr = iMaskBuffer;
       
    67 		iMaskBufferPtrLimit = iMaskBuffer + (KIcoMaskProcessorBufferSize >> iReductionFactor);
       
    68 		
       
    69 		// Create the buffer to hold the 'merged' pixel values, represented by TMonochromeSum.
       
    70 		TInt scaledBufferSize = (iImageRegion.iBr.iX + (1<<iReductionFactor) -1 ) >> iReductionFactor;
       
    71 		iScaledMaskBuffer = new (ELeave) TMonochromeSum[scaledBufferSize];
       
    72 		iScaledMaskBufferPtrLimit = iScaledMaskBuffer + scaledBufferSize;
       
    73 		Mem::FillZ(iScaledMaskBuffer, scaledBufferSize * sizeof(TMonochromeSum));
       
    74 		}
       
    75 	else
       
    76 		{
       
    77 		// Create the buffer to hold the unscaled pixels.
       
    78 		iMaskBuffer = new (ELeave) TRgb[KIcoMaskProcessorBufferSize];
       
    79 		iMaskBufferPtr = iMaskBuffer;
       
    80 		iMaskBufferPtrLimit = iMaskBuffer + KIcoMaskProcessorBufferSize;
       
    81 		}
       
    82 	}
       
    83 
       
    84 void CIcoMaskProcessor::PrepareL(CFbsBitmap& /*aBitmap*/, const TRect& /*aImageRect*/, const TSize& /*aRgbBlockSize*/)
       
    85 	{
       
    86 	ASSERT(EFalse);
       
    87 	}
       
    88 
       
    89 // ICO data is stored from bottom-up, so iYIncrement is negative (draw bottom-up).
       
    90 void CIcoMaskProcessor::SetYPosIncrement(TInt aYInc)
       
    91 	{
       
    92 	iYIncrement = aYInc;
       
    93 	}
       
    94 
       
    95 void CIcoMaskProcessor::SetLineRepeat(TInt /*aLineRepeat*/)
       
    96 	{
       
    97 	ASSERT(EFalse);
       
    98 	}
       
    99 
       
   100 /*
       
   101 ICO data contains padding.  Each mask pixel is represented by 1 bit, thus there
       
   102 can be up to 31 bits of padding in the decoded data buffer to skip.
       
   103 */
       
   104 void CIcoMaskProcessor::SetPixelPadding(TInt aNumberOfPixels)
       
   105 	{
       
   106 	iPixelPadding = aNumberOfPixels;
       
   107 	}
       
   108 
       
   109 /*
       
   110 Function to handle a mask pixel, and thus is either fully opauq white (0xFFFFFFFF) or fully
       
   111 transparent black (0x00000000).
       
   112 */
       
   113 TBool CIcoMaskProcessor::SetPixel(TRgb aColor)
       
   114 	{
       
   115 	if(iReductionFactor)
       
   116 		{
       
   117 		if(iScaledPosition.iX < iImageRegion.Width()) // Ignore decoded padding
       
   118 			{
       
   119 			// When scaling by half, for example, take every other pixel on the first two lines and
       
   120 			// sum their values.  This is then processed later into a single pixel value.
       
   121 			TMonochromeSum* sumPtr = iScaledMaskBuffer + (iScaledPosition.iX >> iReductionFactor);
       
   122 			sumPtr->iLevel += TColorConvertor::RgbToMonochrome(aColor);
       
   123 			sumPtr->iCount++;
       
   124 			}
       
   125 		
       
   126 		iScaledPosition.iX++;
       
   127 				
       
   128 		if(iScaledPosition.iX == iImageRegion.Width() + iPixelPadding)
       
   129 			{
       
   130 			TInt newY = iScaledPosition.iY + iYIncrement;
       
   131 			TBool outsideOfBuffer = ((newY ^ iScaledPosition.iY) >> iReductionFactor) != 0;
       
   132 			
       
   133 			iScaledPosition.iY = newY;
       
   134 			iScaledPosition.iX = 0;
       
   135 			
       
   136 			if(outsideOfBuffer)
       
   137 				{
       
   138 				return FlushPixels();
       
   139 				}
       
   140 			}
       
   141 		}
       
   142 	else
       
   143 		{
       
   144 		*iMaskBufferPtr++ = aColor;
       
   145 		if(iMaskBufferPtr == iMaskBufferPtrLimit)
       
   146 			{		
       
   147 			return FlushPixels();
       
   148 			}
       
   149 		}
       
   150 
       
   151 	return EFalse;
       
   152 	}
       
   153 
       
   154 TBool CIcoMaskProcessor::SetPixelRun(TRgb /*aColor*/, TInt /*aCount*/)
       
   155 	{
       
   156 	ASSERT(EFalse);
       
   157 	return EFalse;
       
   158 	}
       
   159 
       
   160 TBool CIcoMaskProcessor::SetPixels(TRgb* /*aColorBuffer*/, TInt /*aBufferLength*/)
       
   161 	{
       
   162 	ASSERT(EFalse);
       
   163 	return EFalse;
       
   164 	}
       
   165 
       
   166 TBool CIcoMaskProcessor::SetPixelBlock(TRgb* /*aColorBuffer*/)
       
   167 	{
       
   168 	ASSERT(EFalse);
       
   169 	return EFalse;
       
   170 	}
       
   171 
       
   172 TBool CIcoMaskProcessor::SetMonoPixel(TInt /*aGray256*/)
       
   173 	{
       
   174 	ASSERT(EFalse);
       
   175 	return EFalse;
       
   176 	}
       
   177 
       
   178 TBool CIcoMaskProcessor::SetMonoPixelRun(TInt /*aGray256*/, TInt /*aCount*/)
       
   179 	{
       
   180 	ASSERT(EFalse);
       
   181 	return EFalse;
       
   182 	}
       
   183 
       
   184 TBool CIcoMaskProcessor::SetMonoPixels(TUint32* /*aGray256Buffer*/, TInt /*aBufferLength*/)
       
   185 	{
       
   186 	ASSERT(EFalse);
       
   187 	return EFalse;
       
   188 	}
       
   189 
       
   190 TBool CIcoMaskProcessor::SetMonoPixelBlock(TUint32* /*aGray256Buffer*/)
       
   191 	{
       
   192 	ASSERT(EFalse);
       
   193 	return EFalse;
       
   194 	}
       
   195 
       
   196 TBool CIcoMaskProcessor::SetPos(const TPoint& aPosition)
       
   197 	{
       
   198 	iPosition.SetXY(aPosition.iX >> iReductionFactor, aPosition.iY >> iReductionFactor);
       
   199 	iScaledPosition = aPosition;
       
   200 	return ETrue;
       
   201 	}
       
   202 /*
       
   203 Converts the pixel values in the internally held iScaledMaskBuffer into a single pixel value which is then
       
   204 added to the iMaskBuffer.
       
   205 */
       
   206 void CIcoMaskProcessor::ProcessScaledPixels()
       
   207 	{
       
   208 	TMonochromeSum* scaledSumPtr = iScaledMaskBuffer;
       
   209 	TMonochromeSum* scaledSumPtrLimit = iScaledMaskBuffer + (iImageRegion.Width() >> iReductionFactor);
       
   210 	TRgb* maskBufferPtr = iMaskBuffer;
       
   211 	
       
   212 	TInt fullCountFactor = 2 * iReductionFactor;
       
   213 	TInt fullCount = 1 << fullCountFactor;
       
   214 
       
   215 	do
       
   216 		{		
       
   217 		TInt level = scaledSumPtr->iLevel;
       
   218 		TInt count = scaledSumPtr->iCount;
       
   219 
       
   220 		if(count == fullCount)
       
   221 			{
       
   222 			level >>= fullCountFactor;
       
   223 			}
       
   224 		else if(count!=0)
       
   225 			{
       
   226 			level /= count;
       
   227 			}
       
   228 		else
       
   229 			break;
       
   230 
       
   231 		maskBufferPtr->SetInternal(level);
       
   232 		maskBufferPtr++;
       
   233 
       
   234 		scaledSumPtr++;
       
   235 		}
       
   236 	while(scaledSumPtr < scaledSumPtrLimit);
       
   237 	
       
   238 	iMaskBufferPtr = maskBufferPtr;
       
   239 	
       
   240 	TInt numPixels = scaledSumPtr - iScaledMaskBuffer;
       
   241 	Mem::FillZ(iScaledMaskBuffer, numPixels * sizeof(TMonochromeSum));
       
   242 	}
       
   243 
       
   244 TBool CIcoMaskProcessor::FlushPixels()
       
   245 	{
       
   246 	if(iReductionFactor)
       
   247 		{
       
   248 		ProcessScaledPixels();
       
   249 		}
       
   250 	
       
   251 	return DoFlushPixels();
       
   252 	}
       
   253 
       
   254 /*
       
   255 The pixelvalues (i.e. mask values) in the iMaskBuffer are added to the RGB colour values held in the
       
   256 destination bitmap (which have been put there by another image processor), and then put back into the
       
   257 destination bitmap.
       
   258 */
       
   259 TBool CIcoMaskProcessor::DoFlushPixels()
       
   260 	{
       
   261 	TRgb* maskBufferPtrLimit = iMaskBufferPtr;
       
   262 	iMaskBufferPtr = iMaskBuffer; // reset pointer
       
   263 	
       
   264 	TBitmapUtil bitmapUtil(iDestBitmap);
       
   265 	bitmapUtil.Begin(iPosition);
       
   266 	
       
   267 	for(TRgb* maskBufferPtr = iMaskBuffer; maskBufferPtr < maskBufferPtrLimit; maskBufferPtr++)
       
   268 		{		
       
   269 		TInt skip = Min(iPixelsToSkip, maskBufferPtrLimit - maskBufferPtr);
       
   270 		maskBufferPtr += skip;
       
   271 		iPixelsToSkip -= skip;
       
   272 		if(iPixelsToSkip > 0 || maskBufferPtr == maskBufferPtrLimit)
       
   273 			{
       
   274 			break;
       
   275 			}
       
   276 				
       
   277 		// Set the alpha channel of the bitmap
       
   278 		TUint32 pixel = bitmapUtil.GetPixel();
       
   279 		pixel &= KRGBMask; // clear alpha channel
       
   280 		pixel |= maskBufferPtr->Internal() << KAlphaShift; // set alpha
       
   281 
       
   282 		bitmapUtil.SetPixel(pixel);
       
   283 		iPosition.iX++;
       
   284 		
       
   285 		if(iPosition.iX >= (iImageRegion.iBr.iX >> iReductionFactor))
       
   286 			{
       
   287 			iPosition.iX = 0;
       
   288 			iPosition.iY += iYIncrement;
       
   289 			bitmapUtil.SetPos(iPosition);
       
   290 			
       
   291 			if(iPosition.iY < 0)
       
   292 				{
       
   293 				return ETrue;
       
   294 				}
       
   295 			
       
   296 			iPixelsToSkip = (iReductionFactor ? 0 : iPixelPadding);
       
   297 			}
       
   298 		else
       
   299 			{
       
   300 			bitmapUtil.IncXPos();
       
   301 			}
       
   302 		}
       
   303 	
       
   304 	bitmapUtil.End();
       
   305 	
       
   306 	return EFalse;
       
   307 	}