Exif API: Using Exif API

Parsing an existing Exif image

In this example the full validity checking is done.

// 1. Read Exif image from the file to a buffer...
RFile file;
User::LeaveIfError( file.Open( iFs, iExifFile->Des(), EFileRead ) );
CleanupClosePushL( file );
TInt size = 0;
file.Size(size);
HBufC8* exif = HBufC8::NewL( size );
CleanupStack::PushL( exif );
TPtr8 bufferDes( exif->Des() ); 
User::LeaveIfError( file.Read( bufferDes ) );
CleanupStack::Pop( exif );
CleanupStack::PopAndDestroy();
CleanupStack::PushL( exif );

// 2. Instantiate Exif reader...
CExifRead* read = CExifRead::NewL( exif->Des() );
CleanupStack::PushL( read );

// 3. Get required data from the Exif image...
HBufC8* data = NULL;
data = read->GetImageDescriptionL(); /* Leaves if data is not found. */
/* Process the data … */
delete data;
data = NULL;

// 4. Delete the reader instance...
CleanupStack::PopAndDestroy( read );
CleanupStack::PopAndDestroy( exif );

Parsing an existing Exif image with options

In this example the validity checking for the Exif tags or JPEG markers is not done. The execution time is much shorter with bigger images.

// 1. Read Exif information from the file to a buffer...
RFile file;
User::LeaveIfError( file.Open( iFs, iExifFile->Des(), EFileRead ) );
CleanupClosePushL( file );
TInt size = 0;
file.Size(size);
// Don’t read more than 64k
if ( size > 65536 )
    size = 65536;
HBufC8* exif = HBufC8::NewL( size );
CleanupStack::PushL( exif );
TPtr8 bufferDes( exif->Des() );
User::LeaveIfError( file.Read( bufferDes, size ) );
CleanupStack::Pop( exif );
CleanupStack::PopAndDestroy();
CleanupStack::PushL( exif );

// 2. Instantiate Exif reader in fast mode...
CExifRead* read = CExifRead::NewL( exif->Des(),
                               CExifRead::ENoTagChecking | CExifRead::ENoJpeg );
CleanupStack::PushL( read );

// 3. Get required data from the Exif image...
HBufC8* data = NULL;
data = read->GetImageDescriptionL(); /* Leaves if data is not found. */
/* Process the data … */
delete data;
data = NULL;

// 4. Delete the reader instance...
CleanupStack::PopAndDestroy( read );
CleanupStack::PopAndDestroy( exif );

Modifying an existing Exif image

// 1. Read Exif image from the file to a buffer...
RFile file;
User::LeaveIfError( file.Open( iFs, iExifFile->Des(), EFileRead ) );
CleanupClosePushL( file );
TInt size = 0;
file.Size(size);
HBufC8* exif = HBufC8::NewL( size );
CleanupStack::PushL( exif );
TPtr8 bufferDes( exif->Des() );
User::LeaveIfError( file.Read( bufferDes ) );
CleanupStack::Pop( exif );
CleanupStack::PopAndDestroy();
CleanupStack::PushL( exif );

// 2. Instantiate Exif modifier in EModify mode...
CExifModify* modify = CExifModify::NewL( exif->Des(), CExifModify::EModify );
CleanupStack::PushL( modify );

// 3. Modify required data in the Exif image...
modify->SetXResolutionL( 72, 1 ); 

// 4. Get the modified Exif image...
// If zero length descriptor is given instead of exif->Des(), then only the
// Exif meta data is returned.
HBufC8* modifiedExif = modify->WriteDataL( exif->Des() );
/* Process the modified Exif data */
delete modifiedExif;
modifiedExif = NULL;

// 5. Delete the modifier instance...
CleanupStack::PopAndDestroy( modify );
CleanupStack::PopAndDestroy( exif );

Creating an Exif image out of an existing JPEG image

// 1. Read JPEG image from the file to a buffer...
RFile file;
User::LeaveIfError( file.Open( iFs, iExifFile->Des(), EFileRead ) );
CleanupClosePushL( file );
TInt size = 0;
file.Size(size);
HBufC8* jpeg = HBufC8::NewL( size );
CleanupStack::PushL( jpeg );
TPtr8 bufferDes( jpeg->Des() );
User::LeaveIfError( file.Read( bufferDes ) );
CleanupStack::Pop( jpeg );
CleanupStack::PopAndDestroy();
CleanupStack::PushL( jpeg );

// 2. Instantiate Exif modifier in ECreate mode...
CExifModify* modify = CExifModify::NewL( jpeg->Des(), CExifModify::ECreate );
CleanupStack::PushL( modify );

// 3. Insert (Set) at least the mandatory data...
modify->SetXResolutionL( 72, 1 ); 
modify->SetYResolutionL( 72, 1 ); 
modify->SetResolutionUnitL( 2 );
modify->SetYCbCrPositioningL( 1 );
modify->SetComponentsConfigurationL( 1, 2, 3, 0 );
modify->SetColorSpaceL( 1 );
modify->SetPixelXDimensionL( KImageWidth );
modify->SetPixelYDimensionL( KImageHeight );

// 4. Get the new Exif image...
// If zero length descriptor is given instead of jpeg->Des(), then only the
// Exif meta data is returned.
HBufC8* newExif = modify->WriteDataL( jpeg->Des() );
/* Process the new Exif data */
delete newExif;
newExif = NULL;

// 5. Delete the modifier instance...
CleanupStack::PopAndDestroy( modify );
CleanupStack::PopAndDestroy( jpeg );

Creating Exif data without a JPEG image

// 1. Instantiate Exif modifier in ECreate mode...
CExifModify* modify = CExifModify::NewL();
CleanupStack::PushL( modify );

// 3. Insert (Set) at least the mandatory data...
modify->SetXResolutionL( 72, 1 ); 
modify->SetYResolutionL( 72, 1 ); 
modify->SetResolutionUnitL( 2 );
modify->SetYCbCrPositioningL( 1 );
modify->SetComponentsConfigurationL( 1, 2, 3, 0 );
modify->SetColorSpaceL( 1 );
modify->SetPixelXDimensionL( KImageWidth );
modify->SetPixelYDimensionL( KImageHeight );

// 4. Get the new Exif meta data...
// If a descriptor containing valid JPEG data is given instead of zero length 
// descriptor, then the whole Exif image data is returned.
TPtrC8 zeroLengthDesc;
HBufC8* newExif = modify->WriteDataL( zeroLengthDesc );
/* Process the new Exif data */
delete newExif;
newExif = NULL;

// 5. Delete the modifier instance...
CleanupStack::PopAndDestroy( modify );

Error handling

The leave mechanism of the Symbian OS environment is used to handle memory exhaustion. Exif API leaves whenever it detects something from which it cannot recover. The exception/error cases are listed below:

KErrNoMemory Out of memory.
KErrGeneral An internal error occurred.
KErrArgument The given parameter to the API function is incorrect or invalid.
KErrNotSupported This library does not support the requested operation with the given parameters.
KErrCorrupt The given JPEG or Exif data is corrupted or invalid.
KErrNotFound The data (tag or IFD) corresponding to the given parameter is not found in the JPEG or Exif data.
KErrNotReady The Exif data is not yet complete (valid) for writing. Mandatory tags or thumbnail may be missing.
KErrOverflow The APP1 marker segment size exceeds 64K if the given data is inserted to the Exif data.

The users of Exif API should be aware of the following considerations:

Memory overhead

Since the maximum size of an Exif marker is 64 kB (limited by the JPEG application marker segment), memory consumption is not essentially higher than 64 kB in most operations. However, there are two operations where memory consumption may be higher:

  1. While getting out the whole Exif image using the CExifModify function, the instant memory consumption may reach up to twice the JPEG image data size.
  2. While getting out the Exif APP1 segment using the CExifRead function, the instant memory consumption may reach up to twice the Exif APP1 segment data size.

Copyright © Nokia Corporation 2001-2008
Back to top