Rotate an image (1 Viewer)

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 23:13
Joined
Sep 12, 2006
Messages
15,909
I've spent hours on this , and it's close but no cigar.

I downloaded a database called wiarotate.accdb
I thought it was from here, but it's in German, and there's no information about the source. I've included it here for interest.

It uses the WIA library.

The utility reads the exif data from an image, determines the rotational status value, and applies that value, on a copy of the image processed in the WIA module, and then copies the data back into the image object.

I am trying to use the code in my own app, and I when I try to load the rotated image I get error 2192, "image is not a device independent format" is an example.

The wiarotate database is attached.

This code works in wiarotate.
In my own app, with some of the code changed very slightly the line labelled B: fails with error 2192, but using my code in WIARotate, it works correctly, so I can only think I must be missing something.

What I get is this

An image not requiring rotation generates a system error that no filter was used, and then resumes at label B, and then all images whether rotated or not produces the 2192 error. I assume the WIArotate code gets the system error, but ignores it, but it doesn't get the 2192 error.

I can only think there is something different about my app, and my image controls are different somehow to the image controls in the WIARotate database.

The error 2192 occurs with this line
Let Me.Image1.PictureData = Image.FileData.BinaryData 'display the adjusted image from the WIA process.

I have checked all the references, and adjusted them so they are identical in both databases.



CODE IN WIAROTATE
Code:
Private Sub Liste0_Click()
    Dim Image As WIA.ImageFile
    Dim ip As WIA.ImageProcess
    Let Me.Bild3.Picture = Me.path & Me.Liste0.ItemData(Me.Liste0.ListIndex)
    Let Me.Bild4.Picture = ""
    Let Me.TB_Orientation.Value = 1
    Set Image = New WIA.ImageFile
    Call Image.LoadFile(Me.path & Me.Liste0.ItemData(Me.Liste0.ListIndex))
    If Image.Properties.Exists("274") Then
        Set ip = New WIA.ImageProcess
        With ip
            On Error GoTo B
            Let Me.TB_Orientation.Value = Image.Properties("274").Value
            Select Case Image.Properties("274").Value
                Case 2: Call mkFlt(ip, "FlipHorz")
                Case 3: Call mkFlt(ip, "Rotate", 180)
                Case 4: Call mkFlt(ip, "FlipVert")
                Case 5: Call mkFlt(ip, "FlipHorzandRotate", 270)
                Case 6: Call mkFlt(ip, "Rotate", 90)
                Case 7: Call mkFlt(ip, "FlipHorzandRotate", 90)
                Case 8: Call mkFlt(ip, "Rotate", 270)
            End Select
            Set Image = .Apply(Image)
        End With
    End If
B:  Let Me.Bild4.PictureData = Image.FileData.BinaryData
X:  Exit Sub
E:  Debug.Print Err.Description
End Sub


Sub mkFlt(ip As WIA.ImageProcess, sflip$, Optional ByVal rotatevalue As Integer)
    With ip
        Select Case sflip
            Case "FlipHorzandRotate"
                Call mkFlt(ip, "FlipHorz")
                Call mkFlt(ip, "Rotate", rotatevalue)
            Case "FlipHorz"
                Call .Filters.Add(.FilterInfos("RotateFlip").FilterID)
                Let .Filters(.Filters.Count).Properties("FlipHorizontal") = True
                Let .Filters(.Filters.Count).Properties("FlipVertical") = True
                Call mkFlt(ip, "FlipVert")
            Case "Rotate"
                Call .Filters.Add(.FilterInfos("RotateFlip").FilterID)
                Let .Filters(.Filters.Count).Properties("RotationAngle") = rotatevalue
            Case "FlipVert"
                Call .Filters.Add(.FilterInfos("RotateFlip").FilterID)
                Let .Filters(.Filters.Count).Properties("FlipVertical") = True
        End Select
    End With
End Sub



MYCODE

Code:
Public Sub ProcessImage(infile As String)

Dim txtfile As String

Dim Image As WIA.ImageFile
Dim ip As WIA.ImageProcess
 
    txtfile = infile
    MsgBox "Processing: " & txtfile  'to check the file being processed
 
    Let Me.ImageOrig.Picture = infile 'just to display the unadjusted image
    Let Me.Image1.Picture = ""
 
    Let Me.TB_Orientation.Value = 1
    Set Image = New WIA.ImageFile
 
    Call Image.LoadFile(infile)
 
    If Image.Properties.Exists("274") Then
        Set ip = New WIA.ImageProcess
        With ip
     
'            On Error GoTo B:
            On Error GoTo Err_Handler1
         
            Let Me.TB_Orientation.Value = Image.Properties("274").Value
            Select Case Image.Properties("274").Value
                Case 2: Call mkFlt(ip, "FlipHorz")
                Case 3: Call mkFlt(ip, "Rotate", 180)
                Case 4: Call mkFlt(ip, "FlipVert")
                Case 5: Call mkFlt(ip, "FlipHorzandRotate", 270)
                Case 6: Call mkFlt(ip, "Rotate", 90)
                Case 7: Call mkFlt(ip, "FlipHorzandRotate", 90)
                Case 8: Call mkFlt(ip, "Rotate", 270)
            End Select
            Set Image = .Apply(Image)
        End With
    End If
 
B:  On Error GoTo Err_Handler2
    Let Me.Image1.PictureData = Image.FileData.BinaryData 'display the adjusted image from the WIA process.

X:  Exit Sub

E:  'you can't get here now. This is replaced by the 2 error handlers below.
    Debug.Print Err.Description
    MsgBox "Error: " & Err & "  Desc: " & Err.Description

Exit Sub

Err_Handler1:
    MsgBox "Error: " & Err & "  Desc: " & Err.Description, , "Handler1"
    Resume B:

Err_Handler2:
    MsgBox "Error: " & Err & "  Desc: " & Err.Description, , "Handler2"

End Sub
 

Attachments

Try looking at my example app which can rotate images

There are also several articles on WIA on Daniel Pineault's DevHut website
 
@isladogs

Hi Colin. I had already downloaded your demo, but I couldn't follow it, and it wouldn't compile anyway. Maybe that was because I'm using 32 bit Access. However, based on what I had tried with wiarotate , I took another look and used this bit of code you had used.

Code:
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

'and then effectively
       myimage.picture = strpath

So my original code is supposed to flip and rotate the image in memory within wia, and then load the image bitmap into the display image object. That is working in my test, but not working in my application.

However, I can flip and rotate the image, save it to a diskfile, and set the displayimage to use the diskfile. Slower, but it works.
 
Which version of Access are you using. It should work in both 32-bit & 64-bit Access from A2010 onwards.
Not tested in A2007 but likely to have reference issues in A2007
 
Which version of Access are you using. It should work in both 32-bit & 64-bit Access from A2010 onwards.
Not tested in A2007 but likely to have reference issues in A2007
Colin,
Your app appears to work fine in my 32bit 2007 Access?
Your copyright for that program stops at 2021?
1702024443327.png
 
Thanks @Gasman
Obviously A2007 is 32-bit only.
In later versions, the interface looks similar to this

1702026664103.png


As shown, it automatically rotates images using WIA code on the image EXIT data
It also allows you to save the 'correctly rotated' image for future use

However, I haven't checked whether the rotation code works correctly in A2007
The 'copyright info' in the form footer is used to indicate the year it was last updated - in this case 2021
 
I have just noticed one thing however.
If I right click on a photo I have the option to Cut/Copy/Paste, but copying only copies the filename and not the picture?
 
Just to confirm, Colin's app worked in the form I opened, which looks like the one Colin just showed above, but the app wouldn't compile.

As my code was working except for being able to copy the converted image directly to an image control, I used the alternative option of saving the converted image to disk, and then setting the image to that disk file, which I saw Colin was doing. As I only wanted to display an image, that was fine for my purpose.

The WIARotate app copied the bitmap representation from the wia image to the visible image control,rather than saving it to disk, but errored in my database and I couldn't work out why.

I think Colin's app is doing a lot more, but there is much less code in the WIARotate example.

My database was actually designed to manage a collection, and the code element was used to show photos of an individual item in the collection with a separate folder used for each item.
 
Dave
You still didn't tell me which version you were using when you tested my app.
Although intended for A2010 onwards, both @Gasman & I have tested it in A2007. Did you check references?
 
I have just noticed one thing however.
If I right click on a photo I have the option to Cut/Copy/Paste, but copying only copies the filename and not the picture?
AFAIK, that's normal for an image control
 
Sorry, I've just got round to replying.

Colin. Your database worked, but would not compile in 32bit Access current version. (or any other version - that's why I tried to find another solution)

As I said, I used your code to save the rotated image to disk, and assigned that image to an image control. This works.

See the attached cut down database, which I didn't need to zip. It's supposed to manage a collection of clocks and watches. All this includes is the main watch form, and the image viewer. The database just includes a single watch. If you click the small folder icon, you will be able to select an image folder. If you then click the camera icon you will be able to display the photos in that folder.

The showphoto form displays a small copy of the image, and then rotates it with wia code according to the exif setting. Using Colin's display code, it then displays the image by saving the file and then assigning the saved file to the large image control. I deliberately didn't kill the image so I could see the rotated image, and I now see there is an issue (see below).

If I select WIA code from the option group, and move to the next photo, it tries to assign the WIA bit map to the image control, but it errors, as I noted before. This same code works in the original WIARotate program, or at least I can't see any difference between the two databases.

Now I just realised there is a catch. When I look at the photo in the original folder in windows, it looks correct. When I see that same image in my display form that is originally rotated 90 degrees anti clock wise from what I see in the folder, and that is then corrected in the large image. However, I can now see that the image saved by Colin's code is actually rotated 90 degrees clockwise, so I really am not sure what is happening.

Any help would be great.
 

Attachments

Dave
Despite repeated requests you still haven't said which version of Access you are using. What does 'current version' mean?
You've also given no hint about what compile errors you got

However, I've just realised I left in a module (Module1) with code from another AWF member that I was testing several months ago & forgot to remove. I've now uploaded a replacement file without the offending module.
The code wasn't used by me app so either delete Module1 or download a fresh copy
 
@isladogs

I have A2003, and M365, Access Version 2311, 16.0 etc, both 32bit.

I couldn't get the WIARotate code to work in my (either) dbs, as I said, although my code seemingly worked correctly when used in WIARotate database.

Your form frmFolderImages worked correctly, but I couldn't follow your code fully. Since studying WIARoate, it makes more sense now, and I understood enough to use the code snippet to display the final image. I didn;t understand it enough to completely use you ode instead of mine.

I just compiled your code, and it errored at the objpreview assignment in module1, with variable not defined. Is that what you meant.

I suspect that it's not totally coincidentally that is the exact line of code that isn't working for me, an attempt to assign binary data from the img object to an image control. Maybe you were looking at that for another user, although I can't see we have an "IronFelix". Irrespective, that line gives me the 2192 error, but maybe it works for you. I can't understand why it doesn't work for me, as it does when I put my code in the WIARotate dbs.

Code:
Private Sub Test()
'IronFelix717 https://www.access-programmers.co.uk/
Dim fpath           As String
Dim img             As WIA.ImageFile

'fpath = *your path to file*

'ROTATING THE TARGET IMAGE, MODIFYING EXIF, AND WRITING TO DISK (OVERWRITE):
Set img = RotateFlipImage(fpath, fpath, 90, 1)


'ROTATING THE TARGET IMAGE AND ASSIGNING DATA TO A CONTROL:
Set img = RotateFlipImage(fpath, , 90)
objPreview.PictureData = img.FileData.BinaryData


'SIMPLY RETURNING IMG FILE OBJECT (MIS-USE OF FUNCTION)
Set img = RotateFlipImage(fpath)
objPreview.PictureData = img.FileData.BinaryData
End Sub

PS. I just commented out the objPreview assignments, and your dbs compiles. now.
 
Last edited:
Hi
The above few posts may be out of sequence as I wrote post #12 this morning but forgot to send it till much later.
Thanks for the clarification.

None of the code in module1 is used in my app. I recommend deleting it.
That code was provided by AWF member @ironfelix717 but I never got it to fully work or indeed compile(!)
It shouldn't have been included and I can't advise on its use.

I haven't studied your code but I know mine works.
There is an odd glitch with Access rotating jpg files by 90 degrees clockwise.
You can see that if you view files in Windows File Explorer and then in Access. The 8 sample images of the letter F were used to test functionality.
This rotation is nothing to do with my code which is in fact designed to take that into account.
 
Ironfelix is no longer showing as a member. Anyway, his error appears to be with the same line as mine, which is curious, and you also couldn't get it to work, although I don't think that usage would work anyway.
 
Thanks for the link. As I have a working version now, I don't think I will spend a lot of time on this, although I would like to understand how to get it to work.
 
The working version saves the IMG in memory, and then assigns it to the image control. (Your solution)

What I wanted to do was assign the bitmap for IMG in memory directly to the image control, without needing to save it to disk, but that's not working. (Ideal solution)

See the sample database I uploaded in #11 which lets you choose between your solution, and my ideal solution.
 
OK I understand now. Sorry but I don't have the time to investigate further
 

Users who are viewing this thread

Back
Top Bottom