Solved VBA - Image control, orientation incorrect, get EXIF data (1 Viewer)

ironfelix717

Registered User.
Local time
Yesterday, 19:57
Joined
Sep 20, 2019
Messages
193
Hi all,

An app I have built and use frequently uses a lot of photos (of varying dimensions). The source of the photos is usually a cell camera. The problem is, the photos are displayed in the control with the incorrect orientation. If the photo was taken "side-ways" (landscape) with the cell phone, the photo is displayed correctly. If the photo was taken as a regular portrait ("vertical"), then the photo is always incorrectly displayed (90 degrees out).

Windows explorer serves these photos in the correct orientation when viewing them. Likewise on any other device.

How I have remedied this is with a Python script I wrote which orients the Image's EXIF data 90 degrees (Viewing the exact file in Windows after this script is ran displays the photo the same. However, Access image control serves it correctly now (90 degree). So it works, but naturally, its slow as hell and I need a faster solution.

So,
I am looking for a way to read the EXIF image orientation in VBA during upload and automatically rotate it. All in VBA, so its fast and native.

Thanks!
 
there is a project in sourceforge (not actually used it), you might
want to try:
 
Someone was doing something similar over here?
 
EXIF data contains an orientation value from 1 to 8:
  1. = 0 degrees: the correct orientation, no adjustment is required.
  2. = 0 degrees, mirrored: image has been flipped back-to-front.
  3. = 180 degrees: image is upside down.
  4. = 180 degrees, mirrored: image has been flipped back-to-front and is upside down.
  5. = 90 degrees: image has been flipped back-to-front and is on its side.
  6. = 90 degrees, mirrored: image is on its side.
  7. = 270 degrees: image has been flipped back-to-front and is on its far side.
  8. = 270 degrees, mirrored: image is on its far side.
So all you need to do is read the value and use code to rotate by 1 or more multiples of 90 degrees as necessary

See Rotate Photos to be Upright - Sirv Help Center. The link contains some utilities you may find useful
 
there is a project in sourceforge (not actually used it), you might
want to try:

Thanks for the resource. This attempts to solve half of my problem. It can read EXIF but not write it. Is there a class out there to quickly allow writing?


So far, i've gotten two different values from a couple tests on various photos reading Orientation tag using the code. These values were: 53 and 47. Most common is 53. This doesn't jive with what @isladogs is saying. So, the code is faulty or I am missing something.

Ideas?

Thanks
 
I've not looked at the link supplied by @arnelgp so can't comment on the code or whether your implementation is correct.
However, the following code supplied by @daolix (see link in post #3) uses WIA to get EXIF data including GPS values:

Code:
Sub WIA_TEST(ByVal sFile As String)
    Dim sn As String * 24
    Dim p As WIA.Property
    Dim v
    With New WIA.ImageFile
        .LoadFile sFile
        For Each p In .Properties
            sn = p.Name
            Debug.Print p.PropertyID, sn, p.Type, "ist Vector: "; p.IsVector,
            If p.IsVector Then
                For Each v In p.Value
                    Debug.Print Format(v); ", ";
                Next
                Debug.Print
            Else
                Debug.Print p.Value
            End If
        Next
    End With
End Sub

I have tested it on numerous image files and, where orientation data is supplied, it is ALWAYS one of the values from 1-8.
Example output attached as text file

You can also get the orientation info from the extended properties of image files.
However that reports a text string such as Normal or Rotate 270 degrees etc.

The attached application gets the properties of all the images in a folder including the orientation (using extended file properties)
It then automatically rotates a copy of the selected image so it appears correctly for display purposes.

Click Populate Image List to select a folder containing images then select any image in the list to see the image properties and a thumbnail that should always appear correctly oriented

1628459063039.png


NOTE:
1. The original image is NOT altered. In other words the file properties aren't changed.
2. It does not use EXIF data but it should be easy enough for you to adapt
 

Attachments

I've not looked at the link supplied by @arnelgp so can't comment on the code or whether your implementation is correct.
However, the following code supplied by @daolix (see link in post #3) uses WIA to get EXIF data including GPS values:

Code:
Sub WIA_TEST(ByVal sFile As String)
    Dim sn As String * 24
    Dim p As WIA.Property
    Dim v
    With New WIA.ImageFile
        .LoadFile sFile
        For Each p In .Properties
            sn = p.Name
            Debug.Print p.PropertyID, sn, p.Type, "ist Vector: "; p.IsVector,
            If p.IsVector Then
                For Each v In p.Value
                    Debug.Print Format(v); ", ";
                Next
                Debug.Print
            Else
                Debug.Print p.Value
            End If
        Next
    End With
End Sub

I completely missed the URL in the post. Apologies.

Yeah, the code in the provided link mentions nothing about Windows Image Acquisition (WIA). There is ExifTool command line tool, but I have no idea where you get WIA. Its not listed in the references on my installation.

Thanks


UPDATE: Found it under Microsoft Windows Image Aquisition Library 2.0
 
Last edited:
UPDATES:

I've been playing around. I'm able to read the EXIF orientation. Cool.
I am able to rotate the image in VBA with Carda Consultants code.... Cool.... Except it doesn't alter the EXIF data (as @isladogs points out) at the bottom of post #6. Its a hard rotate and doesn't actually modify the EXIF in conjunction with the image processing.

One would think simply..
property.value = value
Would suffice at writing the EXIF. But remember, we're discussing a tool that Microsoft developed. Why would it be that simple?

This is not a solution to rotating the image if the EXIF won't match because now, Windows Photos serves the file incorrectly. Furthermore, I find it comical that Windows and any other photo application has no problem displaying a cell phone portrait (Orientation = 6) in the proper orientation, but Access' image control has a challenge with it. So, that begs the question, what ELSE is being analyzed in the EXIF that allows Windows Photos and other apps to serve the photo correctly? Apparently the 'Orientation' tag is as useless as they come.
 
Windows and the other programs rotate the images when displaying them using the exif tag without changing the file. The correct positioning in Acces you have to program accordingly.
Load the image into a wia.imgefile, read the corresponding tag, rotate/mirror the image according to the tag and assign the content of the wia.imagefile-object to your image control without saving anything on the harddisk. done. No exif tags need to be changed either.
 
WIA. Its not listed in the references on my installation.

UPDATE: Found it under Microsoft Windows Image Aquisition Library 2.0

The code in my app including that from DevHut uses late binding. The reference wasn't required or used in my app.

Back in post #1, you wrote
I am looking for a way to read the EXIF image orientation in VBA during upload and automatically rotate it. All in VBA, so its fast and native
The code I provided does exactly that.
Originally, you didn't state that you wanted the original file overwritten with orientation reset to zero.

This is not a solution to rotating the image if the EXIF won't match because now, Windows Photos serves the file incorrectly. Furthermore, I find it comical that Windows and any other photo application has no problem displaying a cell phone portrait (Orientation = 6) in the proper orientation, but Access' image control has a challenge with it. So, that begs the question, what ELSE is being analyzed in the EXIF that allows Windows Photos and other apps to serve the photo correctly? Apparently the 'Orientation' tag is as useless as they come.

I don't accept that.
Windows File Explorer reads the extended file properties and adjusts the display so it looks correct on screen. It doesn't change the original file.
Access is not designed as an image manipulation program. It normally displays images exactly as created e.g. Rotate 270 degrees. To make it look correct, code is used to create a COPY of the image and rotate that by the appropriate amount

You can find lots of code to rotate, flip, resize & crop images using WIA. For example:
VBA Image Resize Function by Geoff Griffith, Imagne Thought Software (msaccessgurus.com)
and even better vba - How to rotate, crop, scale, flip an image? - Stack Overflow
However this is always done to a copy of the original file

If you want to make a permanent change to your images, I suspect you will need to make use of image editing software.
However, I would be pleased to be proved wrong about that

EDIT:
@Nixversteher posted just a few seconds before I did but has I believe made exactly the same points.
 
If you want to make a permanent change to your images, I suspect you will need to make use of image editing software.
However, I would be pleased to be proved wrong about that
No. You do not need any additional software.
The following example (code fragment) changes the exif tag for the orientation:

Code:
With New WIA.ImageProcess
    call .Filters.Add(.FilterInfos("Exif").FilterID)
    let .Filters(1).Properties("ID") = 274                                  ' = GDIP   "PropertyTagOrientation"
    let .Filters(1).Properties("Type") = UnsignedIntegerImagePropertyType   ' = Equivalent to GDIP "PropertyTagTypeShort"
    let .Filters(1).Properties("Value") = "___Value 1 - 8___"
    set image = new wia.imagefile
    call image.loadfile(___YourImageFile___)
    Set imgage = .Apply(Image)
    call img.SaveFile(___YourNewImageFile___)
End With
 
Yes I have. And it worked for me.
how? you have 3 different variables there:

image, imgage, img?

how about the "other" properties?
you are only interested on the Orientation property?
there are at least 18 of them.

you mean, when you test.
changing the Orientation on the exif property
will "actually" change the "physical" orientation
of the .jpg and therefore will show in
access image control in correct orientation.
 
Last edited:
yes, that's right, once again I didn't have my glasses on.
But I don't know what you mean by the other 18 propertys. The typo-ridden example of mine only changes the Exif tag for orientation. But there are more than 18 Exif tags (.Properties ("ID")). The code fragment also does not change the physical orientation of the image. Changing Exif data and changing image data are two different things. For my test I rotated and / or mirrored the pictures, then changed the exif tag accordingly, and saved them in a new file. In Windows or image software, the images are displayed in the correct orientation, the image control element shows the images as they are on the disk because the Exif data is not interpreted.
 
@Nixversteher
Many thanks for your code. Although it had errors, it was easy to fix & I can confirm it does work

I've now added a cmdResetOrientation button to my main form :

1628538545047.png


The button is only visible when the original image has been rotated
When clicked, the temp image is first modified to Orientation = 1 (Normal), then the original image is overwritten.
The form data and display is then updated (including hiding the button)
The whole process takes less than a second to complete for a single image

1628538357323.png


The button has the following code:
Rich (BB code):
Private Sub cmdResetOrientation_Click()

'Modified version of code supplied by @Nixversteher on 09/08/2021 at:
'https://www.access-programmers.co.uk/forums/threads/vba-image-control-orientation-incorrect-get-exif-data.318976/#post-1779107

'changes orientation value to 1 (Normal) in temp file ...
'then overwrites original file
'finally updates table data and form display

On Error GoTo Err_Handler

    Dim strPath As String
    strPath = Me.lstImages
   
    Dim img As Object, IP As Object
    Set img = CreateObject("WIA.ImageFile") 'create WIA objects
    Set IP = CreateObject("WIA.ImageProcess")
   
    With IP
        .filters.Add (.FilterInfos("Exif").FilterID)
        .filters(1).Properties("ID") = 274    'Orientation    ' = GDIP   "PropertyTagOrientation"
        .filters(1).Properties("Type") = 1003 'UnsignedIntegerImagePropertyType   ' = Equivalent to GDIP "PropertyTagTypeShort"
        .filters(1).Properties("Value") = 1 'Normal orientation - possible values = 1-8
        img.LoadFile (strTempImage) 'load temp image
        Set img = .Apply(img) 'apply changes
        Kill strPath 'delete original image so it can be overwritten
        img.SaveFile (strPath) 'save updated image to original path
    End With
   
    AddFileAttributes 'update tblImages
    Me.lstImages.SetFocus 'move focus so cmdResetOrientation button can be hidden
    lstImages_Click 'update display
   
Exit_Handler:
    Exit Sub

Err_Handler:
    MsgBox "Error " & Err.Number & " in cmdResetOrientation procedure : " & vbNewLine & _
        Err.description, vbExclamation, "Error"
    Resume Exit_Handler
   
End Sub

It would be very simple to add a procedure to loop through all the rotated image files in a folder and reset the orientation.
However, I will leave that for the OP if he wishes to do so
 

Attachments

Using the code provided by @Nixversteher, I was able to modify the EXIF.

To reiterate some points:
The source of confusion (for me, at least) is the comparison of real-life orientation, versus what the EXIF alleges is the orientation. Real-life orientation being what the user actually intended to be the orientation of the photo - which is almost always 1. A user rarely takes a photo with the intent "Ah, yes, the photo should be sideways when viewing it in post"... Rather, it is, "I am going to take this photo, and view it as the SAME as I see it here, in post."

Therefore, whether a user is taking a photo with their phone in LANDSCAPE or PORTRAIT, the EXIF should ALWAYS be 1, because the photo was taken exactly as the user intended to view it on their screen. Instead, cell phone manufacturers decided to just alter the EXIF when the phone is changed to portrait versus landscape, rather than physically rotate the photo. Computationally efficient? Perhaps. Seems pretty lazy and superficial to me.


@Nixversteher explained...
Windows and the other programs rotate the images when displaying them using the exif tag without changing the file. The correct positioning in Acces you have to program accordingly.

As compared to Access' "dumb" control (dumb - meaning, does not have any intelligence built in to analyze the EXIF). Which in its right, should not have to.

So, it was learned (to me, at least) that modifying the EXIF orientation only changes how a 'smart' application will serve the photo to you. But doesn't at all change the physical orientation of the image data.
 
Therefore, whether a user is taking a photo with their phone in LANDSCAPE or PORTRAIT, the EXIF should ALWAYS be 1, because the photo was taken exactly as the user intended to view it on their screen.
that is what you think or wish. but phones have "sensors" and knows which is portrait and landscape.
so your wish will never happen.
 

Users who are viewing this thread

Back
Top Bottom