Thumbnails in VB.NET

ss7thirty

Well-known member
Joined
Jun 14, 2005
Messages
455
Location
New Jersey, US
Programming Experience
5-10
I have an application that will eventually be implemented into a much larger application. I will however only ask for help and ideas on how to create fast thumbnails in VB.NET 2005. I have a custom container control that is a flow layout panel. There is a status bar with buttons and a context menu that allows you to run certain functions on the thumbnails custom control that are loaded into the flow layout panel (FLP). These functions include rotating the image, deleting it, despeckle, deshade, and other various imaging functions. The thumbnails are currently custom controls also. There are 5 buttons that allow you to shift the position and rename, rotate and save, and drag drop to move the position and to rename of it inside the container. The images are loaded onto a picture box. Images will always either be in TIF, JPEG, and rarely PDF format. We are currently caching the files to a C:\Thumbs\ folder and it runs quickly after running it once. However, we are already running low on network space and do not want to have wait when loading the images even the first time if we can. If there are any questions just ask. I am just looking for a faster ways to create/display/manipulate thumbnails in VB.NET, I am open to any suggestions and look forward to hearing what some of you may have to offer.
:cool:

I currently have all of the functions working to manipulate the images once they are on the picture box. It is a matter of finding the best way to display thumbs without taking up too much disk space.
 
Re:

I am now on my home PC and hopefully these questions can be answered by tomorrow, but if not its ok any help for free is very greatfully appreciated. Correct me if I am wrong but the GetThumbnailImage() method is new to 2005, right?


One quick question now that I have just read the through the MSDN library I am having trouble understanding the GetThumbnailImageabort I have no idea what this is doing and have no idea how to get that to work as a parameter I have everything else in there. here is the code. I wrote up a little vb 2003 program with just pictureboxes and a button and a folder c:\test with 5 jpegs in it. One other problem that I am having is that I am only on the academic version of 2003 on this PC tonight so I cant actually run the stuff with system.drawing.image or that is my best guess as to why it wont let me. However, the most important is learning about the getThumbnailImageabort and what is actually going on there because the MSDN explanation looked foreign to me.



CODE:


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim strPath As String = ""
Doagain:
Do Until System.IO.Directory.Exists(strPath)
strPath = InputBox("Enter a valid path", "Path", "C:\TEST")
Loop

Dim dir As New System.IO.DirectoryInfo(strPath)
Dim fis() As System.IO.FileInfo = dir.GetFiles

If fis.Length = 0 Then
'send up to get new path
MsgBox("Please enter a path that has files in it")
GoTo Doagain
End If

Dim blHasJpegs As Boolean = False
For Each fi As System.IO.FileInfo In fis
If fi.Extension.ToUpper = ".JPG" Then
blHasJpegs = True
End If
Next

If blHasJpegs= 0 Then
'send up to get new path
MsgBox("Please enter a path that contains jpg files")
GoTo Doagain
End If

For Each fi As System.IO.FileInfo In fis
If fi.Extension.ToUpper = ".JPG" Then
Dim img As New Image
For Each ctl As Control In Me.Controls
If TypeOf ctl Is PictureBox Then
Dim pb As PictureBox = DirectCast(ctl, PictureBox)
'if pb.image is nothing then
'pb.Image = img.GetThumbnailImage(pb.Width - 5, pb.Height - 5, Image.GetThumbnailImageAbort.RemoveAll(), IntPtr.Zero)
'end if
End If
Next
End If
Next

End Sub
End Class
 
Last edited:
No this is supported in framework 1.1 and the TheGetThumbNailImageAbort is a delegate that points toa function that will prematurely cancel the get thumbnailimage method.

Image.GetthumbNailImageAbort = new Image.GetThumbNailImageAbort(addressof the sub you defiine to abort the procedure)

p.s I think you can just pass this as 'Nothing' if you don't want an abort procedure.
 
Last edited:
Good so far but not fast enough

I did not realize that we have this implemented in our application. We had it wrapped in a private function. However, unless we cache or save the images the images still take a very long time to load. Is there a faster way to create thumbnails and display them that anyone can think of or knows of?

:confused:
 
Well you say that you have a wrapper around the function that loads the thumbnail images. You could modify this to create a new thread for each image there is to retrieve and run that function on the created thread. It may take some modification of the original function but i can't think of another way to speed this up.
 
what would be the best way to implement something like that? Here is the show thumbnails function that gets the thumbnail image and then assigns it to a picture box and loads the custom thumbs control with that picture box on it and assigns all the handlers to the control. How do you think I could modify this so that I could work with multiple threads. I have never done anything like this before.



Private Sub ShowThumbnails()
Dim arrControls() As Control
ReDim arrControls(Me.Files.Length)
Dim intProgress As Integer = 0
Me.flpThumbs.Controls.Clear()
'Dim FirstPB As PictureBox
' Get Height and Width
'
Dim strFilename As String = Nothing
Dim MyImage As System.Drawing.Image = Nothing
With tsPb1
.Visible =
True
.Maximum = Me.Files.Length
.Step = 1
.Value = 1
End With
intProgress = 1
For Each strFilename In Me.Files
Dim ThumbImage As System.Drawing.Image = Nothing
'use this object
Dim img As System.Drawing.Image = Nothing
'Dim strThumbFilename As String = "c:\thumbs\" & strFilename.Substring(3)
'Dim strThumbFolder As String = strThumbFilename.Substring(0, strThumbFilename.LastIndexOf("\"))
'If System.IO.File.Exists(strThumbFilename) Then
' ThumbImage = New System.Drawing.Bitmap(strThumbFilename)
'Else
Try
MyImage = New System.Drawing.Bitmap(strFilename)
Catch ex As Exception
MsgBox(
"There was a problem loading image " & strFilename)
Exit Sub
End Try

ThumbImage = Me.GetThumbNail(MyImage)
'Try
' If Not System.IO.Directory.Exists(strThumbFolder) Then
' System.IO.Directory.CreateDirectory(strThumbFolder)
' End If
'Catch ex As Exception
'End Try
'here is the code that actually saved the thumbs to the c:\thumbs directory
'
'ThumbImage.Save(strThumbFilename, System.Drawing.Imaging.ImageFormat.Tiff)
'SaveAsCCIT(ThumbImage, strThumbFilename)
'
'
Me.tssStatus.Text = "Loading " & intProgress & " of " & Me.Files.Length
tsPb1.PerformStep()
Me.flpThumbs.SuspendLayout()
Dim thumbCtl As New ThumbControl(Me._ThumbnailSize, strFilename)
With thumbCtl
.IsTitleVisible =
True
.Title = strFilename.Substring(strFilename.LastIndexOf("\") + 1)
.pb.Image = ThumbImage
.Size =
Me._ThumbnailSize
AddHandler .ShiftPosition, AddressOf Me.ThumbControl_ShiftPosition
AddHandler .refreshFileName, AddressOf Me.ThumbnailsControl_MouseMove
AddHandler .DragDrop, AddressOf Me.ThumbnailsControl_DragDrop
'AddHandler .ShowContextMenu, AddressOf Me.ThumbsRightClickHandler
AddHandler .SelectedChanged, AddressOf Me.SelectedChanged
AddHandler .MouseOverChanged, AddressOf Me.mouseOverChanged
End With
Me.flpThumbs.ResumeLayout()

arrControls(intProgress - 1) = thumbCtl
'old way...prob slower
'
'Me.flpThumbs.Controls.Add(thumbCtl)
intProgress += 1
Application.DoEvents()
6:
Next
With flpThumbs
.SuspendLayout()
.Controls.AddRange(arrControls)
.ResumeLayout()
End With
Me.tsPb1.Visible = False

Me.tssStatus.Text = intProgress & " of " & Me.Files.Length
End Sub
 
That would take a bit of time. Check out Threading In VB.Net as MSDN. The basic model would go.

1.Determine how many images there are to load
2.BreakUp that sub into smaller parts, so that you only call the rountine to actually load the image on the separate threads, you can do the rest later.

This will probably take quite some time though, and a bit of a re-write.
 
Thanks

:D
Thanks a lot for your help your ideas about the threads were wonderful. I had a stopwatch timing how long it took to load images and it took 13000 milliseconds to do it without threading for about 100 TIFFs and now it is taking about 2500-3000 and it is even faster with JPEGs
 
Doing work in a background thread take equal time as normal synchronous operation, it's just that you don't have to wait for it while for instance displaying form. I guess one could speak of threading as a means of 'caching time'.. :) Good suggestion vis781 !
 
Back
Top