Can I verify a file exists before I LoadImage()?

BlitzMax Forums/BlitzMax Beginners Area/Can I verify a file exists before I LoadImage()?

WarpZone(Posted 2006) [#1]
My game has a different background image for each stage. So far, this is the simplest way I can think of to load it:

BackgroundImage = LoadImage("graphics\stage"+Level+".png") 


It works very nicely, as long as the image it's searching for exists. I don't like the way it fails, though, if the file doesn't exist. (Unhandled Memory Exception Error. Ewwww!)

Is there any way I can check to ensure the png file exists before I try to load it? Perhaps using stage1.png as a handy default image, if the correct png file can not be found? It's not like I plan on releasing the game without as many images as there are stages... I'd just really feel a LOT more comfortable with a default image behavior, as opposed to an abrupt crash.


Mystik(Posted 2006) [#2]
Try something like this to check the file exists before you try to load it:-

local sFileName:string="graphics\stage"+Level+".png"

  if filetype(sFileName)=1 then
     BackgroundImage = LoadImage(sFileName)
  else
     BackgroundImage = LoadImage("stage1.png")
  endif 


or you could just do this, which will cover you if the file exists but does not load correctly:-

local sFileName:string="graphics\stage"+Level+".png"

  BackgroundImage = LoadImage(sFileName)
  
  if not BackgroundImage then
     BackgroundImage = LoadImage("stage1.png")
  endif 


Steve.


sswift(Posted 2006) [#3]
' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' These functions override the regular image loading functions so that we can display an error when an image is missing. 
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function LoadImage:TImage(Url:Object, Flags%=-1)
	
		Local Image:TImage
				
		Image = Brl.Max2D.LoadImage(Url, Flags)
		If Image = Null Then RuntimeError("The following image failed to load: ''" + String(Url) + "''.  Please reinstall the game.")
		
		' Buffer image in video ram.
			DrawImage Image, App.Width, App.Height
		
		LoadScreen.Update(Url)
		
		Return Image
		
	End Function
	

	Function LoadAnimImage:TImage(Url:Object, Cell_Width%, Cell_Height%, First_Cell%, Cell_Count%, Flags%=-1)
	
		Local Image:TImage
		Local Frame%

		Image = Brl.Max2D.LoadAnimImage(Url, Cell_Width, Cell_Height, First_Cell, Cell_Count, Flags)
		If Image = Null Then RuntimeError("The following image failed to load: ''" + String(Url) + "''.  Please reinstall the game.")
		
		' Buffer image in video ram.
			For Frame = First_Cell To First_Cell+(Cell_Count-1)
				DrawImage Image, App.Width, App.Height, Frame
			Next  
		
		LoadScreen.Update(Url)
		
		Return Image
		
	End Function
		

' -----------------------------------------------------------------------------------------------------------------------------------------------------------
' This function overrides the standard RuntimeError function which does not work properly.  Assert also does not work.
' -----------------------------------------------------------------------------------------------------------------------------------------------------------

	Function RuntimeError(Error$)
		EndGraphics
		Notify(Error$, True)
		End
	End Function



WarpZone(Posted 2006) [#4]
Mystik, that was exactly what I was looking for, thanks. :D

sswift, that's amazing! :D I'll come back to your code later if I feel like adding runtime errors to Blitz's internal functions.


WarpZone(Posted 2006) [#5]
Woot. Wrapped it all up in a nice clean function I can call from anywhere within my program with just one line. :)

'This code is public domain, yada yada yada.

'Tries to load an image at runtime, uses a default image if none exists.
'Note: if default image does not exist, the app still crashes!
'This was not meant as a crashfix, but as a placeholder for missing art assets during game development!

Function dynamicLoadImage:TImage(prefix:String="", n:Int=0,suffix:String="")
  Local image:TImage
    ' Load in the required Images...
    'Ensure backgroundImage exists before loading.
    Local sFileName:String=prefix+n+suffix 
    Print sFileName
    If FileType(sFileName)=1 Then
      image = LoadImage(sFileName)
    Else
      image = LoadImage("graphics\null.png")
    EndIf 
    Return image
End Function


'Example of usage
Local BackgroundImage:TImage
BackgroundImage = dynamicLoadImage("graphics\stage", Level,".png")

Think this is worth adding to the code archive? It certianly was exactly what I was looking for. :)


Byteemoz(Posted 2006) [#6]
Maybe this is a little cleaner...
' Still public domain...
Function dynamicLoadImage:TImage(prefix:String="", n:Int=0,suffix:String="")
	' Attempt to load image
	Local image:TImage = LoadImage(prefix+n+suffix)
	' Failed? - Load default image.
	If Not image Then image = LoadImage("graphics\null.png")
	Return image
End Function

'Example of usage (edited)
BackgroundImage = dynamicLoadImage("graphics\stage" , Level , ".png")
-- Byteemoz


WarpZone(Posted 2006) [#7]
Hmmm... Will that work, Byteemoz?

I mean, the whole reason I wanted to check that the file exists FIRST is because loading a file that doesn't exist seemed to crash the game.

Anyway, I can tell you didn't run your code because your function is written to accept 3 variables, and your call to the function only uses one long string. :P

(I had the same idea, though, after I posted. :P )

Here's what I've got currently:

Function dynamicLoadImage:TImage(imageString:String)
  Local image:TImage
  If FileType(imageString)=1 Then
    image = LoadImage(imageString)
  Else
    image = LoadImage("graphics\null.png")
  EndIf 
  Return image
End Function

Local BackgroundImage:TImage
BackgroundImage = dynamicLoadImage("graphics\stage" + Level + ".png")


I guess I'll try it your way and see if it works. It does seem more direct. I'm just worried about causing another Unhandled Memory Exception!


Byteemoz(Posted 2006) [#8]
Sorry ... my fault: I rewrote the Function using just one parameter and changed it later to match your previous example ...
Loading a non existing image just returns Null - trying to _draw_ a non existing image crashes the game.
Actually both functions do the same - the only difference is that one time LoadImage checks if the file exists and the other time we do... So it's more a matter of style/aesthetics than an actual programming problem.
-- Byteemoz


ImaginaryHuman(Posted 2006) [#9]
What about:

Trap
BackgroundImage = LoadImage("graphics\stage"+Level+".png") 
Catch E$
print "File access error"
End Trap


Otherwise I usually try ReadFile() and if it gives Null then the file doesn't exist.


Byteemoz(Posted 2006) [#10]
LoadImage doesn't throw an exception when it encounters a missing or invalid file. (And I think it's "Try" not "Trap")