Reputation: 97
I'm trying to retrieve image dimensions from an image URL. How is this possible? I've done plenty of research and haven't found any code that can achieve this, all of the information gets image dimensions from an image on the local disk which is not what I want.
Is it possible to achieve this?
Upvotes: 3
Views: 1226
Reputation: 802
You don't need to download entire file, only first few bytes. If image is PNG
, width is in 17th, 18th, 19th and 20th byte, and height is in 21st, 22nd, 23rd and 24th byte. If it's GIF
, width is in 7th and 8th byte, and height is in 9th and 10th byte. It's complicated for JPG
. Note that byte order in PNG is big-endian(255
- 000000FF
) and in GIF is little-endian(255
- FF00
). Here is code:
Imports System
Imports System.Net
Imports System.IO
Imports System.Text
Imports System.Threading
Imports Microsoft.VisualBasic
Public Class Form1
Private Sub GetImageDimensions() Handles Button1.Click
HTTPWebRequest_GetResponse.Main("http://www.example.com/image.png") 'without slash at end
Do
If HTTPWebRequest_GetResponse.done = True Then
Dim width As Integer = HTTPWebRequest_GetResponse.width
Dim height As Integer = HTTPWebRequest_GetResponse.height
Exit Do
End If
If HTTPWebRequest_GetResponse.exception Then
Exit Do 'prevents inifinite loop if exception occured
End If
Loop
End Sub
End Class
Public Class RequestState
' This class stores the State of the request.
Public requestData As StringBuilder
Public BufferRead() As Byte
Public request As HttpWebRequest
Public response As HttpWebResponse
Public streamResponse As Stream
Public Sub New()
requestData = New StringBuilder("")
request = Nothing
streamResponse = Nothing
End Sub 'New
End Class 'RequestState
Class HTTPWebRequest_GetResponse
Private BUFFER_SIZE As Integer = 1024
Public Shared response As String
Public Shared done As Boolean = False
Public Shared length As Long = 1
Public Shared progress As Integer
Public Shared myHttpWebRequest As HttpWebRequest
Public Shared myRequestState As New RequestState
Public Shared status As String
Private Shared body As Boolean = False
Public Shared responseStream As Stream
Private Shared offset As Integer
Private Shared bytestoread As Integer
Public Shared width As Integer
Public Shared height As Integer
Private Shared imageType As String
Public Shared exception As Boolean = False
Shared Sub Main(url As String)
done = False
exception = False
Try
If url.Substring(url.Length - 4) = ".png" Then
myRequestState.BufferRead = New Byte(23) {}
offset = 16
bytestoread = 24
imageType = "png"
ElseIf url.Substring(url.Length - 4) = ".gif" Then
myRequestState.BufferRead = New Byte(9) {}
offset = 6
bytestoread = 10
imageType = "gif"
Else
Throw New NotSupportedException("You can only use this with PNG or GIF images.")
End If
' Create a HttpWebrequest object to the desired URL.
myHttpWebRequest = WebRequest.Create(url)
' Create an instance of the RequestState and assign the previous myHttpWebRequest
' object to its request field.
myRequestState.request = myHttpWebRequest
' Start the asynchronous request.
Dim result As IAsyncResult = CType(myHttpWebRequest.BeginGetResponse(New AsyncCallback(AddressOf RespCallback), myRequestState), IAsyncResult)
Catch e As WebException
exception = True
Debug.WriteLine(ControlChars.Lf + "Main Exception raised!")
Debug.WriteLine(ControlChars.Lf + "Message: " + e.Message)
Debug.WriteLine(ControlChars.Lf + "Status: " + e.Status)
Catch e As Exception
exception = True
Debug.WriteLine(ControlChars.Lf + "Main Exception raised!")
Debug.WriteLine("Source : " + e.Source)
Debug.WriteLine("Message : " + e.Message)
End Try
End Sub 'Main
Private Shared Sub RespCallback(asynchronousResult As IAsyncResult)
Try
Dim myHttpWebRequest As HttpWebRequest = myRequestState.request
myRequestState.response = CType(myHttpWebRequest.EndGetResponse(asynchronousResult), HttpWebResponse)
' Read the response into a Stream object.
Dim responseStream As Stream = myRequestState.response.GetResponseStream()
myRequestState.streamResponse = responseStream
' Begin the Reading of the contents of the HTML page.
responseStream.Read(myRequestState.BufferRead, 0, bytestoread)
If BitConverter.IsLittleEndian Then
If imageType = "png" Then
height = BitConverter.ToInt32(myRequestState.BufferRead.Skip(offset).Reverse.Take(4).ToArray, 0)
width = BitConverter.ToInt32(myRequestState.BufferRead.Skip(offset).Reverse.Skip(4).Take(4).ToArray, 0)
Else
width = BitConverter.ToInt16(myRequestState.BufferRead.Skip(offset).Skip(6).Take(2).ToArray, 0)
height = BitConverter.ToInt16(myRequestState.BufferRead.Skip(offset).Skip(8).Take(2).ToArray, 0)
End If
Else
If imageType = "png" Then
width = BitConverter.ToInt32(myRequestState.BufferRead.Skip(offset).Skip(16).Take(4).ToArray, 0)
height = BitConverter.ToInt32(myRequestState.BufferRead.Skip(offset).Skip(20).Take(4).ToArray, 0)
Else
height = BitConverter.ToInt16(myRequestState.BufferRead.Skip(offset).Reverse.Take(2).ToArray, 0)
width = BitConverter.ToInt16(myRequestState.BufferRead.Skip(offset).Reverse.Skip(2).Take(2).ToArray, 0)
End If
End If
done = True
Return
Catch e As WebException
exception = True
Debug.WriteLine(ControlChars.Lf + "RespCallback Exception raised!")
Debug.WriteLine(ControlChars.Lf + "Message: " + e.Message)
Debug.WriteLine(ControlChars.Lf + "Status: " + e.Status)
Catch ex As Exception
exception = True
Debug.WriteLine(ControlChars.Lf + "RespCallback Exception raised!")
Debug.WriteLine(ex.ToString)
End Try
End Sub 'RespCallback
End Class
Code is large, but I think this is only to download only enough bytes.
Sources: https://en.wikipedia.org/wiki/Gif#Example_GIF_file https://en.wikipedia.org/wiki/Portable_Network_Graphics#Technical_details http://www.libpng.org/pub/png/spec/1.2/PNG-Chunks.html#C.IHDR
Upvotes: 5
Reputation: 2477
I don't think this is possible. Thing is...before any information can be retrieved from a certain URL or file or picture from the internet, it has to be downloaded first. It's the reason why Windows has the temp folder. Everything is stored inside the temp folder including the scenario where you're just browsing the internet. So my suggestion would be to do the same thing, download the picture first and save it somewhere and retrieve the information you want, then you can delete the file after if you don't want it anymore.
Upvotes: 0