Full disclosure: I have no formal training in programming, but have dabbled for many years.
I'm making a windows application for use in education/medical imaging. One of the things I would like it to do is to enable the user to scroll through a CT-scan, that is an imageset consisting of 100+ images. (I have captured the CT-scan in compressed .jpegs to conserve memory, so no need to worry about the dicom-format) I have a working solution that uses a vertical scroll bar to allow the user to select which slice of the CT-scan to observe in a picturebox. Images are named simply by numbers, ex. 1.jpeg, 2.jpeg...110.jpeg.
vsbCT = vertical scroll bar
pbxCTScan = Picturebox
Private Sub VsbCT_ValueChanged(sender As Object, e As EventArgs) Handles vsbCT.ValueChanged
Dim CTScanFileName as String
CTScanFileName = "D:\CT_Images\" & CStr(vsbCT.Value) & ".jpeg"
pbxCTScan.Image = Image.FromFile(CTScanFileName)
End Sub
This works pretty nicely as intended, at least initially. However, during testing in the visual studio environment, cycling through many images quickly seems to induce the program to crash. I don't know the cause of the crash, but since it works as intended initially and crashes as a function of how many images I view and how fast I scroll I wonder if there is an issue with memory in some form.
The question is as follows: Is this the most efficient way of accomplishing this task? I have considered entering all images in an array or a list and display them from there, but that would consume 60Mb of memory and seems less elegant than to read it from disk.
Any help will be much appreciated!
best regards
dr_glacier
I will address your problem of the application eventually crashing. The request for a most efficient way is topic of opinion and is thus off-topic for SO and would likely cause your question to be closed.
You are creating a new Image every time VsbCT_ValueChanged
executes. However, you are never calling the Dispose method on the old image. Theoretically, the garbage collector will clean this up, but the majority of the memory consumed by an Image is unmanaged and hence there is little likelihood that memory pressure will trigger a collection. There is also the issue of consumed GDI handles that are limited resource. This is why it is recommended that your code calls Dispose on disposable objects as soon as they are no longer needed so that the consumed resource are released.
On way of dealing with this is to use an extension method.
Public Module Utilities
<Extension()>
Public Sub SwapImage(pb As PictureBox, newImage As Image)
If pb.Image IsNot Nothing Then
pb.Image.Dispose()
End If
pb.Image = newImage
End Sub
End Module
Then this statement:
pbxCTScan.Image = Image.FromFile(CTScanFileName)
would be replaced with:
pbxCTScan.SwapImage(Image.FromFile(CTScanFileName))