Hello, I am using the MediaPicker.TakePhoto()
method to capture a picture from the user's device, then I am resizing the picture and saving within the app's local storage.
What I would like to do is to retain the photo's EXIF (metadata) information, such as date taken, geolocation, etc. Is this possible?
Here's my code, including the resize function:
/// <summary>
/// Raises the photo received event. This is called when the photo is selected
/// from the gallery or captured by the camera.
/// </summary>
/// <param name="file">File.</param>
private void OnPhotoReceived(IMediaFile file) {
if (file == null) {
ShowInfoDialog ("Photo canceled", "Camera");
} else {
UIImage photo = null;
/*var photo = ImageSource.FromFile (file.Path);
if (photo != null)
photo = MaxResizeImage (photo, 800, 800);
this.Photo = photo;*/
photo = UIImage.FromFile (file.Path);
var randomInt = Convert.ToUInt64 (new Random ().NextDouble () * UInt64.MaxValue);
var name = randomInt + ".jpg";
var documentsDirectory = QCApp.MediaPath;
string jpgFilename = System.IO.Path.Combine (documentsDirectory, name); // hardcoded filename, overwritten each time
// Resize the photo!
photo = MaxResizeImage (photo, 800, 800);
NSData imgData = photo.AsJPEG ();
NSError err = null;
if (imgData.Save (jpgFilename, false, out err)) {
System.Diagnostics.Debug.WriteLine ("saved as " + jpgFilename);
// Save info to Pictures collection.
Pictures.Add (new Picture {
Path = jpgFilename,
Filename = name,
SurveyColumnId = this.CurrentQuestionId,
SectionId = this.SelectedModel.Id,
IsUploaded = false,
SurveyId = this.SurveyId,
SerialNumber = this.CurrentSerialNumber
});
MessagingCenter.Send (this, string.Format(PictureMessageCenterFormat, this.CurrentQuestionId, this.CurrentSerialNumber));
//this.OnPropertyChanged ("Pictures");
} else {
System.Diagnostics.Debug.WriteLine ("NOT saved as " + jpgFilename + " because" + err.LocalizedDescription);
}
}
}
/// <summary>
/// Uploads the picture to Azure.
/// </summary>
/// <returns>The picture.</returns>
/// <param name="picture">Picture.</param>
public async Task<CloudBlockBlob> UploadPicture(Picture picture) {
return await UploadImage (picture);
}
static CloudBlobClient GetClient ()
{
var creds = new StorageCredentials (Constants.AZURE_BLOB_ACCOUNTNAME, Constants.AZURE_BLOB_KEYVALUE);
var client = new CloudStorageAccount (creds, true).CreateCloudBlobClient ();
return client;
}
private async Task<CloudBlockBlob> UploadImage(Picture picture)
{
try {
if (!string.IsNullOrWhiteSpace(picture.Path) && !picture.IsUploaded) {
var photo = UIImage.FromFile (picture.Path);
var client = GetClient ();
var container = client.GetContainerReference("surveypics");
container.CreateIfNotExists();
var blob = container.GetBlockBlobReference(picture.Filename);
var jpgImage = photo.AsJPEG ();
var stream = jpgImage.AsStream();
blob.UploadFromStream (stream);
return blob;
}
else
return null;
}
catch (Microsoft.WindowsAzure.Storage.StorageException storageException)
{
return null;
}
catch (System.Net.ProtocolViolationException protocolViolationException)
{
return null;
}
catch (Exception e) {
MessagingCenter.Send<MobileServiceClient, ExceptionContainerException> (QCApp.Client,
Common.Constants.MessageCenterMessages.MessagingCenterError, new ExceptionContainerException { Title = "Error uploading image",
Exception = e
});
return null;
}
}
// Resize the image to be contained within a maximum width and height, keeping aspect ratio:
public UIImage MaxResizeImage(UIImage sourceImage, float maxWidth, float maxHeight)
{
var sourceSize = sourceImage.Size;
var maxResizeFactor = Math.Min(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
if (maxResizeFactor > 1) return sourceImage;
var width = maxResizeFactor * sourceSize.Width;
var height = maxResizeFactor * sourceSize.Height;
UIGraphics.BeginImageContext(new SizeF(width, height));
sourceImage.Draw(new RectangleF(0, 0, width, height));
var resultImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return resultImage;
}