imaging/imagingfws/src/BufferedImageConversion.cpp
changeset 0 5752a19fdefe
equal deleted inserted replaced
-1:000000000000 0:5752a19fdefe
       
     1 // Copyright (c) 2001-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 "ImageConversion.h"
       
    17 #include "ImageClientMain.h"
       
    18 
       
    19 // BUFFERED IMAGE DECODER
       
    20 
       
    21 /**
       
    22 Creates a buffered decoder.
       
    23 
       
    24 The function leaves if the decoder object cannot be created or initialised.
       
    25 
       
    26 @param  aFs
       
    27         A reference to a file server session for the decoder to use.
       
    28 
       
    29 @return A pointer to the newly created decoder.
       
    30 */
       
    31 EXPORT_C CBufferedImageDecoder* CBufferedImageDecoder::NewL(RFs& aFs)
       
    32 	{
       
    33 	CBufferedImageDecoder* self = new (ELeave) CBufferedImageDecoder(aFs);
       
    34 	return self;
       
    35 	}
       
    36 
       
    37 /**
       
    38 Creates a decoder for the image in the source buffer. The client supplies
       
    39 a MIME type which will be used to try and select an appropriate plugin
       
    40 decoder. If it finds a decoder it creates it and then goes on to use that
       
    41 decoder to scan the beginning of the image file.
       
    42 
       
    43 @param  aSourceData
       
    44         The buffer containing the image to be decoded.
       
    45 @param  aMIMEType
       
    46         The MIME type of the image in the buffer.
       
    47 @param  aOptions
       
    48         The options to use.
       
    49 
       
    50 @leave  KEComErrNoInterfaceIdentified
       
    51         No plugin decoder could be found for the specified image.
       
    52 */
       
    53 EXPORT_C void CBufferedImageDecoder::OpenL(const TDesC8& aSourceData, const TDesC8& aMIMEType, const CImageDecoder::TOptions aOptions)
       
    54 	{
       
    55 	__ASSERT_ALWAYS(iState == EStateCreated, Panic(EInvalidState));
       
    56 
       
    57 	ASSERT(iMimeType.Ptr() == NULL);
       
    58 	const TInt mimeLength = aMIMEType.Length();
       
    59 	TUint8* ptr = STATIC_CAST(TUint8*, User::AllocL(mimeLength));
       
    60 	iMimeType.Set(ptr, mimeLength, mimeLength);
       
    61 	iMimeType.Copy(aMIMEType);
       
    62 
       
    63 	iOptions = aOptions;
       
    64 	iImageTypeOpen = EFalse;
       
    65 
       
    66 	AppendDataL(aSourceData);
       
    67 
       
    68 	iState = EStateOpening;
       
    69 
       
    70 	ContinueOpenL();
       
    71 
       
    72 	}
       
    73 
       
    74 /**
       
    75 Creates a decoder for the image in the source buffer. 
       
    76 
       
    77 If the client supplies an image type (and sub-type, if applicable) or decoder uid, these will be
       
    78 used to try and select an appropriate plugin decoder. If not, then the selection
       
    79 will be done by matching the image header from the buffer. If it finds a decoder
       
    80 it creates it and then goes on to use that decoder to scan the beginning of
       
    81 the image buffer. If a decoder could not be created append data using AppendDataL()
       
    82 and call ContinueOpenL().
       
    83 
       
    84 @param  aSourceData
       
    85         The buffer containing the image to be decoded.
       
    86 @param  aOptions
       
    87         The decoder options to use.
       
    88 @param  aImageType
       
    89         The image type of the image in the file (optional).
       
    90 @param  aImageSubType
       
    91         The image sub-type of the image in the file (optional).
       
    92 @param  aDecoderUid
       
    93 		The implementation UID for a specific codec or a decoder/encoder class UID (optional, defaults to KNullUid).
       
    94 		If this option is selected for a specific codec the image type and image sub type for the displayer must be supplied.
       
    95 		When loading plugins by class UID the image type and image subtype are not mandatory and the first valid plugin from 
       
    96 		the list of available plugins with the specified class UID will be loaded.
       
    97 @see	KUidICLJpegEXIFInterface
       
    98 @see	KUidICLJpegImageFrameInterface
       
    99 @leave  KErrUnderflow
       
   100         Not enough data in descriptor to identify which plugin decoder to use.
       
   101 @leave  KEComErrNoInterfaceIdentified
       
   102         No plugin decoder could be found for the specified image.
       
   103 @leave  KErrNotFound
       
   104         The specified codec could not be found.
       
   105 */
       
   106 EXPORT_C void CBufferedImageDecoder::OpenL(const TDesC8& aSourceData, const CImageDecoder::TOptions aOptions, const TUid aImageType, const TUid aImageSubType, const TUid aDecoderUid)
       
   107 	{
       
   108 	__ASSERT_ALWAYS(iState == EStateCreated,Panic(EInvalidState));
       
   109 
       
   110 	iOptions = aOptions;
       
   111 	iImageType = aImageType;
       
   112 	iImageSubType = aImageSubType;
       
   113 	iDecoderUid = aDecoderUid;
       
   114 	iImageTypeOpen = ETrue;
       
   115 
       
   116 	AppendDataL(aSourceData);
       
   117 
       
   118 	iState = EStateOpening;
       
   119 
       
   120 	ContinueOpenL();
       
   121 	}
       
   122 
       
   123 /**
       
   124 Call this function to retry to create a decoder after OpenL() returned with
       
   125 KErrUnderFlow and extra data was added to the descriptor using AppendDataL().
       
   126 This function can be recalled until ValidDecoder() return ETrue.
       
   127 
       
   128 @leave  KErrUnderflow
       
   129         Not enough data in descriptor to identify which plugin decoder to use.
       
   130 */
       
   131 EXPORT_C void CBufferedImageDecoder::ContinueOpenL()
       
   132 	{
       
   133 
       
   134 	__ASSERT_ALWAYS(iState == EStateOpening, Panic(EInvalidState));
       
   135 	TInt error = KErrNone;
       
   136 
       
   137 	if(!ValidDecoder())
       
   138 		{
       
   139 		if(iImageTypeOpen)
       
   140 			{
       
   141 			TRAP(error, iDecoder = CImageDecoder::DataNewL(iFileSession, iBuffer, iOptions, iImageType, iImageSubType, iDecoderUid));
       
   142 			}
       
   143 		else
       
   144 			{
       
   145 			TRAP(error, iDecoder = CImageDecoder::DataNewL(iFileSession, iBuffer, iMimeType, iOptions));
       
   146 			}
       
   147 		}
       
   148 
       
   149 	if(error != KErrNone)
       
   150 		{
       
   151 		if(error != KErrUnderflow)
       
   152 			User::Leave(error);
       
   153 		}
       
   154 	else
       
   155 		iState = EStateOpen;
       
   156 
       
   157 	}
       
   158 
       
   159 /**
       
   160 Destructor for this class.
       
   161 
       
   162 Stops decoding if it is in progress and frees all resources owned by the object prior to its destruction.
       
   163 */
       
   164 EXPORT_C CBufferedImageDecoder::~CBufferedImageDecoder()
       
   165 	{
       
   166 	Cancel();
       
   167 	Reset();
       
   168 	ASSERT(iDecoder == NULL); // make sure decoder is deleted
       
   169 	}
       
   170 
       
   171 /**
       
   172 Starts decoding an image frame asynchronously.
       
   173 
       
   174 When converting the operation can complete with KErrUnderflow, if there is insufficient
       
   175 information in the descriptor. In this situation, ContinueConvert() should be called repeatedly
       
   176 until the descriptor has accumulated enough information for ContinueConvert() to complete with KErrNone.
       
   177 
       
   178 @param  aRequestStatus
       
   179         The request status. On completion contains an error code.
       
   180         KErrNone if frame was decoded successfully,
       
   181         KErrUnderflow if the frame was partially decoded
       
   182         otherwise another of the system-wide error codes.
       
   183 @param  aDestination
       
   184         A bitmap that will contain the decoded frame. The bitmap
       
   185         must be created before the call and must be large enough
       
   186         for the frame and set to the required display mode.
       
   187         FrameInfo() can be used to obtain the size and display mode
       
   188         of the frame.
       
   189 @param  aFrameNumber
       
   190         The frame in multi-frame image to decode (optional).
       
   191 */
       
   192 EXPORT_C void CBufferedImageDecoder::Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, TInt aFrameNumber)
       
   193 	{
       
   194 	__ASSERT_ALWAYS(iState == EStateOpen || iState == EStateConverting, Panic(EInvalidState));
       
   195 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   196 	iDecoder->Convert(aRequestStatus, aDestination, aFrameNumber);
       
   197 	iState = EStateConverting;
       
   198 	}
       
   199 
       
   200 /**
       
   201 Starts decoding an image frame and mask asynchronously.
       
   202 
       
   203 When converting the operation can complete with KErrUnderflow, if there is insufficient
       
   204 information in the descriptor. In this situation, ContinueConvert() should be called repeatedly
       
   205 until the descriptor has accumulated enough information for ContinueConvert() to complete with KErrNone.
       
   206 
       
   207 @param  aRequestStatus
       
   208         The request status. On completion contains an error code.
       
   209         KErrNone if frame was decoded successfully,
       
   210         KErrUnderflow if the frame was partially decoded
       
   211         otherwise another of the system-wide error codes.
       
   212 @param  aDestination
       
   213         A bitmap that will contain the decoded frame. The bitmap
       
   214         must be created before the call and must be large enough
       
   215         for the frame and set to the required display mode.
       
   216         FrameInfo() can be used to obtain the size and display mode
       
   217         of the frame.
       
   218 @param  aDestinationMask
       
   219         A bitmap that will contain the decoded frame mask. The bitmap
       
   220         must be created before the call and must be large enough
       
   221         for the mask. The display mode must be EGray2 or EGray256 and
       
   222         must be EGray256 if the image contains alpha-blending information.
       
   223         This information can be obtained from the iFlags property and
       
   224         TFrameInfoFlags of TFrameInfo
       
   225         obtained from a FrameInfo() call.
       
   226 @param  aFrameNumber
       
   227         The frame in multi-frame image to decode (optional).
       
   228 */
       
   229 EXPORT_C void CBufferedImageDecoder::Convert(TRequestStatus* aRequestStatus, CFbsBitmap& aDestination, CFbsBitmap& aDestinationMask, TInt aFrameNumber)
       
   230 	{
       
   231 	__ASSERT_ALWAYS(iState == EStateOpen || iState == EStateConverting, Panic(EInvalidState));
       
   232 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   233 	iDecoder->Convert(aRequestStatus, aDestination, aDestinationMask, aFrameNumber);
       
   234 	iState = EStateConverting;
       
   235 	}
       
   236 
       
   237 /**
       
   238 Continues decoding a frame and/or mask after new image data was added to
       
   239 the source file or descriptor and a previous call to Convert() or
       
   240 ContinueConvert() returned KErrUnderflow.
       
   241 
       
   242 @param  aRequestStatus
       
   243         The request status. On completion contains an error code.
       
   244         KErrNone if frame was decoded successfully,
       
   245         KErrUnderflow if the frame was partially decoded
       
   246         otherwise another of the system-wide error codes.
       
   247 */
       
   248 EXPORT_C void CBufferedImageDecoder::ContinueConvert(TRequestStatus* aRequestStatus)
       
   249 	{
       
   250 	__ASSERT_ALWAYS(iState == EStateConverting, Panic(EInvalidState));
       
   251 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   252 	iDecoder->ContinueConvert(aRequestStatus);
       
   253 	}
       
   254 
       
   255 /**
       
   256 Reset the decoder for reuse. 
       
   257 
       
   258 Follow this call with OpenL() and new source data.
       
   259 */
       
   260 EXPORT_C void CBufferedImageDecoder::Reset()
       
   261 	{
       
   262 	delete iDecoder; iDecoder = NULL;
       
   263 	User::Free(STATIC_CAST(TAny*,CONST_CAST(TUint8*,iBuffer.Ptr())));
       
   264 	iBuffer.Set(NULL, 0 ,0);
       
   265 	User::Free(STATIC_CAST(TAny*,CONST_CAST(TUint8*,iMimeType.Ptr())));
       
   266 	iMimeType.Set(NULL, 0 ,0);
       
   267 	iImageType = KNullUid;
       
   268 	iImageSubType = KNullUid;
       
   269 	iDecoderUid = KNullUid;
       
   270 	iOptions = CImageDecoder::EOptionNone;
       
   271 	iState = EStateCreated;
       
   272 	}
       
   273 
       
   274 /**
       
   275 Requests an asynchronous decode to terminate. 
       
   276 
       
   277 Cancels any conversions currently in progress.
       
   278 */
       
   279 EXPORT_C void CBufferedImageDecoder::Cancel()
       
   280 	{
       
   281 	if(iDecoder)
       
   282 		iDecoder->Cancel();
       
   283 	}
       
   284 
       
   285 /**
       
   286 Adds new image data. 
       
   287 
       
   288 A copy of the data is held internally, and the caller does not need to retain the data.
       
   289 
       
   290 @param  aData
       
   291         The new image data to append.
       
   292 */
       
   293 EXPORT_C void CBufferedImageDecoder::AppendDataL(const TDesC8& aData)
       
   294 	{
       
   295 	// Resize the buffer
       
   296 	TInt oldLength = iBuffer.Length();
       
   297 	TInt newLength = oldLength + aData.Length();
       
   298 
       
   299 	if(iBuffer.Ptr() == NULL)
       
   300 		{
       
   301 		TUint8* ptr = STATIC_CAST(TUint8*,User::AllocL(newLength));
       
   302 		iBuffer.Set(ptr, newLength, newLength);
       
   303 		iBuffer.Copy(aData);
       
   304 		}
       
   305 
       
   306 	if(iBuffer.MaxLength() < newLength)
       
   307 		{
       
   308 		TAny* oldBuffer  = STATIC_CAST(TAny*, CONST_CAST(TUint8*, iBuffer.Ptr()));
       
   309 		TUint8* newBuffer = STATIC_CAST(TUint8*, User::ReAllocL(oldBuffer,newLength));
       
   310 		iBuffer.Set(newBuffer,oldLength, newLength);
       
   311 		iBuffer.Append(aData);
       
   312 		}
       
   313 	}
       
   314 
       
   315 /**
       
   316 Returns the number of frames in the image being decoded. This function can
       
   317 be called immediately after the call to create the decoder, thus enabling
       
   318 the caller to know how many frames need to be converted.
       
   319 
       
   320 @return The number of frames.
       
   321 */
       
   322 EXPORT_C TInt CBufferedImageDecoder::FrameCount() const
       
   323 	{
       
   324 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   325 	return iDecoder->FrameCount();
       
   326 	}
       
   327 /**
       
   328 Returns the status of the image.
       
   329 
       
   330 If the image is incomplete or not terminated correctly EFalse will be returned
       
   331 
       
   332 @return A boolean indicating the image status. Returns ETrue if image header processing is complete,
       
   333         otherwise EFalse.
       
   334 */
       
   335 EXPORT_C TBool CBufferedImageDecoder::IsImageHeaderProcessingComplete() const
       
   336 	{
       
   337 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   338 	return iDecoder->IsImageHeaderProcessingComplete();
       
   339 	}
       
   340 
       
   341 /**
       
   342 Continues processing image headers after new image data was appended.
       
   343 
       
   344 This function can be called until IsImageHeaderProcessingComplete()
       
   345 return ETrue.
       
   346 */
       
   347 EXPORT_C void CBufferedImageDecoder::ContinueProcessingHeaderL()
       
   348 	{
       
   349 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   350 	iDecoder->ContinueProcessingHeaderL();
       
   351 	}
       
   352 
       
   353 /**
       
   354 Returns the frame info for a specified frame of the image.
       
   355 
       
   356 This function can be called immediately after the call to create the decoder, thus enabling
       
   357 the caller to know about each frame in advance of converting it.
       
   358 
       
   359 @param  aFrameNumber
       
   360         The frame number.
       
   361 
       
   362 @return The information for the specified frame.
       
   363 */
       
   364 EXPORT_C const TFrameInfo& CBufferedImageDecoder::FrameInfo(TInt aFrameNumber) const
       
   365 	{
       
   366 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   367 	return iDecoder->FrameInfo(aFrameNumber);
       
   368 	}
       
   369 
       
   370 /**
       
   371 Returns the image data for a specific frame.
       
   372 
       
   373 Use FrameCount() to determine how many frames are contained in the image before using this function.
       
   374 
       
   375 @param  aFrameNumber
       
   376         The frame number for which to return frame data.
       
   377 
       
   378 @return The data for the specified frame.
       
   379 */
       
   380 EXPORT_C const CFrameImageData& CBufferedImageDecoder::FrameData(TInt aFrameNumber) const
       
   381 	{
       
   382 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   383 	return iDecoder->FrameData(aFrameNumber);
       
   384 	}
       
   385 /**
       
   386 Returns the number of comments attached to the image (as opposed to
       
   387 a particular frame).
       
   388 
       
   389 @return The number of comments attached to the image.
       
   390 */
       
   391 EXPORT_C TInt CBufferedImageDecoder::NumberOfImageComments() const
       
   392 	{
       
   393 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   394 	return iDecoder->NumberOfImageComments();
       
   395 	}
       
   396 
       
   397 /**
       
   398 Returns a particular comment attached to the image.
       
   399 Ownership of the returned buffer is transferred to the caller.
       
   400 
       
   401 Use NumberOfImageComments() to determine how many (if any) comments are contained within the image.
       
   402 
       
   403 @param  aCommentNumber
       
   404         The comment number.
       
   405 
       
   406 @return A buffer containing the comment.
       
   407 */
       
   408 EXPORT_C HBufC* CBufferedImageDecoder::ImageCommentL(TInt aCommentNumber) const
       
   409 	{
       
   410 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   411 	return iDecoder->ImageCommentL(aCommentNumber);
       
   412 	}
       
   413 
       
   414 /**
       
   415 Returns the number of comments attached to a given frame of the image
       
   416 as opposed to the whole image.
       
   417 
       
   418 Use FrameCount() to retrieve the number of frames in the image to ensure that the value you use for
       
   419 aFrameNumber is valid.
       
   420 
       
   421 @param  aFrameNumber
       
   422         The frame number.
       
   423 
       
   424 @return The number of comments attached to a given frame of the image.
       
   425 */
       
   426 EXPORT_C TInt CBufferedImageDecoder::NumberOfFrameComments(TInt aFrameNumber) const
       
   427 	{
       
   428 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   429 	return iDecoder->NumberOfFrameComments(aFrameNumber);
       
   430 	}
       
   431 
       
   432 /**
       
   433 Returns a particular comment attached to a given frame of the image.
       
   434 Ownership of the returned buffer is transferred to the caller.
       
   435 
       
   436 @param  aFrameNumber
       
   437         The frame number.
       
   438 @param  aCommentNumber
       
   439         The comment number.
       
   440 
       
   441 @return A buffer containing the comment.
       
   442 */
       
   443 EXPORT_C HBufC* CBufferedImageDecoder::FrameCommentL(TInt aFrameNumber, TInt aCommentNumber) const
       
   444 	{
       
   445 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   446 	return iDecoder->FrameCommentL(aFrameNumber, aCommentNumber);
       
   447 	}
       
   448 
       
   449 /**
       
   450 Returns the formatted frame information strings for a specific frame
       
   451 and leave it on the cleanup stack.
       
   452 
       
   453 Ownership is transferred to the caller.
       
   454 
       
   455 @param  aFrameNumber
       
   456         The frame number.
       
   457 
       
   458 @return The formatted frame information strings.
       
   459 */
       
   460 EXPORT_C CFrameInfoStrings* CBufferedImageDecoder::FrameInfoStringsLC(TInt aFrameNumber)
       
   461 	{
       
   462 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   463 	return iDecoder->FrameInfoStringsLC(aFrameNumber);
       
   464 	}
       
   465 
       
   466 /**
       
   467 Returns the formatted frame information strings for a specific frame.
       
   468 
       
   469 Ownership is transferred to the caller.
       
   470 
       
   471 @param  aFrameNumber
       
   472         The frame number.
       
   473 
       
   474 @return The formatted frame information strings.
       
   475 */
       
   476 EXPORT_C CFrameInfoStrings* CBufferedImageDecoder::FrameInfoStringsL(TInt aFrameNumber)
       
   477 	{
       
   478 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   479 	return iDecoder->FrameInfoStringsL(aFrameNumber);
       
   480 	}
       
   481 
       
   482 /**
       
   483 Returns the implementation UID of the decoder being used to decode the image.
       
   484 
       
   485 @return The implementation UID of the decoder.
       
   486 */
       
   487 EXPORT_C TUid CBufferedImageDecoder::ImplementationUid() const
       
   488 	{
       
   489 	__ASSERT_ALWAYS(ValidDecoder(),Panic(EDecoderNotCreated));
       
   490 	return iDecoder->ImplementationUid();
       
   491 	}
       
   492 
       
   493 /**
       
   494 Determine if enough data was available to determine which plugin decoder
       
   495 to use. If this return EFalse append extra data using AppendDataL() and
       
   496 and call ContinueOpenL()
       
   497 
       
   498 @return A boolean indicating if the decoder plugin was successful. ETrue if a decoder plugin was 
       
   499         created, otherwise EFalse.
       
   500 */
       
   501 EXPORT_C TBool CBufferedImageDecoder::ValidDecoder () const
       
   502 	{
       
   503 	return iDecoder != NULL;
       
   504 	}
       
   505 /**
       
   506 Constructor for this class.
       
   507 @internalTechnology
       
   508 */
       
   509 CBufferedImageDecoder::CBufferedImageDecoder(RFs& aFs):
       
   510 	iFileSession(aFs),
       
   511 	iBuffer(NULL,0,0),
       
   512 	iMimeType(NULL,0,0),
       
   513 	iState(EStateCreated)
       
   514 	{
       
   515 	}