Retaining EXIF properties after Editing and Saving a JPEG

Saturday, 6 May 2006 11:34 by RanjanBanerji

EXIF (Exchangeable Image File Format) is a format used by most digital cameras to save images and information on these images.  The standard has been created by JEITA (Japan Electronics and Information Technology Industries Association).  The EXIF format turns out to be very beneficial as the image now contains all sorts of valuable information on the image such as date and time the photograph was taken, make and model of the camera, shutter speed, aperture, ISO, and a lots of other such properties.

Now here is the problem.  Most software that allows you to edit photographs will lose the EXIF information when you save the edited image.  I too experienced this while trying to resize and save the new image.  The solution to the problem is simple in .Net and its implementation of GDI+, yet its difficult to seek out and very rarely used as evidenced by a lot of commercial software that I see out there.

Lets say you wish to resize an image and then save it.  You could write code that would be something like:

 

//This method will resize the image to half its 
//original size and then save it as another image
public void ResizeAndSave( Image imageToResize ) {
    Bitmap newImage = null;

    int originalWidth = imageToResize.Width;
    int originalHeight = imageToResize.Height;
    int newWidth = (int)( originalWidth * 0.5 );
    int newHeight = (int)( originalHeight * 0.5 );

    newImage = new Bitmap( newWidth, newHeight, PixelFormat.Format24bppRgb );
    newImage.SetResolution( imageToResize.HorizontalResolution, imageToResize.VerticalResolution );

    Graphics graphics = Graphics.FromImage( newImage );
    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

    graphics.DrawImage( imageToResize, new Rectangle( 0, 0, newWidth, newHeight ),
        new Rectangle( 0, 0, originalWidth, originalHeight ), GraphicsUnit.Pixel );

    graphics.Dispose();
    
    //Will not save EXIF from original image
    newImage.Save( "c:\\somefilename.jpg" ); 
     //Will not save EXIF from original image
    newImage.Save( "c:\\somefilename.jpg" , ImageFormat.Exif );
    
    //Transfer properties
    foreach( PropertyItem propertyItem in imgPhoto.PropertyItems ) {
        newImage.SetPropertyItem( propertyItem );
    }
}

 

The code above will resize and save the image, however, you will have lost all the EXIF properties.  I then used the ImageFormat argument for the Save method.  So instead of:

//Will not save EXIF from original image
    newImage.Save( "c:\\somefilename.jpg" );

I used:

 //Will not save EXIF from original image
  
newImage.Save( "c:\\somefilename.jpg", ImageFormat.Exif );

Well this did not help either. This is when I realzed that simply saving an image after modifying it was not enough.  Also, if you look at the code that is used to resize that image, you will notice that the code entails redrawing the image to a new image.  Therefore there is no transfer of non image properties occurring.  The question then is, what needs to be done?  The answer is quite simple, copy the properties from the source image to the destination image.  To do so we modify the the ResizeAndSave methods by querying the source image for its PropertyItems array and then setting each property to the new  image we have created.  BUT!!!, be warned that is not enough.  Saving the image using Save( filename, ImageFormat ) will not be enough.  Despite setting properties the image when saved will not retain the properties.  This is because these properties are specific to the EXIF format and setting the ImageFormat to be EXIF is not enough.  You need the appropriate ImageCodecInfo to save the new image such that all the new properties you have set are saved.  So the code you need to write will be something like:

 //This method will resize the image to half its
//original size and then save it as another image
public voidResizeAndSave( Image imageToResize ) {
    Bitmap newImage = null;

    int originalWidth = imageToResize.Width;
    int originalHeight = imageToResize.Height;
    int newWidth = (int)( originalWidth * 0.5 );
    int newHeight = (int)( originalHeight * 0.5 );

    newImage = newBitmap( newWidth, newHeight, PixelFormat.Format24bppRgb );
    newImage.SetResolution( imageToResize.HorizontalResolution, imageToResize.VerticalResolution );

    Graphics graphics = Graphics.FromImage( newImage );
    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

    graphics.DrawImage( imageToResize, newRectangle( 0, 0, newWidth, newHeight ),
        newRectangle( 0, 0, originalWidth, originalHeight ), GraphicsUnit.Pixel );

    graphics.Dispose();
   
    //First Transfer properties
  
foreach( PropertyItem propertyItem inimageToResize.PropertyItems ) {
        newImage.SetPropertyItem( propertyItem );
    }
   
    //Now save the file
  
System.Drawing.Imaging.Encoder encoder = System.Drawing.Imaging.Encoder.Transformation;
    EncoderParameters encoderParms = newEncoderParameters( 1 );
    EncoderParameter encoderParm;
   
    ImageCodecInfo codecInfo;
   
    //Find the right encoder
  
ImageCodecInfo[] encoders;
    encoders = ImageCodecInfo.GetImageEncoders();
    for( int i = 0; i < encoders.Length; i++ ) {
        if( encoders[ i ].MimeType == "image/jpeg") {
            codecInfo = encoders[ i ];
            break;
        }
    }

    encoderParm = newEncoderParameter( encoder, (long)EncoderValue.CompressionNone );
    encoderParms.Param[0] = encoderParm;
   
    //Now save the image with the correct encoder information and your properties should be saved.
  
newImage.Save( "c:\\somefilename.jpg", codecInfo, null); //You dont have to specify EncoderParameters
}

The code above has been pulled out of one of my applications and has been modified for the purpose of this article.  You may need some minor adjustments if it does not compile.  But in principal it does lay out all the steps required to save an image after editing, such that all the EXIF properties of the original are preserved in the new image.

Tags:  
Categories:   .Net
Actions:   E-mail | Permalink | Comments (1) | Comment RSSRSS comment feed

Comments

January 27. 2014 16:04

pingback

Pingback from camera-site.com

Best Digital Camera Under 500 | Digital SLR Camea Site

camera-site.com

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading