Page 1 of 1

Get Image Type...

Posted: Sun Jun 10, 2007 3:03 am
by localmotion34
If you like graphics, and like fooling around with images, you may have had a problem with an images extension not matching the real type of image format it is. Some real #$%$# can change the extension just to be funny guys.

Freeimage has "Freeimage_GetFormat", so in the spirit of the up and coming PB image library, here is my smaller, yet almost bulletproof version of that function.

The FINAL aim of this is to look at the extension of the file, and compare that to what format this function detects. If both correspond, then it will return a value of #totally_OK_to_Load. if the extension doesn't match the format, i know my detection methods are near bulletproof, so it will return #probably_ok_to_load. If NOTHING pans out, then I will give the user the option of #Load_at_all_costs_because_I_want_the_darn_image_NOW, and defer to heuristic image loading routines.

PLEASE, PLEASE, PLEASE, if you can add more detections to this, PLEASE DO!!!

Code: Select all

#Image_Unknown=0 
#Image_DCX=1
#Image_GIF =2
#Image_PCX=3
#Image_JPEG=4
#Image_PNG=5
#Image_TGA=6
#Image_BMP_Win=7
#Image_BMP_OS2=8
#Image_Tiff=9 
#Image_RAS=10
#Image_Pic=11

Macro SwapL(val)
  (((val>>24) & $000000FF)|((val>>8) & $0000FF00)|((val<<8) & $00FF0000)|((val<<24) & $FF000000))
EndMacro 

Procedure GetImageType(filename.s)
  If FileSize(filename); make sure some idiot didnt send us a fake file
    file=ReadFile(#PB_Any,filename)
    If file ; OK, file is open
      
      ; let's try DCX, Magic # is FIRST long
      Magic.l=ReadLong(file) 
      If Magic =987654321
        CloseFile(file)
        ProcedureReturn #Image_DCX
      EndIf 
      
      ; Let's try GIF next.  fairly easy to spot
      FileSeek(file,0)
      gif=AllocateMemory(6)
      ReadData(file,gif,6) 
      If PeekS(gif,6)= "GIF89a" Or PeekS(gif,6)= "GIF87a"
        CloseFile(file)
        FreeMemory(gif)
        ProcedureReturn #Image_GIF
      EndIf
      FreeMemory(gif)
      
      ;Now JPEG
      FileSeek(file,0)
      byte.b=ReadByte(file)
      byte1$=Right(Hex(byte),2)
      byte.b=ReadByte(file)
      byte1$+Right(Hex(byte),2)
      FileSeek(file, Loc(file)+4)
      jfif$=""
      For a=0 To 3
        jfif$=jfif$+Chr(ReadByte(file))
      Next
      If byte1$="FFD8" And jfif$="JFIF"
        CloseFile(file)
        ProcedureReturn #Image_JPEG
      EndIf
      
      ;Now PNG
      FileSeek(file,0)
      For a=0 To 7
        byte.b=ReadByte(file)
        If a=0
          rtn.s=Right(Hex(byte),2)
          string$=string$+ rtn 
        Else
          rtn.s=RSet(Hex(byte),2,"0") 
          string$=string$+ rtn
        EndIf 
      Next
      If string$="89504E470D0A1A0A"
        CloseFile(file)
        FreeMemory(st)
        ProcedureReturn #Image_PNG 
      EndIf
      
      ;Now TGA
      FileSeek(file,Lof(file)-18)
      st=AllocateMemory(16)
      ReadData(file,gif,16) 
      If PeekS(gif,16)= "TRUEVISION-XFILE"
        CloseFile(file)
        FreeMemory(st)
        ProcedureReturn #Image_TGA
      EndIf 
      FreeMemory(st)
      
      ;PCX
      FileSeek(file,0)
      st=AllocateMemory(4)
      ReadData(file,st,4)
      ident.b=PeekB(st)
      Version.b=PeekB(st+1)
      encoding=PeekB(st+2)
      bitsPerPixel=PeekB(st+3)
      If ident=10
        If Version<=5 And encoding=1
          ProcedureReturn #Image_PCX
        EndIf
      EndIf
      FreeMemory(st)
      
      ;BMP (Windows)
      FileSeek(file,0)
      BM$=""
      For a=0 To 1
        BM$=BM$+Chr(ReadByte(file))
      Next
      FileSeek(file,14)
      Size.b=ReadByte(file)
      If BM$= "BM" And Size.b=40
        ProcedureReturn #Image_BMP_Win
      EndIf
      
      ;BMP (OS2)
      FileSeek(file,0)
      BM$=""
      For a=0 To 1
        BM$=BM$+Chr(ReadByte(file))
      Next
      FileSeek(file,14)
      Size.b=ReadByte(file)
      If BM$= "BM" And Size.b=12
        ProcedureReturn #Image_BMP_OS2
      EndIf
      
      ;TIFF
      FileSeek(file,0)
      MM$=""
      For a=0 To 1
        MM$=MM$+Chr(ReadByte(file))
      Next
      If MM$= "II" Or MM$="MM"
        ProcedureReturn #Image_Tiff
      EndIf
      
      ;RAS
      FileSeek(file,0)
      Magic.l=ReadLong(file)
      Magic1.l= SwapL(Magic)
      If Magic1 = 1504078485
        ProcedureReturn #Image_RAS
      EndIf
      
      ;uh, ok.  Let's try .PIC/Pictor PC Paint
      FileSeek(file,0)
      id.w=ReadWord(file)
      If id= $1234
        ProcedureReturn #Image_Pic 
      EndIf 
    EndIf 
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

If OpenWindow(0,0,0,470,420,"",#PB_Window_SystemMenu|#PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0)) 
  ButtonGadget(0, 10, 10,80,20,"OpenFile") 
  ImageGadget(1, 10, 50, 300,300,0,#PB_Image_Border)
  
EndIf 
Repeat 
  
  Select  WaitWindowEvent() 
    Case #PB_Event_Gadget 
      Select EventGadget() 
        Case 0
          Pattern$ ="All Supported Formats|*.nif;*.BMP;*.gif;*.JPG;*.jpeg;*.tif;*.tiff;*.pcx;*.tga;*.png;*.iff;*.wbm;*.wbmp;*.dcx;*.ras;*.pic"
          Pattern$ +"|New image Format (nif)|*.nif|BITMAP (bmp)|*.bmp|Graphics Interchange Format (gif)|*.gif|JPEG (jpg)|*.jpg;*.jpeg|TIFF (tif)|*.tif;*.tiff|Zsoft PainBrush (pcx)|*.pcx|Targa (tga)|*.tga|Portable Networks Graphic (png)|*.png|Amiga IFF (iff)|*.iff|Wireless Bitmap (wbm, wbmp)|*.wbm;*.wbmp|Pictor PC Paint (pic)|*.pic"
          Pattern$+"|Windows Metafile (wmf, emf)|*.wmf;*.emf|Multipage PCX (dcx)|*.dcx"
          filename.s = OpenFileRequester("Choose An Image File To Open","",Pattern$,0)
          If filename
            Debug GetImageType(filename)
          EndIf
      EndSelect  
    Case #PB_Event_CloseWindow
      End 
  EndSelect 
ForEver

Posted: Sun Jun 10, 2007 4:52 am
by GeoTrail
There's an error on line 71 when opening a PNG image. And sometimes when opening a JPG image it returns 0 (unknown)

Why don't you use

Code: Select all

Enumeration
  #Image_Unknown
  #Image_DCX
  #Image_GIF
  #Image_PCX
  #Image_JPEG
  #Image_PNG
  #Image_TGA
  #Image_BMP_Win
  #Image_BMP_OS2
  #Image_Tiff
  #Image_RAS
  #Image_Pic
EndEnumeration
instead?

And to be even more safe

Code: Select all

If FileSize(filename) <> -1 And FileSize(filename) <> -2 And FileSize(filename) <> 0

Posted: Sun Jun 10, 2007 2:17 pm
by AND51
:idea:

Code: Select all

If FileSize(filename) <> -1 And FileSize(filename) <> -2 And FileSize(filename) <> 0
  • Image

Code: Select all

If FileSize(filename) > 0

Posted: Sun Jun 10, 2007 8:34 pm
by GeoTrail
Hehehe yeah I thought of that after I posted it ;)