Just click the button, select any folder with pictures in it and watch. It's a smooth running slide show that leaves your main form to get on with its own business. It works by using two extra forms to show alternate images, and changing the opacity of the top one to do cross fading. Using extra forms maybe sounds a bit clunky, but making them into Owned forms takes away all the nastiness.
To set it up, make a form and give it a button, a panel and a trackbar. If I haven't forgotten anything, all the non-default properties and other controls are set in the code. Otherwise, just copy the picture below.
There's just over 100 lines of code, and half of those are layout stuff. The only purpose of the panel is to mark the position for the two Owned forms. Their bounds stay the same as those of the panel when you move or resize the form. At the moment the program reads JPG, PNG and BMP files but you could easily add GIFs too (see the code to see how it's done).
I gave the main form a gradient background to make it look a bit more interesting when there's no picture. Apart from that, the design is nothing fancy. I hope you like it and can use some of the ideas in it. Criticism is also welcome. (Is using more than 1 form really evil?)
You seem to be one of the more efficient users of LockBits, couldn't you use that instead? There's this to average colors with weighting (I did write it on the spur of the moment, so I couldn't make it to accept Integers and I'm not sure if it's 100% correct. Sorry!):
Code:
Private Function CombineColors(ByVal color1 As Color,ByVal color2 As Color,ByVal weighting As Single) As Color 'Weighting is from 0.0 (all color1) to 1.0 (all color2).
Dim c1 As Single = 1.0! - weighting
Dim c2 As Single = weighting
Dim color1ret As Color = Color.FromArgb(255,CInt(Math.Round(color1.R * c1)),CInt(Math.Round(color1.G * c1)),CInt(Math.Round(color1.B * c1)))
Dim color2ret As Color = Color.FromArgb(255,CInt(Math.Round(color2.R * c1)),CInt(Math.Round(color2.G * c1)),CInt(Math.Round(color2.B * c1)))
Dim colorret As Color = Color.FromArgb(255,color1ret.R+color2ret.R,color1ret.G+color2ret.G,color1ret.B+color2ret.B)
Return colorret
End Function
I didn't post any settings for the TrackBar, but I suggest the following which could be done in the Designer or in Form1.Load
Code:
'Trackbar
With TrackBar1
.Orientation = Orientation.Vertical
.Minimum = 1
.Maximum = 200
.Value = 50
.TickFrequency = 10
End With
Originally Posted by minitech
You seem to be one of the more efficient users of LockBits, couldn't you use that instead? There's this to average colors with weighting (I did write it on the spur of the moment, so I couldn't make it to accept Integers and I'm not sure if it's 100% correct. Sorry!):
Code:
Private Function CombineColors(ByVal color1 As Color,ByVal color2 As Color,ByVal weighting As Single) As Color 'Weighting is from 0.0 (all color1) to 1.0 (all color2).
Dim c1 As Single = 1.0! - weighting
Dim c2 As Single = weighting
Dim color1ret As Color = Color.FromArgb(255,CInt(Math.Round(color1.R * c1)),CInt(Math.Round(color1.G * c1)),CInt(Math.Round(color1.B * c1)))
Dim color2ret As Color = Color.FromArgb(255,CInt(Math.Round(color2.R * c1)),CInt(Math.Round(color2.G * c1)),CInt(Math.Round(color2.B * c1)))
Dim colorret As Color = Color.FromArgb(255,color1ret.R+color2ret.R,color1ret.G+color2ret.G,color1ret.B+color2ret.B)
Return colorret
End Function
Hi minitech,
The smooth operation of the slide show depends on two things:
1. The high efficiency of PictureBox.Load. It seems to be capable of reading and scaling very large images much faster than anything you could do in GDI+.
2. Form Opacity is done in the graphics hardware. I don't know the details, but in theory the program only has to send 1 byte to change the opacity. This makes it easy to do the fade in 50 steps in e.g. 0.5 seconds without placing any measurable burden on the main form.
It would be possible to use a LockBits method instead of form opacity. LockBits is vastly faster than Bitmap.Get/SetPixel but it still has a cost. It would mean reading the bitmap with Image.FromFile (slower than PictureBox.Load), scaling the image to fit the display in GDI+, and then processing every pixel of the scaled image together with the corresponding pixel of the previous image, using a formula such as the one you have suggested. It might work if the images aren't too large, but it could keep the processor tied up while the slide show is running.
By the way, I didn't know the above technical points in advance. I made the program as a quick demo to answer someone's question on the VB.Net forum and was surprised at how well it worked. It took a while to figure out why!
Originally Posted by minitech
I sure think it is! But that doesn't matter.
I don't make any money on people using Forms . But it surprises me how often using an extra form can resolve traditionally insoluble graphics problems. As far as I am concerned, a Form is just another Windows.Forms.Control. The basic code is already in the framework, and an empty form doesn't consume any more memory at runtime than a PictureBox, a Panel or a Button. Obviously, you could load it down with lots of child controls or scaled image(s), but that applies to other controls too. I admit that there are some extra things to tidy up when you use a form as a control:
1. Make sure about the ownership (e.g. use OwnedForm.Show(Me))
2. ShowInTaskbar=False
3. Possibly, inherit the form and set its CreateParams.ExStyle to WM_ToolWindow to keep it out of Alt-Tab.
Hi boop boops, thanks for your quick reply on my post. um ive had a look at this, and it does the job basically, tho the code is a little on the complex side for me tho. what im acctually trying to achieve is a slide show using a picutrebox which loads images from a predefined location and a prdefined time frame say 3 seconds per fade. i.e like a screen saver without you having to select the folder everytime. thanks a lot in advance
Too complicated? Well, I suppose I did make it a bit too complicated. Here's a really simple screen-saver with cross fading in only 30 lines of code, based on the same principles.
1. Start a Forms project (Form1). In the Designer, set your form's FormBorderStyle to None, Opacity to 0% and WindowState to Maximized.
2. Add a Timer (Timer1) to the form and set its Interval to 3000.
3. Add another Form to the project (from the Project menu/Add Windows Form...). Set its Name to DisplayForm, FormBorderStyle to None, KeyPreview to True, Opacity to 0%, ShowInTaskbar to False and WindowState to Maximize.
4. Add a PictureBox to DisplayForm. Set its Dock property to Fill and its SizeMode property to Center (or Stretch or Zoom, depending on the images you are going to use).
5. Add the code below to Form1. Obviously, you can change the name of the folder and type of file, e.g. GetFiles("D:\Images", "*.png").
Code:
Private imageFiles() As String = IO.Directory.GetFiles _
(My.Computer.FileSystem.SpecialDirectories.MyPictures, "*.jpg", IO.SearchOption.AllDirectories)
Private index As Integer
Private WithEvents DisplayForm1, DisplayForm2 As New DisplayForm
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DisplayForm1.PictureBox1.Load(imageFiles(0))
DisplayForm1.Show(Me)
DisplayForm2.Show(Me)
Timer1.Start()
End Sub
Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
If DisplayForm1.Opacity > 0.5 Then
CrossFade(DisplayForm1, DisplayForm2)
Else
CrossFade(DisplayForm2, DisplayForm1)
End If
End Sub
Private Sub CrossFade(ByVal FromForm As DisplayForm, ByVal ToForm As DisplayForm)
ToForm.Select()
Do While ToForm.Opacity < 1
ToForm.Opacity += 0.01
Threading.Thread.Sleep(10)
Loop
FromForm.Opacity = 0
index = (index + 1) Mod imageFiles.Count
FromForm.PictureBox1.Load(imageFiles(index))
End Sub
Private Sub DisplayForm1_PreviewKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles DisplayForm1.PreviewKeyDown, DisplayForm2.PreviewKeyDown
Me.Close()
End Sub
Press any key to close the program (you may have to wait a few seconds).
EDIT: it looks best if you set the BackColor of the forms and PictureBox to Black. EDIT2: code improved to give better start.
BB
Last edited by boops boops; Feb 8th, 2011 at 10:36 AM.
Hi boops boops, is it possible for u to apply the same technique u av used with track bar to help me create an image sharpening form? The image should be sharpened as you move the track bar slider, up and down.