Code archives/Graphics/Retrieve image information without loading entire image
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This code retrieves width, height, number of colours and some other basic (arbitrarily decided!) information directly from image files, ie. you don't have to load the full images into Blitz first. To use: Call GetImageInfo with your image filename, test the result in case it's Null (important!), and access the width, height, colors and info fields from the ImageInfo result, eg. image:ImageInfo = GetImageInfo ("test.jpg") If image <> Null Print image.width Print image.height Print image.colors Print image.info Else Print "Couldn't get image information!" EndIf The currently supported formats are the most popular ones for Blitz usage, ie. BMP, JPEG, TGA and PNG (plus Gif). These all seem to work very well now, having been tested on around 11,500 files. In fact, the code seems to return 100% correct results as far as I can tell; if you find any results that state information couldn't be found for one of the supported images, check whether or not it really is the type of image specified by the file extension -- the chances are it isn't! NB. You can copy/paste/call the individual formats' functions directly, if you prefer, rather than GetImageInfo (), eg. GetJPEGInfo (). Just be sure to include the ImageInfo type at the top of the code. To do: More consistent colour information. Currently returns mixed results between formats, eg. an indexed palette-based image might have only 256 colours, each of which can be (eg.) a 24-bit value, so I'm returning 24-bits. I think I'll return a max colours-per-pixel and number of palette entries where applicable. If you add any other image formats (following the same conventions as the code below), please drop me an email and I'll update this code. (Please only email me if your code can be declared public domain.) | |||||
Type ImageInfo Field width:Int Field height:Int Field colors:Int Field info:String End Type Function GetBMPInfo:ImageInfo (f:String) Local image:ImageInfo = New ImageInfo If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local bmp:TStream = LittleEndianStream (ReadFile (f)) If bmp Try If ReadByte (bmp) = $42 And ReadByte (bmp) = $4D For Local loop:Int = 1 To 12 ReadByte bmp Next Local width:Int Local height:Int If ReadInt (bmp) = 40 width = ReadInt (bmp) height = ReadInt (bmp) EndIf ' Not needed... ReadByte bmp ReadByte bmp Local depth:Int = ReadShort (bmp) Local compression:Int = ReadInt (bmp) Local version:String Select compression Case 0 version = "No compression" Case 1 version = "RLE-8 compression" Case 2 version = "RLE-4 compression" Default version = "Unknown compression" End Select image.width = width image.height = height image.colors = 2 ^ depth image.info = version Else image = Null EndIf Catch ReadFail:Object DebugLog "Read error in " + f image = Null End Try CloseFile bmp Else image = Null EndIf Return image End Function Function GetGIFInfo:ImageInfo (f:String) Local image:ImageInfo = New ImageInfo If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf ' Read the file... Local gif:TStream = LittleEndianStream (ReadFile (f)) If gif Try ' First 3 bytes must be "GIF"... Local g:String Local loop:Int ' For byte-seek loops... For loop = 0 To 2 g = g + Chr (ReadByte (gif)) Next If g = "GIF" Print "Got GIF???" ' Next 3 bytes contain version (87a or 89a)... Local version:String = "GIF version " For loop = 3 To 5 version = version + Chr (ReadByte (gif)) Next ' Dimensions... Local width:Int = ReadShort (gif) Local height:Int = ReadShort (gif) ' Depth is encoded in first 3 bits of this byte! Local packed:Int = ReadByte (gif) Local depth:Int = (packed & 1) + (packed & 1 Shl 1) + (packed & 1 Shl 2) + 1 Local colors:Int = 2 ^ depth image.width = width image.height = height image.colors = colors image.info = version:String Else image = Null EndIf Catch ReadFail:Object DebugLog "Read error in " + f image = Null End Try CloseFile gif Else image = Null EndIf Return image End Function Function GetJPEGInfo:ImageInfo (f:String) Global remote:Int = False ' Used for online images If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) remote = True EndIf Local image:ImageInfo = New ImageInfo Local jpeg:TStream = BigEndianStream (ReadFile (f)) If jpeg Try ' Start of image (SOI) marker ($FFD8) -- MUST BE PRESENT! If ReadByte (jpeg) = $FF And ReadByte (jpeg) = $D8 ' ... followed by JFIF 'APP0' marker ($FFE0). In theory must be present, but reality says otherwise... ReadByte jpeg ' Should be $FF but not always true... ReadByte jpeg ' Should be $E0 but not always true... ' Start of first block... Local block_length:Int = ReadShort (jpeg) - 2 ' Less these two bytes! ' Check for JFIF identification string (generally treated as optional)... Local jfif:Int = 0 ' Have to check each byte separately as BlitzMax's 'early-out' feature may mean the ' wrong number of bytes are read if one doesn't match, eg. If ReadByte (x) And ReadByte (y)... If ReadByte (jpeg) = 74 Then jfif = jfif + 1 ' ASCII code for "J" If ReadByte (jpeg) = 70 Then jfif = jfif + 1 ' ASCII code for "F" If ReadByte (jpeg) = 73 Then jfif = jfif + 1 ' ASCII code for "I" If ReadByte (jpeg) = 70 Then jfif = jfif + 1 ' ASCII code for "F" If ReadByte (jpeg) = 0 Then jfif = jfif + 1 ' 0 If jfif = 5 Then jfif = True Else jfif = False ' Read next two bytes. If the file has a JFIF marker, this is the version string. If ' not, it's probably random bollocks... Local major:String = String (ReadByte (jpeg)) ' Major revision number Local minor:String = RSet (String (ReadByte (jpeg)), 2) ' Minor revision (padded with leading space) Local version:String If jfif ' JFIF-compliant! Yay! minor = Replace (minor, " ", "0") ' Replace space with 0! ' The above changes version from (eg.) "1.2" to "1.02", ' as in common rendering of "JFIF, version 1.02"... version = "JFIF version " + major + "." + minor Else ' Missing either APP0 marker or "JFIF" string. Boo! version = "Not a 100% JFIF-compliant JPEG file" EndIf image.info = version Local loop:Int ' For byte seek loops... ' Skip block length, minus the previous 7 reads since start of block... If remote ' Online image, read byte-by-byte... For loop = 1 To block_length - 7 ReadByte jpeg Next Else ' Local image, just stream... SeekStream jpeg, StreamPos (jpeg) + (block_length - 7) EndIf Local back_byte:Int = 0 ' See below... While Not Eof (jpeg) ' We should be at the start of a block; if not, bail out... ' DebugLog "---------------------------------------------------------------------------------------" ' DebugLog "New block at " + StreamPos (jpeg) ' DebugLog "---------------------------------------------------------------------------------------" Local checkff:Byte ' Byte to be tested for $FF (start of block)... ' See further down -- needed as we can't seek backwards with online images... If back_byte ' Byte from last time around... checkff = back_byte Else checkff = ReadByte (jpeg) EndIf If checkff = $FF back_byte = 0 ' Reset for next loop... ' Read the byte AFTER a $FF marker... Local afterff:Byte = ReadByte (jpeg) ' Some debug information, perhaps of interest... ' DebugLog "$FF" + Right (Hex (afterff), 2) ' $D8 = Start of Image (SOI) marker ' $D9 = End of Image (EOI) marker ' $ED = Photoshop data marker ' $E1 = Start of Exif data ' Grab next two bytes (length of block) before proceeding... block_length = ReadShort (jpeg) - 2 ' The 2 subtracted bytes store the length itself... If afterff => $C0 And afterff <= $C3 ' Bits per pixel... Local bpp:Int = ReadByte (jpeg) ' Height and width... Local height:Int = ReadShort (jpeg)' (ReadByte (jpeg) Shl 8) + ReadByte (jpeg) Local width:Int = ReadShort (jpeg)'(ReadByte (jpeg) Shl 8) + ReadByte (jpeg) ' Components per pixel (1 for grayscale, 3 for RGB)... Local components:Int = ReadByte (jpeg) ' Depth/total colours... Local depth:Int = bpp * components Local colors:Int = 2 ^ depth ' Fill in ImageInfo data... image.width = width image.height = height image.colors = colors ' Done! Exit Else ' Go to next block... If remote ' Online image, read byte-by-byte... For loop = 1 To block_length ReadByte jpeg Next Else ' Local image, just seek... SeekStream jpeg, StreamPos (jpeg) + block_length EndIf ' Found huge string of zeroes after jumping block_length in PS 7 JPEG! Skip... Local next_byte:Byte = 0 Repeat next_byte = ReadByte (jpeg) Until next_byte ' OK, found non-zero byte, so go back one byte and return to start of loop... back_byte = next_byte ' Store last-read byte (can't seek back with online images)... ' back_byte will be checked at start of While/Wend loop... EndIf Else ' Not at a block marker. Oops! Bail... image = Null Exit EndIf Wend Else image = Null EndIf Catch ReadFail:Object DebugLog "Read error in " + f image = Null End Try CloseFile jpeg Else image = Null EndIf Return image End Function Function GetPNGInfo:ImageInfo (f:String) If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local image:ImageInfo = New ImageInfo Local png:TStream = BigEndianStream (ReadFile (f)) If png Try ' PNG header... If ReadByte (png) = $89 And Chr (ReadByte (png)) = "P" And Chr (ReadByte (png)) = "N" And Chr (ReadByte (png)) = "G" ' PNG header continued... If ReadByte (png) = 13 And ReadByte (png) = 10 And ReadByte (png) = 26 And ReadByte (png) = 10 For Local loop:Int = 1 To 4 ReadByte png Next ' IHDR chunk (always first)... If Chr (ReadByte (png)) = "I" And Chr (ReadByte (png)) = "H" And Chr (ReadByte (png)) = "D" And Chr (ReadByte (png)) = "R" Local width:Int = ReadInt (png) Local height:Int = ReadInt (png) Local depth:Int = ReadByte (png) Local colortype:Int = ReadByte (png) Local info:String Select colortype Case 0 info = "Pixels represented by grayscale values" Case 2 info = "Pixels represented by RGB values" Case 3 info = "Pixels represented by palette indices" Case 4 info = "Pixels represented by grayscale values plus alpha" Case 6 info = "Pixels represented by RGB values plus alpha" Default info = "Unknown pixel format" End Select image.width = width image.height = height image.colors = 2 ^ depth image.info = info Else image = Null EndIf Else image = Null EndIf Else image = Null EndIf Catch ReadFail:Object DebugLog "Read error in " + f image = Null End Try CloseFile png Else image = Null EndIf Return image End Function Function GetTGAInfo:ImageInfo (f$) If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local image:ImageInfo = New ImageInfo Local tga:TStream = LittleEndianStream (ReadFile (f$)) If tga Try Local idlength:Byte = ReadByte (tga) Local colormap:Byte = ReadByte (tga) Local imagetype:Byte = ReadByte (tga) Local info:String Select imagetype ' First three bits: Case 0 info = "No image data present" Case 1 info = "Uncompressed color-mapped image" Case 2 info = "Uncompressed RGB image" Case 3 info = "Uncompressed grayscale image" ' Fourth bit: Case 9 info = "RLE-compressed color-mapped image" Case 10 info = "RLE-compressed RGB image" Case 11 info = "RLE-compressed grayscale image" ' From http://www.gamers.org/dEngine/quake3/TGA.txt ... Case 32 info = "Color-mapped image (Huffman/Delta/RLE-compressed)" Case 33 info = "Color-mapped image (Huffman/Delta/RLE-compressed, 4-pass quadtree)" Default info = "Unknown image type" End Select Local colormapstart:Short = ReadShort (tga) Local colormaplength:Short = ReadShort (tga) Local colormapbpp:Byte = ReadByte (tga) Local xorigin:Short = ReadShort (tga) Local yorigin:Short = ReadShort (tga) Local width:Short = ReadShort (tga) Local height:Short = ReadShort (tga) Local depth:Byte = ReadByte (tga) If colormap depth = colormapbpp ' DebugLog "Color map start: " + colormapstart ' DebugLog "Color map length: " + colormaplength ' DebugLog "Color map bits per pixel: " + colormapbpp ' Select colormap ' Case 0 ' DebugLog "Image has no indexed palette" ' Case 1 ' DebugLog "Image has indexed palette (" + colormaplength + " entries)" ' Case colormap =>2 And colormap <= 127 ' DebugLog "Truevision-specific color map" ' Case colormap => 128 And colormap <= 255 ' DebugLog "Third-party color map" ' End Select EndIf Local desc:Byte = ReadByte (tga) Local pixelattr:Byte = desc & (Int (2 ^ 3) | Int (2 ^ 2) | Int (2 ^ 1) | Int (2 ^ 0)) Select pixelattr Case 0 info = info + ", no alpha mask" Case 1 info = info + ", with background mask" Case 8 info = info + ", with alpha mask" End Select ' 32-bit depth may or may not include an alpha mask, but RGB values are max 24-bit... If depth = 32 Then depth = 24 Local colors:Int = Int (2 ^ depth) ' NOTE: colors value is the maximum number of colours available to each ' pixel. This applies even in images with a limited number of palette ' entries, eg. a palette of 8 indexed colours may still contain 24-bit values! image.width = width image.height = height image.colors = colors image.info = info Catch ReadFail:Object DebugLog "Read error in " + f image = Null End Try CloseFile tga Else image = Null EndIf Return image End Function ' ----------------------------------------------------------------------------- ' File format tests... ' ----------------------------------------------------------------------------- Function GotBMP:Int (f:String) If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local result:Int = False Local bmp:TStream = LittleEndianStream (ReadFile (f)) If bmp Try If ReadByte (bmp) = $42 And ReadByte (bmp) = $4D For Local loop:Int = 1 To 12 ReadByte bmp Next If ReadInt (bmp) = 40 result = True EndIf EndIf Catch ReadFail:Object DebugLog "Read error in " + f End Try CloseFile bmp EndIf Return result End Function Function GotGIF:Int (f:String) If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local result:Int = False Local gif:TStream = LittleEndianStream (ReadFile (f)) If gif Try ' First 3 bytes must be "GIF"... Local g:String ' /beavis: Uh... huh huh! Local loop:Int ' For byte-seek loops... For loop = 0 To 2 g = g + Chr (ReadByte (gif)) Next If g = "GIF" ' Next 3 bytes contain version (87a or 89a)... Local version:String For loop = 3 To 5 version = version + Chr (ReadByte (gif)) Next If version = "87a" Or version$ = "89a" result = True EndIf EndIf Catch ReadFail:Object DebugLog "Read error in " + f End Try CloseFile gif EndIf Return result End Function Function GotJPEG:Int (f:String) If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local result:Int = False Local jpeg:TStream = BigEndianStream (ReadFile (f)) If jpeg Try If ReadByte (jpeg) = $FF And ReadByte (jpeg) = $D8 ReadByte jpeg ReadByte jpeg Local block_length:Int = ReadShort (jpeg) - 2 ReadByte jpeg ReadByte jpeg ReadByte jpeg ReadByte jpeg ReadByte jpeg ReadByte jpeg ReadByte jpeg Local loop:Int For loop = 1 To block_length - 7 ReadByte jpeg Next If ReadByte (jpeg) = $FF result = True EndIf EndIf Catch ReadFail:Object DebugLog "Read error in " + f End Try CloseFile jpeg EndIf Return result End Function Function GotPNG:Int (f:String) If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local result:Int = False Local png:TStream = BigEndianStream (ReadFile (f)) If png Try If ReadByte (png) = $89 And Chr (ReadByte (png)) = "P" And Chr (ReadByte (png)) = "N" And Chr (ReadByte (png)) = "G" ' PNG header continued... If ReadByte (png) = 13 And ReadByte (png) = 10 And ReadByte (png) = 26 And ReadByte (png) = 10 For Local loop:Int = 1 To 4 ReadByte png Next ' IHDR chunk (always first)... If Chr (ReadByte (png)) = "I" And Chr (ReadByte (png)) = "H" And Chr (ReadByte (png)) = "D" And Chr (ReadByte (png)) = "R" result = True EndIf EndIf EndIf Catch ReadFail:Object DebugLog "Read error in " + f End Try CloseFile png EndIf Return result End Function Function GotTGA:Int (f:String, ext:Int = True) ' Best to take extension into account here, since there are no 100% identifying TGA markers... If ext If Lower (ExtractExt (f)) <> "tga" Return False EndIf EndIf If Lower (Left (f, 7)) = "http://" f = "http::" + Right (f, Len (f) - 7) EndIf Local result:Int = False Local tga:TStream = LittleEndianStream (ReadFile (f)) If tga Try ReadByte tga ReadByte tga ReadByte tga ReadShort tga ReadShort tga Local mapbits:Byte = ReadByte (tga) ReadShort tga ReadShort tga ' Width and height > 0... If ReadShort (tga) > 0 And ReadShort (tga) > 0 ' Depth > 0 or bits per palette entry > 0... Local depth:Byte = ReadByte (tga) If depth result = True Select depth Case 8 Case 16 Case 24 Case 32 Default result = False End Select Else If mapbits result = True Select depth Case 15 Case 16 Case 24 Case 32 Default result = False End Select EndIf EndIf EndIf Catch ReadFail:Object DebugLog "Read error in " + f End Try CloseFile tga EndIf Return result End Function Function GetImageInfo:ImageInfo (f:String) Local i:ImageInfo = New ImageInfo Local ext:String = Lower (ExtractExt (f)) Select ext:String Case "jpg", "jpeg", "jpe", "jfif" i = GetJPEGInfo (f) Case "gif" i = GetGIFInfo (f) Case "bmp" i = GetBMPInfo (f) Case "png" i = GetPNGInfo (f) Case "tga" i = GetTGAInfo (f) Default i = Null End Select If i = Null If GotJPEG (f) Then i = GetJPEGInfo (f); If i Then i.info = "This is really a JPEG file!"; Return i If GotBMP (f) Then i = GetBMPInfo (f); If i Then i.info = "This is really a BMP file!"; Return i If GotPNG (f) Then i = GetPNGInfo (f); If i Then i.info = "This is really a PNG file!"; Return i If GotGIF (f) Then i = GetGIFInfo (f); If i Then i.info = "This is really a GIF file!"; Return i If GotTGA (f) Then i = GetTGAInfo (f); If i Then i.info = "This is really a TGA file!"; Return i EndIf Return i End Function |
Comments
| ||
Quick test -- add some image filenames: If you have a folder full of images (including any sub-folders), this will go through all of them and print the details. |
| ||
Some JPEG files contain EXIF data - data which shows information from the digital camera/phone the picture was taken on; such as date/time taken, shutter speed, ISO, aperture, white balance and so on. You checked for any correlation between that and the jpeg images that don't work right? |
| ||
No, it doesn't appear to be related to EXIF information. I believe some files don't contain the expected $FF, or possibly $C0, values, though I need to look into it further... ($FF marks the start of a block of information, and a following $C0 marks the block containing width/height information... at a very quick glance, it seems either that $C0 isn't found after a $FF in the files that fail, or the expected $FF block marker isn't found where it's expected at some point.) I believe EXIF would just be another $FF block (or several), but this program seems to prove EXIF isn't the problem. |
| ||
I read somewhere that when you open a jpeg, part of the file is run as an exe so perhaps they built some kind of protection into it... maybe check the disc space it takes up, then ctrl-prtSc it and save as the same resolution jpeg. and see if it still doesnt return info? |
| ||
part of the file is run as an exe I don't think that's true! I've almost got it sussed, though -- only 8 of my 10,000+ JPEGs are failing now (as opposed to around 1,400 yesterday!). I just had to check for some more $FFCx markers and relax the requirement for certain 'correct' details which are often skipped in reality. The only other 'fails' were images with incorrect extensions (eg. a BMP file named as "blah.jpg"), so that's pretty good. I have an idea what might be wrong with the remaining 8 files, but will be updating this code soon anyway... |
| ||
[EDIT: Sorted!] Gah! Photoshop 7 JPEGs are the only ones failing, and it seems that they're widely incompatible unless saved using the 'Save for Web' function, since Adobe wisely decided to do their own thing that nobody else does. I might have a go at working around this, but I don't think it's that important -- see links below if interested: http://photo.net/bboard/q-and-a-fetch-msg?msg_id=003j8d http://www.codeproject.com/KB/graphics/iptc.aspx?fid=2301&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=716178 http://www.tow.com/photo/articles/1d_jpeg_iptc/ http://209.85.229.132/search?q=cache:Lf0CVkgJLMwJ:www.adobeforums.com/webx%3F14@@... |
| ||
I've updated the code (and my first post) with the fixed JPEG reader. It seems to correctly retrieve the details of any supported image file I throw at it now! The only exceptions have been images named with the wrong extension, just because the test code passes images to each decoder based on extension (so it actually flags mis-named files!). Just got to test on PPC Mac, attempt to work around stupid PS 7 JPEGs and add some checking for corrupt files (so I don't call ReadByte past the end of broken files, not that this has come up so far). |
| ||
I read somewhere that when you open a jpeg, part of the file is run as an exe so perhaps they built some kind of protection into it. That's not true, although there have been some viruses that did spread through plain images: This was due to an archaic windows 3.x printer image format that contained some macro system which was found to be vulnerable to buffer overflows. This was exploited by renaming the bad files in question to .JPG, which IE would then blindly hand over to the Windows rendering system to display... Except it wasn't really a JPEG but a different file format containing the virus code which then got executed. The problem was 'fixed' by Microsoft by removing support for the other image format altogether. Normal JPEGs have no executable code or 'smarts' inside of them, it's just a common lossy compression algorithm. |
| ||
For anyone that may be interested, this now appears to provide 100% correct results for all supported image formats -- BMP, PNG, JPEG and Gif so far. Please see updated code (including example in first post), and my updated comments before the code. |
| ||
I haven't looked at your code, but does your code also determine the pic type by looking at the info, or does it use the file extension? Can you just feed it a file (such as picture.dat) and it tell you whether it is jpg, gif, bmp, or png as well as give you the info? |
| ||
This is great! Any thought of extending it to support exif reading? (Not the only place I put this request): /Community/posts.php?topic=84682 http://code.google.com/p/maxmods/issues/detail?id=9 |
| ||
Thanks James. I had my own hacked jpg size reader before. I just adapted Marks jpg loader but hacked it so it only read the first few bytes - seemed to work ok, but this is much better. |
| ||
Sounds good but dont forget the tga format :) |
| ||
I've added TGA support, and (@ TaskMaster) I do plan to add proper image type checking rather than just relying on extension. Dunno about Exif... I got really bogged down by that in the JPEG code, but might have another go! (I've put the demos into the first post so the main code can just be copied and pasted into your own projects. You'll have to paste it into the demos to try them!) |
| ||
Wa-hey... coming in the next day or so:Info for "http://www.hi-toro.com/images/test.tga": 512 x 384, 16777216 colours (Uncompressed color-mapped image, no alpha mask) Info for "http://www.hi-toro.com/images/test.png": 300 x 300, 256 colours (Pixels represented by RGB values) URLs (http:// only) can now be passed as easily as filenames. Online images do (eg. JPEG) block jumps byte-by-byte, while local images can just use SeekStream to keep the same speed. I need to do some more error-checking (particularly for EOF) before adding any more features (eg. found a couple of instances of not returning Null on failure to retrieve information). |
| ||
I've updated this entry with online support (just pass a normal http:// based URL), and I've added Try/Catch around byte read sections, so that broken files are aborted safely. (Tested on some deliberately truncated files, online and locally.)image:ImageInfo = GetImageInfo ("http://www.hi-toro.com/images/test.png") If image <> Null Print "Width: " + image.width Print "Height: " + image.height Print "Colours: " + image.colors Print "Info: " + image.info Else Print "Couldn't get image information!" EndIf Next will be proper file-type checking, rather than choosing which function to call based on the file extension. Also need to add consistency between formats' colour reporting, which is a bit mixed at present. EDIT: Fixed variable name discrepancy when running without SuperStrict. |
| ||
Fixed endianness so it now works correctly on PPC Macs -- it was failing on some file types. There is a minor problem still on the PPC Mac, but I think it's a Blitz bug/discrepancy. It doesn't crash, though -- it just returns false information for images that are broken/truncated. For normal files it's fine. |
| ||
Proper file-type checking now added... It now checks using the file extension first, as before (since most files are named correctly), but if the result of GetImageInfo () is Null (the expected result where a file's extension is incorrect), it byte-checks the actual file type. (It puts a warning with the correct file type into the .info field, but the width/height/etc results should be correct regardless, assuming you have a valid, non-Null ImageInfo result.) |
| ||
The "minor problem" on PPC Mac is non-existent if your BlitzMax installation is up to date -- version 1.33 upwards will be fine. Corrupt files are correctly caught and skipped. |
Code Archives Forum