שתף באמצעות


Modifying JPEG Exif metadata with Visual Basic

Question

Tuesday, June 23, 2015 4:05 AM

I am looking for a way to change a metadata field on a JPG file in VB 2010 and Windows 7.
This is the same result as if you selected the file in Windows Explorer and clicked on the Title field in the details pane and made a change.
What does *not* work is:

  Dim MyImage As Image = Nothing
  MyImage = Image.FromFile("C:\Test\mypic.jpg")
    '..make changes here, or don't..
  MyImage.Save(C:\Test\mypic.jpg)   'this fails; External exception

The reason being that "The image was saved to the same file it was created from."
In theory, I could save the file under a new name and follow that with delete and rename, but that can't be a best practice.
What's the right way to do this?

All replies (5)

Tuesday, June 23, 2015 6:05 AM ✅Answered

[...]

  Dim MyImage As Image = Nothing
  MyImage = Image.FromFile("C:\Test\mypic.jpg")
    '..make changes here, or don't..
  MyImage.Save(C:\Test\mypic.jpg)   'this fails; External exception

The reason being that "The image was saved to the same file it was created from."

[...]

Hi,

open the Image from stream to re-save it to the same filename, or:

open the image fromFile,

create a new Bitmap from it

dispose the image you opened from file

and then work and re-save the bitmap.

https://msdn.microsoft.com/en-us/library/System.Drawing.Image.FromStream%28v=vs.110%29.aspx

Note that re-saving as Jpeg will probably affect the quality of the image, because its re-encoded and the default quality setting is something about 75 of 100. Use EncoderParameters to get the best quality (100). For testing I'd save the images into different files (different fileNames), or you'll probably lose quality in the original image.

        Dim img2 As Image = Nothing

        Using fs As New IO.FileStream("somePath", IO.FileMode.Open)
            img2 = Image.FromStream(fs)
            'work with img2 and
            img2.RotateFlip(RotateFlipType.Rotate180FlipNone)
        End Using

        img2.Save("somePath", System.Drawing.Imaging.ImageFormat.Jpeg) 'use EncoderParams to get bertter quality
        img2.Dispose()

or

        Dim img As Image = Image.FromFile("SomePath")
        Dim bmp As Bitmap = New Bitmap(img) 'will create a 32bpp bitmap
        img.Dispose()

        'work with bmp and
        bmp.Save("SomePath")

Regards,

  Thorsten


Tuesday, June 23, 2015 4:41 AM

I am looking for a way to change a metadata field on a JPG file in VB 2010 and Windows 7.

Use the component and examples provided here:
http://www.codeproject.com/Articles/4956/The-ExifWorks-class

You must rewrite the file - there is no other way to make the changes permanent.


Tuesday, June 23, 2015 6:03 AM

The reason being that "The image was saved to the same file it was created from."
In theory, I could save the file under a new name and follow that with delete and rename, but that can't be a best practice.
What's the right way to do this?

A right practice is how you describe that it goes, the worst is what you want. 

If the file writing goes wrong while overwriting it is gone, if it is not still saved somewhere. 

Success
Cor


Wednesday, June 24, 2015 2:53 AM

Thanks to everyone for their comments and suggestions. Yes, I realize that rewriting the file will be necessary, and it looks like I'll need to manually do the upload/delete/rename sequence in a Try...Catch block. Thorsten's point about EncoderParameters  is important, since I don't want to lose image quality just because I modified an Exif field. After rummaging around on MSDN, I think I found the example I need under EncoderParameters:

https://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.DRAWING.IMAGING.ENCODERPARAMETER);k(TargetFrameworkMoniker-".NETFRAMEWORK%2cVERSION%3dV4.0");k(DevLang-VB)&rd=true


Wednesday, June 24, 2015 2:59 AM

After rummaging around on MSDN, I think I found the example I need under EncoderParameters:

https://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.DRAWING.IMAGING.ENCODERPARAMETER);k(TargetFrameworkMoniker-".NETFRAMEWORK%2cVERSION%3dV4.0");k(DevLang-VB)&rd=true

Hi,

yes, this (setting the encoder quality) is what I meant.

Regards,

  Thorsten