imageeditorengine/filters/FilterJpegSource/Src/CFilterJpegSource.cpp
changeset 1 edfc90759b9f
equal deleted inserted replaced
0:57d4cdd99204 1:edfc90759b9f
       
     1 /*
       
     2 * Copyright (c) 2010 Ixonos Plc.
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - Initial contribution
       
    11 *
       
    12 * Contributors:
       
    13 * Ixonos Plc
       
    14 *
       
    15 * Description:  
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include <fbs.h>
       
    21 #include "CFilterJpegSource.h"
       
    22 #include "JpegLoadFactory.h"
       
    23 #include "MJpegLoad.h"
       
    24 
       
    25 const TInt KBlockBufferSize = 256;	// should be enough for every picture...
       
    26 const TInt KScaleBits = 12;
       
    27 const TInt KDestBufferMaxDim = 352;
       
    28 
       
    29 //=============================================================================
       
    30 EXPORT_C TInt CFilterJpegSource::Create()
       
    31 	{
       
    32 	CFilterJpegSource* ptr = NULL;
       
    33 	TRAPD( error, ptr = NewL(); );
       
    34 	if( error != KErrNone )
       
    35 		{
       
    36 		ptr = NULL;
       
    37 		}
       
    38 	return (TInt)((MImageFilter*)ptr);
       
    39 	}
       
    40 
       
    41 //=============================================================================
       
    42 CFilterJpegSource* CFilterJpegSource::NewL()
       
    43 	{
       
    44 	CFilterJpegSource* self = new( ELeave )CFilterJpegSource();
       
    45 	CleanupStack::PushL( self );
       
    46 	self->ConstructL();
       
    47 	CleanupStack::Pop( self );
       
    48 	return self;
       
    49 	}
       
    50 
       
    51 //=============================================================================
       
    52 CFilterJpegSource::~CFilterJpegSource()
       
    53 {
       
    54     delete iJpeg;
       
    55     delete iDestBuffer;
       
    56     delete[] iIndexMap;
       
    57     if ( iBlockBuffer )
       
    58     {
       
    59 	    for (TInt i = 0; i < KBlockBufferSize; ++i)
       
    60 	    {
       
    61 	        delete iBlockBuffer[i];
       
    62 	        iBlockBuffer[i] = NULL;
       
    63 	    }
       
    64     }
       
    65 	delete[] iBlockBuffer;
       
    66     iBlockBuffer = NULL;
       
    67 }
       
    68 
       
    69 //=============================================================================
       
    70 CFilterJpegSource::CFilterJpegSource()
       
    71 	{
       
    72 
       
    73 	}
       
    74 
       
    75 //=============================================================================
       
    76 void CFilterJpegSource::ConstructL()
       
    77 	{
       
    78 
       
    79 	}
       
    80 
       
    81 //=============================================================================
       
    82 TRect CFilterJpegSource::Rect()
       
    83 {
       
    84     if (iOutputState == EDirect)
       
    85     {
       
    86 	    return iRect;
       
    87     }
       
    88     else
       
    89     {
       
    90         return iScaledRect;
       
    91     }
       
    92 }
       
    93 
       
    94 //=============================================================================
       
    95 TReal CFilterJpegSource::Scale()
       
    96 {
       
    97     if (iOutputState == EDirect)
       
    98     {
       
    99         return 1.0;
       
   100     }
       
   101     else
       
   102     {
       
   103 	    return iRelScale;
       
   104     }
       
   105 }
       
   106 
       
   107 //=============================================================================
       
   108 TSize CFilterJpegSource::ViewPortSize()
       
   109 {
       
   110     return iFullSize;
       
   111 }
       
   112 
       
   113 //=============================================================================
       
   114 TBlock * CFilterJpegSource::GetBlockL ( const TRect & aRect )
       
   115 {
       
   116     if (iOutputState == EBuffer)
       
   117     {
       
   118         if ( !aRect.Intersects(iScaledRect) )
       
   119         {
       
   120             return NULL;
       
   121         }
       
   122         TRect rect = aRect;
       
   123         rect.Intersection(iScaledRect);
       
   124 
       
   125         TBlock * pB = new (ELeave) TBlock (rect);
       
   126 
       
   127         TUint32 * pS = iDestBuffer + (rect.iTl.iY - iScaledRect.iTl.iY) * iDestSize.iWidth + 
       
   128             (rect.iTl.iX - iScaledRect.iTl.iX);
       
   129         TUint32 * pD = pB->iData;
       
   130    
       
   131         for (TInt i = rect.iTl.iY; i < rect.iBr.iY; ++i)
       
   132         {
       
   133             Mem::Copy(pD, pS, pB->iWidth * sizeof(TUint32));
       
   134             pD += pB->iWidth;
       
   135             pS += iDestSize.iWidth;
       
   136         }
       
   137         return pB;
       
   138     }
       
   139     else
       
   140     {
       
   141 
       
   142 		if (!aRect.Intersects(iRect))
       
   143 		{
       
   144 			return NULL;
       
   145 		}
       
   146 
       
   147 		//  Clip rectangle to image
       
   148 		TRect rect = aRect;
       
   149 		rect.Intersection(iRect);
       
   150 
       
   151         //  Compute region of interest in blocks
       
   152         TRect blockRect = rect; 
       
   153         blockRect.iTl.iX /= iBlockSize.iWidth;
       
   154         blockRect.iTl.iY /= iBlockSize.iHeight;
       
   155         blockRect.iBr.iX /= iBlockSize.iWidth;
       
   156         blockRect.iBr.iY /= iBlockSize.iHeight;
       
   157         
       
   158         if (blockRect.iBr.iX < iSizeInBlocks.iWidth)
       
   159         {
       
   160         	blockRect.iBr.iX++;	
       
   161         }
       
   162         if (blockRect.iBr.iY < iSizeInBlocks.iHeight)
       
   163         {
       
   164         	blockRect.iBr.iY++;	
       
   165         }
       
   166         
       
   167         //  Create block for pixel data
       
   168         TBlock * pB = new (ELeave) TBlock;
       
   169         CleanupStack::PushL(pB);
       
   170         pB->iRect = blockRect;
       
   171         pB->iRect.iTl.iX *= iBlockSize.iWidth;
       
   172         pB->iRect.iTl.iY *= iBlockSize.iHeight;
       
   173         pB->iRect.iBr.iX *= iBlockSize.iWidth;
       
   174         pB->iRect.iBr.iX += iBlockSize.iWidth;
       
   175         pB->iRect.iBr.iY *= iBlockSize.iHeight;
       
   176         pB->iRect.iBr.iY += iBlockSize.iHeight;
       
   177         pB->iWidth = (pB->iRect.iBr.iX - pB->iRect.iTl.iX);
       
   178         pB->iHeight = (pB->iRect.iBr.iY - pB->iRect.iTl.iY);
       
   179         pB->iDataLength = pB->iWidth * pB->iHeight;
       
   180         pB->iData = new (ELeave) TUint32 [pB->iDataLength];
       
   181 
       
   182         //  Read all blocks in region of interest
       
   183         for (TInt i = blockRect.iTl.iY; i < blockRect.iBr.iY; ++i)
       
   184         {
       
   185 
       
   186             for (TInt j = blockRect.iTl.iX; j < blockRect.iBr.iX; ++j)
       
   187             {
       
   188 
       
   189                 //  Get block index
       
   190                 TInt index = i * iSizeInBlocks.iWidth + j;
       
   191 
       
   192                 //  If not found, load new block, add to cache and update index table
       
   193                 if ( iIndexMap[index] < 0 )
       
   194                 {
       
   195 
       
   196                     //  Load block
       
   197 		            TBlockEntry * e = new (ELeave) TBlockEntry;
       
   198 		            CleanupStack::PushL(e);
       
   199                     e->iRect = TRect ( TPoint (j * iBlockSize.iWidth, i * iBlockSize.iHeight), iBlockSize);
       
   200 		            e->iBitmap = iJpeg->LoadBlockL (TPoint(j,i));
       
   201 
       
   202                     //  Remove index of the oldest block from the map
       
   203                     if (iBlockBuffer [iOldestBlock])
       
   204                     {
       
   205                         TPoint blockPos = iBlockBuffer[iOldestBlock]->iRect.iTl;
       
   206 	                    blockPos.iX /= iBlockSize.iWidth;
       
   207 	                    blockPos.iY /= iBlockSize.iHeight;
       
   208                         iIndexMap[blockPos.iY * iSizeInBlocks.iWidth + blockPos.iX] = -1;
       
   209 
       
   210                         //  Delete oldest block
       
   211 		                delete iBlockBuffer [iOldestBlock];
       
   212                         iBlockBuffer [iOldestBlock] = NULL;
       
   213                     }
       
   214 
       
   215                     //  Insert new block to buffer and update map
       
   216                     iBlockBuffer[iOldestBlock] = e;
       
   217                     iIndexMap[index] = iOldestBlock;
       
   218                     CleanupStack::Pop(e);
       
   219 
       
   220                     //  Update old block index
       
   221                     iOldestBlock++;
       
   222                     if (iOldestBlock >= KBlockBufferSize) iOldestBlock = 0;
       
   223 
       
   224                 }
       
   225 
       
   226                 //  Store pixel data to block
       
   227 	            TUint32 * pS = (TUint32*)( iBlockBuffer[ iIndexMap[index] ]->iBitmap.iData );
       
   228                 TUint32 * pD = 
       
   229                     pB->iData + 
       
   230                     (i - blockRect.iTl.iY) * iBlockSize.iHeight * pB->iWidth + 
       
   231                     (j - blockRect.iTl.iX) * iBlockSize.iWidth;
       
   232                 for (TInt ib = 0; ib < iBlockSize.iHeight; ++ib)
       
   233                 {
       
   234                     Mem::Copy (pD, pS, iBlockSize.iWidth * sizeof(TUint32));
       
   235                     pS += iBlockSize.iWidth;
       
   236                     pD += pB->iWidth;
       
   237                 }
       
   238             }
       
   239         }
       
   240         CleanupStack::Pop( pB );
       
   241         return pB;
       
   242     }
       
   243 }
       
   244 
       
   245 
       
   246 //=============================================================================
       
   247 void CFilterJpegSource::SetParent( MImageFilter* aParent )
       
   248 	{
       
   249 	iParent = aParent;
       
   250 	}
       
   251 
       
   252 //=============================================================================
       
   253 void CFilterJpegSource::SetChild( MImageFilter* aChild )
       
   254 	{
       
   255 	iChild = aChild;
       
   256 	}
       
   257 
       
   258 //=============================================================================
       
   259 TInt CFilterJpegSource::CmdL( const TDesC16& aCmd )
       
   260 	{
       
   261 
       
   262 	TLex lex( aCmd );
       
   263 
       
   264 	while( ! lex.Eos() )
       
   265 		{
       
   266 
       
   267         TPtrC token = lex.NextToken();
       
   268 		if( token.Compare( _L("file") ) == 0 )
       
   269 			{
       
   270 			iFileName.Zero();
       
   271 			
       
   272 			//	Find the start of the string
       
   273 			while (!lex.Eos()) 
       
   274 			    {
       
   275 				if (lex.Get() == '"') break;
       
   276 			    }
       
   277 
       
   278 			//	Get the text data
       
   279 			while (!lex.Eos())
       
   280 			    {
       
   281 				TChar c= lex.Get();
       
   282 				if (c == '"')
       
   283 				    {
       
   284 					break;
       
   285 				    }
       
   286 				else
       
   287 				    {
       
   288 					iFileName.Append(c);
       
   289 				    }
       
   290 			    }
       
   291 			}
       
   292 		else if( token.Compare( _L("loadimage") ) == 0 )
       
   293             {
       
   294             
       
   295             delete iJpeg;
       
   296             iJpeg = 0;
       
   297 	        iJpeg = JpegLoadFactory::CreateJpegLoadL();
       
   298             
       
   299             // open
       
   300 			iJpeg->OpenL( iFileName );
       
   301             iJpeg->ScanRandomL();
       
   302 			
       
   303 			const TJpegData & d = iJpeg->Info();
       
   304 
       
   305             //  set crop rectangle to full image size
       
   306             if (iRect.Size() == TSize(0,0))
       
   307             {
       
   308                 iRect.iTl.iX = 0;
       
   309 			    iRect.iTl.iY = 0;
       
   310 			    iRect.iBr.iX = d.iSize.iWidth;
       
   311 			    iRect.iBr.iY = d.iSize.iHeight;
       
   312             }
       
   313             iFullSize = d.iSize;
       
   314 
       
   315             //  set macroblock parameters
       
   316             iBlockSize = d.iBlockSize;
       
   317             iSizeInBlocks = d.iSizeInBlocks;
       
   318 
       
   319             iOutputState = EBuffer;
       
   320 
       
   321 		    if ( iBlockBuffer )
       
   322 		    {
       
   323 			    for (TInt i = 0; i < KBlockBufferSize; ++i)
       
   324 			    {
       
   325 			        delete iBlockBuffer[i];
       
   326 			        iBlockBuffer[i] = NULL;
       
   327 			    }
       
   328 		    }
       
   329 			delete[] iBlockBuffer;
       
   330 		    iBlockBuffer = NULL;
       
   331             iBlockBuffer = new (ELeave) TBlockEntry * [KBlockBufferSize];
       
   332             TInt i;
       
   333             for (i = 0; i < KBlockBufferSize; ++i) iBlockBuffer[i] = NULL;
       
   334 
       
   335             iSizeInBlocks = d.iSizeInBlocks;
       
   336             TInt blocks = iSizeInBlocks.iWidth * iSizeInBlocks.iHeight;
       
   337             delete[] iIndexMap;
       
   338             iIndexMap = NULL;
       
   339             iIndexMap = new (ELeave) TInt [blocks];
       
   340             for (i = 0; i < blocks; ++i) iIndexMap[i] = -1;
       
   341 
       
   342             iOldestBlock = 0;
       
   343 
       
   344 
       
   345             //  load rectangle
       
   346             LoadRectL();
       
   347             }
       
   348 		else if( token.Compare( _L("exifdata") ) == 0 )
       
   349 			{
       
   350 			return (TInt)(iJpeg->ExifData().Ptr());
       
   351 			}
       
   352 		else if( token.Compare( _L("ulc") ) == 0 )
       
   353 			{
       
   354 			lex.Inc();
       
   355 			lex.Val( iRect.iTl.iX );			
       
   356 			}
       
   357 		else if( token.Compare( _L("ulr") ) == 0 )
       
   358 			{
       
   359 			lex.Inc();
       
   360 			lex.Val( iRect.iTl.iY );			
       
   361 			}
       
   362 		else if( token.Compare( _L("lrc") ) == 0 )
       
   363 			{
       
   364 			lex.Inc();
       
   365 			lex.Val( iRect.iBr.iX );			
       
   366 			}
       
   367 		else if( token.Compare( _L("lrr") ) == 0 )
       
   368 			{
       
   369 			lex.Inc();
       
   370 			lex.Val( iRect.iBr.iY );			
       
   371 			}
       
   372 		else if( token.Compare( _L("fileoutput") ) == 0 )
       
   373 			{
       
   374             iRect.iTl.iX = 0;
       
   375             iRect.iTl.iY = 0;
       
   376             iRect.iBr.iX = iFullSize.iWidth;
       
   377             iRect.iBr.iY = iFullSize.iHeight;
       
   378             iOutputState = EDirect;
       
   379 			}
       
   380 		else if( token.Compare( _L("bufferoutput") ) == 0 )
       
   381 			{
       
   382             iOutputState = EBuffer;
       
   383 			}
       
   384 		else if( token.Compare( _L("exiflength") ) == 0 )
       
   385 			{
       
   386 			return iJpeg->ExifData().Length();
       
   387 			}
       
   388 		}
       
   389 	return 0;
       
   390 	}
       
   391 
       
   392 //=============================================================================
       
   393 const char* CFilterJpegSource::Type()
       
   394 	{
       
   395 	return "jpegsource";
       
   396 	}
       
   397 
       
   398 //=============================================================================
       
   399 void CFilterJpegSource::LoadRectL()
       
   400 	{
       
   401 
       
   402     // compute destination buffer size
       
   403     TInt width = iRect.iBr.iX - iRect.iTl.iX;
       
   404     TInt height = iRect.iBr.iY - iRect.iTl.iY;
       
   405 
       
   406     if (width >= height)
       
   407     {
       
   408         TReal scale = (TReal)KDestBufferMaxDim / width;
       
   409         iDestSize.iWidth = KDestBufferMaxDim;
       
   410         iDestSize.iHeight = (TInt)(height * scale + 0.5);
       
   411     }
       
   412     else
       
   413     {
       
   414         TReal scale = (TReal)KDestBufferMaxDim / height;
       
   415         iDestSize.iHeight = KDestBufferMaxDim;
       
   416         iDestSize.iWidth = (TInt)(width * scale + 0.5);
       
   417     }
       
   418 
       
   419     //  create new destination buffer
       
   420     delete[] iDestBuffer;
       
   421     iDestBuffer = new (ELeave) TUint32 [iDestSize.iWidth * iDestSize.iHeight];
       
   422 
       
   423     //  compute scale
       
   424     TJpegScale scale = EScale1;
       
   425     while ((width /= 2) > iDestSize.iWidth)
       
   426         {
       
   427         if (scale == EScale1)
       
   428             {
       
   429             scale= EScale2;
       
   430             }
       
   431         else if (scale == EScale2)
       
   432             {
       
   433             scale= EScale4;
       
   434             }
       
   435         else if (scale == EScale4)
       
   436             {
       
   437             scale= EScale8;
       
   438             }
       
   439         }
       
   440 
       
   441     //  load scaled rectangle 
       
   442     TBitmapHandle loadbitmap;
       
   443     TRect loadrect = iRect;
       
   444     iJpeg->SetScale(scale);
       
   445     loadbitmap = iJpeg->LoadImageL(loadrect);
       
   446 
       
   447     //  scale buffer 
       
   448     TInt sc = (TInt) ((TReal)(height << KScaleBits) / iDestSize.iHeight + 0.5);
       
   449     TInt ws = (loadrect.iBr.iX - loadrect.iTl.iX) >> (TInt)scale;
       
   450 
       
   451     TUint32 * pD = iDestBuffer;
       
   452     TUint32 * pS = (TUint32 *)loadbitmap.iData +
       
   453         ((iRect.iTl.iY - loadrect.iTl.iY) >> (TInt)scale) * ws +
       
   454         ((iRect.iTl.iX  - loadrect.iTl.iX) >> (TInt)scale);
       
   455 
       
   456     for (TInt i = 0; i < iDestSize.iHeight; ++i)
       
   457     {
       
   458         TInt y = (i * sc) >> KScaleBits;
       
   459         y >>= (TInt)scale;
       
   460         for (TInt j = 0; j < iDestSize.iWidth; ++j)
       
   461         {
       
   462             TInt x = (j * sc) >> KScaleBits;
       
   463             x >>= (TInt)scale;
       
   464             *pD++ = *(pS + y * ws + x);
       
   465         }
       
   466     }
       
   467 
       
   468     delete loadbitmap.iData;
       
   469 
       
   470     iRelScale = (TReal)(iDestSize.iHeight) / (TReal)height;
       
   471 
       
   472     iScaledRect.iTl.iX = (TInt)(iRelScale * iRect.iTl.iX + 0.5);
       
   473     iScaledRect.iTl.iY = (TInt)(iRelScale * iRect.iTl.iY + 0.5);
       
   474     iScaledRect.iBr.iX = (TInt)(iRelScale * iRect.iBr.iX + 0.5);
       
   475     iScaledRect.iBr.iY = (TInt)(iRelScale * iRect.iBr.iY + 0.5);
       
   476 
       
   477 	//	check that iScaledRect is inside buffer
       
   478 	TInt tmp = iScaledRect.iBr.iX - iScaledRect.iTl.iX - iDestSize.iWidth;
       
   479 	if ( tmp > 0 )
       
   480 	{
       
   481 		iScaledRect.iBr.iX -= tmp;
       
   482 	}
       
   483 
       
   484 	tmp = iScaledRect.iBr.iY - iScaledRect.iTl.iY - iDestSize.iHeight;
       
   485 	if (tmp > 0 )
       
   486 	{
       
   487 		iScaledRect.iBr.iY -= tmp;
       
   488 	}
       
   489 	
       
   490 
       
   491 //    CFbsBitmap * bitmap = new (ELeave) CFbsBitmap;
       
   492 //    CleanupStack::PushL(bitmap);
       
   493 //    User::LeaveIfError(bitmap->Create(iDestSize, EColor16M));
       
   494 //    TBitmapUtil bm (bitmap);
       
   495 //    bm.Begin(TPoint(0,0));
       
   496 //    TUint8 * pDOS = (TUint8 *)bitmap->DataAddress();
       
   497 //    pS = iDestBuffer;
       
   498 //    ws = CFbsBitmap::ScanLineLength(iDestSize.iWidth, EColor16M);
       
   499 //    for (TInt ii = 0; ii < iDestSize.iHeight; ++ii)
       
   500 //    {
       
   501 //        TUint8 * pD = pDOS;
       
   502 //        pDOS += ws;
       
   503 //        for (TInt j = 0; j < iDestSize.iWidth; ++j)
       
   504 //        {
       
   505 //            TUint32 c = *pS++;
       
   506 //            *pD++ = c & 0xFF;
       
   507 //            c >>= 8;
       
   508 //            *pD++ = c & 0xFF;
       
   509 //            c >>= 8;
       
   510 //            *pD++ = c & 0xFF;
       
   511 //        }
       
   512 //    }
       
   513 //    bm.End();
       
   514 //    TFileName filename;
       
   515 //    filename.Copy (_L("c:\\nokia\\images\\sf_"));
       
   516 //    filename.AppendNum((TInt)iDestBuffer);
       
   517 //    filename.Append(_L(".mbm"));
       
   518 //    bitmap->Save(filename);
       
   519 //
       
   520 //    CleanupStack::PopAndDestroy(); // bitmap
       
   521 
       
   522 
       
   523 	}
       
   524             
       
   525 	
       
   526 	
       
   527 #if !defined(EKA2)
       
   528 GLDEF_C TInt E32Dll( TDllReason )
       
   529     {
       
   530     return KErrNone;
       
   531     }	
       
   532 #endif