Reputation: 1757
Using an MVC application to upload an image, we need to reduce the file size before saving to the DB, but want to retain the EXIF data... The only way I can think of this is to get this from the original uploaded image and then add it to the resized one, using MetadataExtractor
We can get the metadata like this
Dim vMetadata As IEnumerable(Of System.IO.Directory) = MetadataExtractor.ImageMetadataReader.ReadMetadata(file.InputStream)
Then resize the image like this
fext = IO.Path.GetExtension(file.FileName).ToLower
Dim vLen As Integer = file.ContentLength
Dim vData(vLen - 1) As Byte
Dim image_file As System.Drawing.Image = System.Drawing.Image.FromStream(file.InputStream)
Dim image_height As Integer = image_file.Height
Dim image_width As Integer = image_file.Width
Dim max_height As Integer = 240
Dim max_width As Integer = 320
image_height = (image_height * max_width) / image_width
image_width = max_width
If image_height > max_height Then
image_width = (image_width * max_height) / image_height
image_height = max_height
End If
Dim bitmap_file As New System.Drawing.Bitmap(image_file, image_width, image_height)
Using vStream As New IO.MemoryStream
Select Case fext
Case ".jpg"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".jpeg"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".png"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Png)
Case ".gif"
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Gif)
Case Else
bitmap_file.Save(vStream, System.Drawing.Imaging.ImageFormat.Jpeg)
End Select
vStream.Position = 0
vStream.Read(vData, 0, vStream.Length)
vImageFile = vData
vData = Nothing
End Using
So we have the metadata saved as Dictionary, and the reduced size image file as the variable vImageFile that we can now save...
The question is - how do we add that metadata back to the new file?
Thank you
------------------- Edit added 01 October 2017 --------------------
I have added this code
Dim vOrientationNumber As Integer = 1
Dim vEXIF As String = ""
Dim vDirectories = ImageMetadataReader.ReadMetadata(file.InputStream)
Dim vSub = vDirectories.OfType(Of ExifSubIfdDirectory)().FirstOrDefault
If Not vSub Is Nothing Then
Dim vOrientationObj = vSub.GetObject(ExifDirectoryBase.TagOrientation)
If Not vOrientationObj Is Nothing Then
If Not vOrientationObj.Equals(DBNull.Value) Then
vOrientationNumber = Convert.ToInt16(vOrientationObj)
End If
End If
End If
For Each vDirectory In vDirectories
For Each Tag In vDirectory.Tags
vEXIF += vDirectory.Name & " " & Tag.Name & " " & Tag.Description & Environment.NewLine
Next
Next
to get a handle on the Orientation number, but the variable vSub is always Nothing. I know with this image the orientation number is there (as it finds it in the main WPF desktop app and rotates it). Any idea what I could be doing wrong now?
Upvotes: 0
Views: 1516
Reputation: 310897
MetadataExtractor doesn't support writing metadata to files. It's a popular feature request, but to do it properly (which is obviously essential given people will likely overwrite their files) will take some work.
However to do this the library does provide some code that might be useful, so long as you're dealing with JPEG files.
JPEG files are basically a list of so-called JPEG segments. The Exif data lives within one of those segments. So if you isolate that segment in the original image, you can replace it after you've resized it.
I don't have any code for this unfortunately. You can use JpegSegmentReader
to extract the segment(s) you need (Exif is in JpegSegmentType.App1
) which should get you started.
The string value you are seeing is a description. To access the raw orientation value, use code like this:
var directories = ImageMetadataReader.ReadMetadata(imagePath);
var subIfd = directories.OfType<ExifIfd0Directory>().FirstOrDefault();
int? orientation = subIfd?.GetObject(ExifDirectoryBase.TagOrientation);
Note that both subIfd
and orientation
can be null, depending upon the image.
It's C# as I don't know VB.NET, sorry. Hopefully it's a straightforward conversion for you.
Upvotes: 1