smithvoice.com
 Y'herd thisun? 

“'Everyone wants to eat like an American on this globe,' said Daniel Basse of AgResource, a Chicago consultancy. 'But if they do, we're going to need another two or three globes to grow it all.'”

from As world's appetite soars, so do food bills by David Streitfeld

Your own image control and App part 28

TaggedCoding, VB, Imaging

Originally published December 2002 on DoItIn.net using VB7.0/2002. Updated for VB7.1 February 2005

Links for compiled demo versions, all required resources and source code are included at the end of this article.

Plus, get the complete eBook in Adobe Acrobat 7 format ... all here.


 

28) Dealing with that last exception

You might think that the OutofMemoryException is a problem with our code way back in the beginning of the svImageControl, where we did the P/Invoke to get the display color depth then lowballed maximums with those magic numbers, but it's not. All of that previous code was to avoid hitting the maxsize limit of a picturebox control, if we didn't do that we got a .Net fatal exception when trying to make the picturebox control too big. What we're hitting now isn't a fatal unhandleable exception, it's a system memory problem during the GDI+ creation of memory bitmaps.

The reason there's no protection is that the limits are moving targets. A machine with lots of RAM and a huge swap file will handle bigger images than a less well endowed box. That being said, you'd figure that looking to the machine's memory level and comparing it to the images dimensions multiplied by the pixel depth would let you check up front if a file could be loaded, but there's a catch in that idea.

Getting the machine memory can't be done directly with the current .Net Framework, but its easy enough with the VBClassic Win32 function:

 

Public Structure MEMORYSTATUS
Dim dwLength As Integer
Dim dwMemoryLoad As Integer
Dim dwTotalPhys As Integer
Dim dwAvailPhys As Integer
Dim dwTotalPageFile As Integer
Dim dwAvailPageFile As Integer
Dim dwTotalVirtual As Integer
Dim dwAvailVirtual As Integer
 End Structure
 
 Public Declare Sub GlobalMemoryStatus Lib "kernel32" _
(ByRef lpBuffer As MEMORYSTATUS)
 
Private Sub butMemory_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles butMemory.Click
 
Dim memInfo As New MEMORYSTATUS
GlobalMemoryStatus(memInfo) 
 
TextBox1.Text = "Total memory bytes: " & _
Format(memInfo.dwTotalPhys, "#,###") & _
vbCrLf & _
"Available memory bytes: " & Format(memInfo.dwAvailPhys, "#,###") & _
vbCrLf & vbCrLf & _
"Total Vmemory bytes: " & Format(memInfo.dwTotalVirtual, "#,###") & _
vbCrLf & _
"Available Vmemory bytes: " & Format(memInfo.dwAvailVirtual, "#,###")
 
End Sub

 

Here's the problem: What are you going to compare the available memory to? GDI+ has a caveat, it can't tell you an image size and color depth until an Image object is created so if Image.FromFile fails it's no help to know the available memory on a machine. Doh! Catch22.

If you're willing to put in the effort you may want to pick apart the file headers to get the values before passing the file to GDI+. Most header specifications are available in books or on the web so it's just a matter of interpreting the bits in the svImageEditor LoadImage(file) routine. That work might pay off in a few cases. In my experience however, doing the code for all of the standard image types isn't really worth it just to tell the users that an image can't be loaded; we've already got the message being passed to them via the OutOfMemory exception.

 

How come other apps can show some of these massive images? As I understand it from talking to C+ imaging devs, it's because a retail imaging tool developer will always do low level checks in order to open more filetypes than GDI+ understands, and they have the ability to do segmented loading of image files.

If a source image is too big to open fully they can instead grab small areas in blocks and read/display the blocks on demand as they're needed in the viewport or take each block one at a time, create a low resolution version then stitch these lighter blocks together for a displayable full image. Zooms in an out go back to the well to grab new blocks at higher or lower resolution. Neat huh? Smoke and Mirrors everywhere :)

By the way, even with these tricks "real apps" still will find images that are too big to load. PaintShop Pro, just like our app, can be forced to make images that are too big for it to re-open.

That covers the memory problem with loads, what about saves? If we only allow saving at limits that we can display then logic says we could pre-evaluate the specified sizes against the available memory. Again, you can shave off a few exceptions but not all of them because the limit keeps changing as things happen on the machine; services kick in, the user checks their email right after pressing the save button and on and on. OutOfMemory is nearly impossible to completely avoid under all situations without severely lowballing.

Bottom line: In our control code we stopped the .Net fatal exception, the one that would crash both the control and its host app... that's better than even Visual Studio does when you try to use the Size properties of controls. Trap for the exception and, like Microsoft's VB/VS IDE developers have for many years, take a chance that the only people who will hit it are testers using completely unrealistic values.

Next: Offer more with menus

Robert Smith
Kirkland, WA


added to smithvoice march 2005


jump to:

  • 1) The spec
  • 2) Setting up the workspace
  • 3) Feature 1: Loading an image
  • 4) Custom Exceptions
  • 5) "Fax images" and Multipage TIFFs
  • 6) Custom events
  • 7) Selecting specific fax pages
  • 8) Feature 2: Rotating image displays
  • 9) The most useful tool in GDI+: DrawImage
  • 10) Feature 3: Zooming
  • 11) Handling the unhandleable exception
  • 12) Fixing the squish
  • 13) Zooming to fit the control
  • 14) You're already beating the Pros
  • 15) Feature 4: Cropping
  • 16) Bonus Feature: StickyMouse
  • 17a) Final Cleanup
  • 17b) Passing the current display image
  • 18) Making the application
  • 19) Source and result viewports
  • 20) A better toolbar
  • 21) Hooking the toolbar to the project
  • 22) Adding ImageEditors
  • 23) The toolbar ZoomCombo
  • 24) The final solution
  • 25) Saving to image files
  • 26) An integer-only textbox
  • 27) Passing save options between forms
  • 28) Dealing with that last exception
  • 29) Offer more options with menus
  • 30 The downloads and ebook


  • home     who is smith    contact smith     rss feed π
    Since 1997 a place for my stuff, and it if helps you too then all the better smithvoice.com