How can I save an image using System.Drawing.Imaging without auto rotating it? - vb.net

When I resize my image and save it using the "System.Drawing.Imaging" save function, it adds the rotation embedded from the EXIF data and rotates my good original picture 180 degrees. I tried saving it in a different format to remove the EXIF data but it still includes the EXIF rotation for the new picture. Any ideas on how I can save the picture in the orientation I can see in the thumbnails .
Private Sub ClearEXIF()
Dim Pname As String = Nothing
For Each Fil In Directory.GetFiles(DlDir)
OK2Go = False
If Fil.Contains("jpg") Then OK2Go = True
If Fil.Contains("jpeg") Then OK2Go = True
If OK2Go Then
Dim bmp As Bitmap = Image.FromFile(Fil)
Pname = GetLastName(Fil) 'this function gets the name of the jpg without the path info
temp1 = Split(Pname, ".")
bmp.Save("C:\Temp\Flat\" & temp1(0) & "+" & temp1(1) & ".png", ImageFormat.png)
bmp.Dispose()
End If
Next
MsgBox("Done")
End Sub

Related

Scaling Imaging from URL using Web Broswer Control

I am having a problem trying to get a Web Browser control in a MS Access form to display an image from a URL correctly.
I am using .navigate (strImagePath) to place the imaging in to WebBrowser1. That works fine. The images are jpg and I have the full path and image filename.
The problem is the that the image is displayed at 100% scale, which is larger than the size of the browser. I can use zoom (OLECMDID_OPTICAL_ZOOM) to scale the image, but this only works if I know the size of the image, which I don't to get the right zoom factor.
Ideally, I would like to have the image fit to window without having to determine the image size.
It that is not possible, the other option is to determine the image size and then set the appropriate zoom. I have not figured a way to determine the image size without saving it locally. Which would be a big overhead and add a unacceptable lag to the form display, specially when move through records. Any ideals here?
Thanks
I was able to get it running after the code from Thomas.
There is the final code.
Public Function DisplayImage(ctlImageControl As Control, strImagePath As Variant) As String
On Error GoTo Err_DisplayImage
Dim strResult As String
Dim intHeight As Integer
Dim intWidth As Integer
Dim intHeightZoom As Integer
Dim intWidthZoom As Integer
Dim intPageZoom As Integer
With ctlImageControl
If strImagePath = "" Then
.Visible = False
strResult = "No image name specified."
Else
.Visible = True
.Navigate (strImagePath)
Do While .Object.Busy Or .Object.ReadyState <> 4 'wait to imaged loaded
DoEvents
Loop
intHeight = .Document.images(0).clientHeight
intWidth = .Document.images(0).clientWidth
intHeightZoom = CLng(21600) / intHeight
intWidthZoom = CLng(43200) / intWidth
If intHeightZoom < intWidthZoom Then
intPageZoom = intHeightZoom
Else
intPageZoom = intWidthZoom
End If
.Object.ExecWB OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, _
CLng(intPageZoom), vbNull
strResult = "success"
End If
End With
Exit_DisplayImage:
DisplayImage = strResult
Exit Function
Err_DisplayImage:
Select Case Err.Number
Case 2220 ' Can't find the picture.
ctlImageControl.Visible = False
strResult = "Can't find image in the specified name."
Resume Exit_DisplayImage:
Case Else ' Some other error.
MsgBox Err.Number & " " & Err.Description
strResult = "An error occurred displaying image."
Resume Exit_DisplayImage:
End Select
End Function
There the function is called by
Me!txtFaceResults = DisplayImage(Me!WebBrowser1, strFullImageName)
While it works to zoom the images to a uniform size, the scaling is still off. But the general process works of loading the images in to the ActiveX Web Browser object. Reads the image size and calculates a zoom factor and then apply the zoom. It is important to wait for the image to load, otherwise you will either get an error or the size of the previously loaded image.
I was not able to use HtmlImg Type as Thomas used, so I got the elements individually. I used the documentation on Mozilla at:
https://developer.mozilla.org/en-US/docs/Web/API/Element
to see the element available.
If you have only the image loaded, the following code will get you the width and height of that image.
Dim img As HtmlImg
Set img = Me.WebBrowser1.Document.images(0)
Debug.Print img.naturalHeight, img.naturalWidth
However, I was not really able to calculate the correct zoom factor nor to pass a variable zoom factor to the ExecWB-method - I always got a runtime error, not matter which data type I used (constant values are working).
Plus, at least in my tests, the image was displayed with (white) borders which also would influence the zoom factor. Anyhow, the width and height are exactly the dimensions of the test image I was playing with.

Slow speed of VBA command (Application.FollowHyperlink) in a local network

I am using a MS Access application in local network, this application have form for display data, and one of the features in the form is opening picture files regarding the data in the form. My issue is opening the pictures are very slow for the Front End users (1 to 5 seconds). This is my function for the opening photos:
Public Sub OpenPicture(PictureName As Variant)
If PictureName <> "" Then
DoCmd.SetWarnings False
Dim iPath , filePath As String
iPath = "C:\photo\"
filePath = iPath & PictureName
Application.FollowHyperlink filePath
DoCmd.Requery
DoCmd.SetWarnings True
End If
End Sub
In the above code, PictureName is the name of the image in the DataForm. I should mention there are Image controls for showing pictures in the DataForm, but these controls are small. My purpose is to crop or rotate these pictures in case of need in other programs.
Also I have a lot of image files (more than 200000) in the image source folder.
Please help me for improving the speed of this function.
Thanks in advance.

Retrieving images from a database?

I'm new to the forums and wanted to ask a question that has been bugging me for ages. I am using Visual Studio express 2012 with Windows Forms.
I want to have a database consisting of different images. Each row has its own image, and the other fields in the row define the images characteristics (I.E. Colour = Red, Striped = Yes etc) and its own specific ID.
Now what I want to do is allow the user to search via the form (Selecting what characteristics they want the image to have based on options on the form and then using SQL statements to retrieve the images based on their inputs). The only issue I am having is displaying all of the images on the form when they have searched? Is there any idea as to how to do this dynamically?
I created a form with FlowLayoutPanel in it. I set its AutoScroll property to true so that if there more pictures than fit in the space, it'll show a scroll bar so you can see them all.
I'm not entirely sure how you're getting the image, but assuming you have a function that returns a list of images.
Private Function DoImageSearch(parameters As SearchParameters) As List(Of Image)
'Go get images from database
End Function
Then you could have a function like the following to dynamically create PictureBox controls to be added to the FlowLayoutPanel.
Private Sub DynamicallyCreatedPictureBoxes(images As List(Of Image))
For Each image In images
Dim picture = New PictureBox()
picture.Image = image
picture.Size = image.Size
FlowLayoutPanel1.Controls.Add(picture)
Next
End Sub
In this case I've set the size of the PictureBox to be the size of the image. You may want to try to scale them or make thumbnails, but I'll leave that up to you (or another question). You'd probably also want another method to clear the images.
Private Sub ClearPictureBoxes()
FlowLayoutPanel1.SuspendLayout()
For Each control As Control In FlowLayoutPanel1.Controls
control.Dispose()
Next
FlowLayoutPanel1.Controls.Clear()
FlowLayoutPanel1.ResumeLayout()
End Sub
I'm not confident that last method is entirely correct, but you'd probably want something close to it.
Try like the this,
If color_RadioButton.Checked = True and type_RadioButton.Checked = True Then
cmdTect="color='" & color_RadioButton.Text & "' and type='" & type_RadioButton.Text & "'"
ElseIf color_RadioButton.Checked = True and type_RadioButton.Checked = False Then
cmdTect="color='" & color_RadioButton.Text & "'"
ElseIf color_RadioButton.Checked = False and type_RadioButton.Checked = TrueThen
cmdTect="type='" & type_RadioButton.Text & "'"
End If
dim cmd as new sqlcommand("select count(photo) from tbl where " & cmdTect,conn)
dim cnt as integer=cmd.ExecuteScalar()
for i as integer=0 to cnt
cmd = New SqlCommand("select photo from tbl where" & cmdTect,conn)
Dim imageData As Byte() = DirectCast(cmd.ExecuteScalar(), Byte())
If Not imageData Is Nothing Then
Dim ms As New MemoryStream(imageData, 0, imageData.Length)
ms.Write(imageData, 0, imageData.Length)
Dim pic As New PictureBox
pic.BackgroundImage = Image.FromStream(ms, True)
Panel1.Controls.Add(pic)
End If
Next

Restrict Image by selecting it's URL

I am trying to add Images from websites and I am facing poblem with an issue which is that when I am trying to go to google images and trying to add some Images and when I right click for some images I find "Copy Image URL" and for some I don't find it and I find "Copy link address".Now I want my users to restrict from adding the Images which contain "Copy Image URL"
And I am attaching Images so that you'll understand me in a better way.
How do I do that?
Here is the code for saving the image:
Dim dir_name As String = txtDirectory.Text
If Not dir_name.EndsWith("\") Then dir_name &= "\"
For Each pic As PictureBox In flpPictures.Controls
Dim bm As Bitmap = CType(pic.Image, Bitmap)
Dim filename As String = CStr(pic.Tag)
filename = filename.Substring(filename.LastIndexOf("/") + 1)
Dim ext As String = filename.Substring(filename.LastIndexOf("."))
'Here it gives me an error at(filename.lastindexof(".")
Dim full_name As String = dir_name & filename
Select Case ext
Case ".bmp"
bm.Save(full_name, Imaging.ImageFormat.Bmp)
Case ".gif"
bm.Save(full_name, Imaging.ImageFormat.Gif)
Case ".jpg", "jpeg"
bm.Save(full_name, Imaging.ImageFormat.Jpeg)
Case ".png"
bm.Save(full_name, Imaging.ImageFormat.Png)
Case ".tiff"
bm.Save(full_name, Imaging.ImageFormat.Tiff)
Case Else
MessageBox.Show( _
"Unknown file type " & ext & _
" in file " & filename, _
"Unknown File Type", _
MessageBoxButtons.OK, _
MessageBoxIcon.Error)
End Select
Next pic
Beep()
'WEB CLIENT IS NEEDED TO DO THE DOWNLOAD
Dim MyWebClient As New System.Net.WebClient
'BYTE ARRAY HOLDS THE DATA
Dim ImageInBytes() As Byte = MyWebClient.DownloadData(url)
'CREATE A MEMORY STREAM USING THE BYTES
Dim ImageStream As New IO.MemoryStream(ImageInBytes)
'CREATE A BITMAP FROM THE MEMORY STREAM
PictureBox1.Image = New System.Drawing.Bitmap(ImageStream)
In the top screenshot, you are right-clicking directly on an image.
In the bottom screenshot, you are right-clicking on an empty div with a z-index that puts it above the image.
Here's an example:
<a href="http://example.com">
<img src="myImg.jpg" style="position: absolute;" />
<div style="z-index:1; position:absolute; width:100%; height:100%;"></div>
</a>
When you mouse over the link in Google Images another div is shown on top that contains the saveable image. Have a look with Firebug and see for yourself :)
Note that there is no perfect way to prevent users from saving images from your website. You can disable right click, mask the image with a div, mask the image with a transparent image (so the user can right-click and save the image but they get the wrong one), prevent caching etc but ultimately any tech savvy user can get around this. Still, these approaches will stop casual users so it's better than nothing. If you want to find out more about the methods that I just named, I suggest Googling for "disable save image as" or "disable copy image url".
maybe helpful
Sub Base64Convert(ByVal Base64MSG As String)
'Setup image and get data stream together
Dim img As System.Drawing.Image
Dim MS As System.IO.MemoryStream = New System.IO.MemoryStream
Dim b64 As String = Base64MSG
Dim b() As Byte
'Converts the base64 encoded msg to image data
b = Convert.FromBase64String(b64)
MS = New System.IO.MemoryStream(b)
'creates image
img = System.Drawing.Image.FromStream(MS)
'writes image for displaying
img.Save(Request.ServerVariables("APPL_PHYSICAL_PATH") & "LabelInfo.tiff", System.Drawing.Imaging.ImageFormat.Tiff)
'cleaning up house
img.Dispose()
MS.Close()
End Sub

images vb.net file used by another process error

I'm writing a little program where I select a picture through an open file dialogue. When I selected a picture I want it to overwrite the current picture and display the new image. Now I don't have any problems with picking an image with a different extension. So when I currently have a .png I can select a .jpg but when I choose an image with the same extension as the current image I get an error:
The process cannot access the file 'C:\Users....\woontypeimages\chalet_foto.jpg' because it is being used by another process.
If ofd.ShowDialog() = Windows.Forms.DialogResult.OK Then
Dim sFilename As String = cboWoningtypesWoningtype.SelectedItem.ToString & "_foto" & System.IO.Path.GetExtension(ofd.FileName)
System.IO.File.Copy(ofd.FileName, Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Camping Relaxx\woontypeimages\" & sFilename, True)
txtWoningtypesFoto.Text = sFilename
updateImages()
End If
Private Sub updateImages()
Try
picFoto.Image = Nothing
txtWoningtypesFoto.BackColor = clrReadonly
txtWoningtypesFoto.ForeColor = Color.Black
picFoto.Image = System.Drawing.Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Camping Relaxx\woontypeimages\" & txtWoningtypesFoto.Text)
Catch ex As Exception
txtWoningtypesFoto.BackColor = clrError
txtWoningtypesFoto.ForeColor = Color.White
End Try
Try
picGrondplan.Image = Nothing
txtWoningtypesGrondplan.BackColor = clrReadonly
txtWoningtypesGrondplan.ForeColor = Color.Black
picGrondplan.Image = System.Drawing.Image.FromFile(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Camping Relaxx\woontypeimages\" & txtWoningtypesGrondplan.Text)
Catch ex As Exception
txtWoningtypesGrondplan.BackColor = clrError
txtWoningtypesGrondplan.ForeColor = Color.White
End Try
End Sub
If anyone could help me I would be pleased
Thanks in advance
Instead of worrying about Dispose() you can instead use the Load(string) method of the PictureBox which won't lock the file.
Me.PictureBox1.Load("C:\test.png")
Use these :
picFoto.Image.Dispose()
picGrondplan.Image.Dispose()
instead of :
picFoto.Image = Nothing
picGrondplan.Image = Nothing
The Image.FromFile method maintains a lock on the source file until the image has been disposed. Setting an object to nothing does not immediately dispose it - the garbage collector will take care of that in its own time (which might well not be until you've closed the form with the picture box on). Dispose is required to immediately free the file handle.