Need help identifying picture format

Hi all. How can I identify the format of a picture (jpeg, tiff, png, etc.) that a user drags onto a Canvas object? The aforementioned pictures all drag-n-drop and display perfectly on my UI - I just need to know what type of picture format it is. Thanks!

A bit of Googling gave me this website: http://www.filesignatures.net

Beatrix, thanks. But I’m hoping for something in Xojo for this functionality. I’ve looked, but can’t find anything. Something like Canvas.GetPictureFormat().

The usual way is simply to look at Obj.FolderItem.Name in the DropObject event. The extension tells you which type it is. Or am I missing something here ?

You can’t rely on extensions to always be correct.

When the picture is in the Canvas, it has already been turned into Xojo’s internal format. It is too late.

See http://documentation.xojo.com/index.php/Picture.IsImportFormatSupported if you want to test the file for supported formats.

Alex, if you e-mail me at harriew at frontiernet dot net I can send you a little project of mine that I wrote some time ago when I needed to be able to get the dimensions of a graphics file in order to insert the proper dimensions in HTML code that a program of mine was producing. It can determine BMP, GIF, JPG, PNG, TIF, and PCT files. Typically you only need the first few bytes of the file in order to determine its type. Getting the dimensions can be a little tricker; but, once you know the type of file there are rules to follow to fetch the dimensions. In this little test project you drag a graphics file on to the window and it will tell you the type, size in bytes, and width and height of the graphic.

if it’s about file dragging, you define the file types the user can drop with Canvas.AcceptFileDrop
Due to this, in DropObject you will check for obj.FolderItemAvailable and if true, obj.FolderItem.type will contains the file type.

Several ways:
#1 Add different file types in a file type set of Xojo and then compare folderitem.type against the name of your file types.
#2 Read the first 4 bytes of the file and then compare that to a list of common magic markers.

BMP starts with BM. TIFF starts with II or MM. PNG starts with PNG. JPEG is based on blocks, but doesn’t require any block to be on front. Often you find a JFIF near the front. GIF starts with GIF and the version number.

I wrote a small program in the past to determine the image header , and displayed into a TextArea. Was just a test, a simple program, but you might find it useful, how to get the image header.

Window1 Control PushButton1:

Sub Action()
  dim f as folderitem = getOpenFolderitem("Whole File")
  Dim header as Variant
  
  if f <> nil then
    //open the folderitem as a binary file without write privileges
    //To open file with write privileges, pass true instead of false
    const writePerm = false
    
    try
      dim bs as BinaryStream = BinaryStream.Open(f, writePerm)
      //read the whole binaryStream
            
      header = bs.read(64)
      
      TextArea1.text = EncodeHex(header,true) +EndOfLine
      TextArea1.AppendText  header +EndOfLine
      TextArea1.AppendText  EndOfLine + EndOfLine+ test_jpeg(header)+EndOfLine
      TextArea1.AppendText test_png(header)+EndOfLine
      TextArea1.AppendText test_gif(header)+EndOfLine
      TextArea1.AppendText test_tiff(header)+EndOfLine
      TextArea1.AppendText test_bmp(header)+EndOfLine
      TextArea1.AppendText test_rgb(header)+EndOfLine
      TextArea1.AppendText test_xbm(header)+EndOfLine
      TextArea1.AppendText test_rast(header)+EndOfLine
      TextArea1.AppendText test_pbm(header)+EndOfLine
      TextArea1.AppendText test_pgm(header)+EndOfLine
      TextArea1.AppendText test_ppm(header)+EndOfLine
            
    catch e as IOException
      msgbox "IO Exception"
      //something went wrong when opening the file. This is where you would handle the error
      //if appropriate
    end try
  end if
End Sub

Window1.test_bmp:

Protected Function test_bmp(h as Variant) As string
  Dim mb as Memoryblock
  
  mb = str(h)
  
  if h.LeftB(2) =  "BM"  Then  //
    //msgbox encodehex(h.midb(19,4),true)
    Return "BMP"
  Else
    Return "NoGO"
  End if
End Function 

Window1.test_gif:

Protected Function test_gif(h As variant) As string 
  //GIF ('87 and '89 variants)
  
  if h.LeftB(6) =  "GIF87a"  OR  h.LeftB(6) =  "GIF89a"Then 
    Return "GIF"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_jpeg:

Protected Function test_jpeg(h as variant) As string 
  
  if h.MidB(7,4) = "JFIF"  Then
    return "JPEG"
  Elseif  h.MidB(7,4) = "Exif" Then    //"""JPEG data in Exif format"""
    Return "JPEG (Exif)"
  Else
    Return "NoGO"
  End If
End Function

Window1.test_pbm:

Protected Function test_pbm(h as Variant) As String 
  //PBM (portable bitmap)
  
  if  EncodeHex(h.midB(1,1),false) =  "50"  And (EncodeHex(h.midB(2,1),false)  = "31" OR EncodeHex(h.midB(2,1),false) = "34" )  And (EncodeHex(h.midB(3,1),false)  = "09" OR EncodeHex(h.midB(3,1),false) = "0A" OR EncodeHex(h.midB(3,1),false) = "0D" )Then  
    Return "PBM"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_pgm:

Protected Function test_pgm(h as Variant) As string 
  //PGM (portable graymap)
  
  if  EncodeHex(h.midB(1,1),false) =  "50"  And (EncodeHex(h.midB(2,1),false)  = "32" OR EncodeHex(h.midB(2,1),false) = "35" )  And (EncodeHex(h.midB(3,1),false)  = "09" OR EncodeHex(h.midB(3,1),false) = "0A" OR EncodeHex(h.midB(3,1),false) = "0D" )Then
    Return "PGM"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_png:

 Protected Function test_png(h as Variant) As string 
  if EncodeHex(h.LeftB(8), false) =  "89504E470D0A1A0A" Then   //  IF "&h89 + PNG + \\r + \
 + &h1A + \
"
    Return "PNG"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_ppm:

Protected Function test_ppm(h as Variant) As String
  //PPM (portable pixmap)
  
  if  EncodeHex(h.midB(1,1),false) =  "50"  And (EncodeHex(h.midB(2,1),false)  = "33" OR EncodeHex(h.midB(2,1),false) = "36" )  And (EncodeHex(h.midB(3,1),false)  = "09" OR EncodeHex(h.midB(3,1),false) = "0A" OR EncodeHex(h.midB(3,1),false) = "0D" )Then
    Return "PPM"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_rast:

Protected Function test_rast(h As Variant) As string 
  //Sun raster file
  
  if EncodeHex(h.LeftB(4), false) =  "59A66A95" Then   //  IF "&h59 +&hA6 + &h6A + &h95"
    Return "RAST"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_rgb:

Protected Function test_rgb(h as Variant) As String
  //"SGI image library"
  
  if EncodeHex(h.LeftB(2), false) =  "01DA" Then   //  IF "&h01 +&hDA "
    Return "RGB"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_tiff:

Protected Function test_tiff(h as Variant) As string
  if h.LeftB(2) =  "MM"  OR  h.LeftB(2) =  "II"Then  //Motorola or Intel byte order
    Return "TIFF"
  Else
    Return "NoGO"
  End if
End Function

Window1.test_xbm:

Protected Function test_xbm(h As Variant) As String 
  //X bitmap (X10 or X11)
    
  if h.LeftB(7) =  "#define"  Then  
    Return "XBM"
  Else
    Return "NoGO"
  End if
End Function

Hey Everyone,

Thanks for responding. Massimo’s approach seems to work best for me, at least for now.

If I may, here’s a VERY general question about handling pictures in a Mac app: What picture formats should the app support to ensure 99% coverage? I’m thinking jpeg, png and tiff.

[quote=150586:@Alex Sharp]Hey Everyone,

Thanks for responding. Massimo’s approach seems to work best for me, at least for now.

If I may, here’s a VERY general question about handling pictures in a Mac app: What picture formats should the app support to ensure 99% coverage? I’m thinking jpeg, png and tiff.[/quote]

If you had been to http://documentation.xojo.com/index.php/Picture.IsImportFormatSupported you would have seen that Xojo also supports BMP and Gif. Then you are sure to cover all Xojo’s possibilities.

Michael, thanks - I meant to follow the link but forgot.

On OSX and Linux there is the file command you could call in a shell. It will identify a file regardless of the extension. There’s no direct equivalent for Windows but this comes close.

Previously I mentioned a little program that I wrote to figure out graphic file types. Here is the code that that program uses. f is a property of the window and either points to the file that was dropped on the window or was chosen via an open dialog. This method determines the type of graphic. BMP, GIF, JPG, PNG, TIF and PCT. These days you can probably ignore the PCT but they do still exist.

[code] Dim fileIdent As Uint32
Dim firstFour, s As String

lblName.Text = f.Name
//Determine the kind of image file that we have and call the
// appropriate analyseXXX method to get width and height
// read first four bytes of the file passed in and check to see if it
// is one of the image types that this program will process.
bs = BinaryStream.Open(f, False)
if bs = nil then
s = “Unable to open the selected file “”” + f.name + " in the analyseGraphic method"
showAlertDialog kPgmErr, s, “Okay”, “”, “”, “a”, “”, 0
Return
end if
fileIdent = bs.readUint32 // read first four bytes from the file
firstFour = Right(“0000000” + hex(fileIdent), 8)
if left(firstFour, 4) = “424D” then // first two bytes 424D (BM) a BMP file?
analyseBMP
else
select case firstFour
case “47494638” // test if first four bytes are &h47494638 (GIF8) a GIF file
analyseGIF
case “FFD8FFE0” // test if first four bytes are &hFFD8FFE0 for a JPG file
analyseJPG
case “FFD8FFE1”
analyseJPG
case “89504E47” // test if first four bytes are &h89504E47 for a PNG file
analysePNG
case “4D4D002A” // is this one of the TIF identifiers?
analyseTIF
case “49492A00” // is this the other TIF identifier?
bs.LittleEndian = true // this TIF format has low byte first
analyseTIF
case “00000000” // does this look like a PICT file can’t find any written spec for PICT
analysePCT
else
imageKind = “?” // not a known image file
end Select
end if
bs.Close
[/code]
The analyseXXX methods that you see being called dig deeper in to the files to fetch the size, and width and height of the image.

Thanks Harrie!