Get image width and height without loading image
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
Hello chaps, sorry to bother you with this.
I'm using this code with PB5.42Beta1 on Win7 x86. The code is super fast and is giving accurate results.
However, a few files return a size of zero zero. I have set #ImageHeaderSize = 4096
ImageSize.zip
Edit: I should mention that I'm using Michael Vogel's "Wilbert-style" code, posted: Fri Mar 20, 2015 2:48pm
I'm using this code with PB5.42Beta1 on Win7 x86. The code is super fast and is giving accurate results.
However, a few files return a size of zero zero. I have set #ImageHeaderSize = 4096
ImageSize.zip
Edit: I should mention that I'm using Michael Vogel's "Wilbert-style" code, posted: Fri Mar 20, 2015 2:48pm
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Michael Vogel
- Addict
- Posts: 2808
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Get image width and height without loading image
IdeasVacuum, maybe you will try the following tool to check if I do something wrong: Speed Renamer - just copy all files in the same directory as your example images.
After starting the SpeedRenamer, all image files should be prepared to be renamed to "<px> x <py>.<e>", what means "width x height plus extension"...
...if everything works as expected, I will extract all parts from the source you need for your program.
After starting the SpeedRenamer, all image files should be prepared to be renamed to "<px> x <py>.<e>", what means "width x height plus extension"...
...if everything works as expected, I will extract all parts from the source you need for your program.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
Points of interest
The Win7 sample images verify zero zero with #ImageHeaderSize = 4096. They are all the same Width/Height, all .jpgs, Filesizes range from 549KB to 859KB.
If #ImageHeaderSize = 8182, all but two of the images verify.
If #ImageHeaderSize = 10240, all images verify.
Instead of using the #ImageHeaderSize constant, I tried FileSize() instead. This also worked with the Win7 sample images but not with the bunch of .jpg files I have posted here. Tricky
The Win7 sample images verify zero zero with #ImageHeaderSize = 4096. They are all the same Width/Height, all .jpgs, Filesizes range from 549KB to 859KB.
If #ImageHeaderSize = 8182, all but two of the images verify.
If #ImageHeaderSize = 10240, all images verify.
Instead of using the #ImageHeaderSize constant, I tried FileSize() instead. This also worked with the Win7 sample images but not with the bunch of .jpg files I have posted here. Tricky

IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Michael Vogel
- Addict
- Posts: 2808
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Get image width and height without loading image
Are these values ok?


-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
Hello Michael
Followed your instructions and sure enough, SpeedRenamer lists the files, new "<px> x <py>.<e>" name and their Width/Height/Size, as shown in your screenshot. The sizes match those reported by the OS and by IrfanView.
Followed your instructions and sure enough, SpeedRenamer lists the files, new "<px> x <py>.<e>" name and their Width/Height/Size, as shown in your screenshot. The sizes match those reported by the OS and by IrfanView.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Michael Vogel
- Addict
- Posts: 2808
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Get image width and height without loading image
Okay, will extract the code, but you have to be patient, will do so tomorrow morning...
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
That is very kind of you Michael and much appreciated.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Michael Vogel
- Addict
- Posts: 2808
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Get image width and height without loading image
Here we are (hope it works)...
Code: Select all
Structure FileType
ImageX.i
ImageY.i
EndStructure
Global Dim File.FileType(0)
Procedure.i iAbs(val.i)
EnableASM
CompilerIf #PB_Compiler_Processor=#PB_Processor_x86
MOV eax, val
NEG eax
CMOVS eax, val
CompilerElse
MOV rax, val
NEG rax
CMOVS rax, val
CompilerEndIf
DisableASM
ProcedureReturn
EndProcedure
Procedure GetImageInformation(entry,filename.s)
#ImageMinimumSize= 24
#ImageHeaderSize= 2048
#ImageHeaderGIF= $38464947; 'GIF8'
#ImageHeaderJPG0= $E0FFD8FF; -
#ImageHeaderJPG1= $E1FFD8FF; -
#ImageHeaderJP2= $0C000000; -
#ImageHeaderPNG= $474E5089; '‰PNG'
#ImageHeaderBMP= $4D42; 'BM'
#ImageHeaderTIF_LSB= $4949; 'II'
#ImageHeaderTIF_MSB= $4D4D; 'MM'
#ImageHeaderPCX= $0A; -
#ImageHeaderTGA= $01; -
Structure MemArray
StructureUnion
a.a[0]
w.w[0]
l.l[0]
EndStructureUnion
EndStructure
Protected *Buffer.MemArray
Protected *MemArray.MemArray
Protected BytesRead
Protected FileShift
Protected a.a,n.l,m
#ImageFile=666
File(entry)\ImageX=#Null
File(entry)\ImageY=#Null
If #True
If ReadFile(#ImageFile,FileName, #PB_File_NoBuffering|#PB_File_SharedRead)
*Buffer=AllocateMemory(#ImageHeaderSize,#PB_Memory_NoClear)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
If BytesRead>=#ImageMinimumSize
Select *Buffer\l[0]&$FFFFFFFF
Case #ImageHeaderJPG0,#ImageHeaderJPG1
n=*Buffer\a[4]<< 8|*Buffer\a[5]+4
If n>20
FileShift=n
FileSeek(#ImageFile,n)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
n=0
EndIf
*MemArray=*Buffer+n
While *MemArray-*Buffer+8<=BytesRead; 8 Bytes Information
If *MemArray\a[0]=$FF
a=*MemArray\a[1]
; Debug Hex(*MemArray\w[0])
If a=$c0 Or (a>>4=$C And a&3)
File(entry)\ImageX=*MemArray\a[7]<<8|*MemArray\a[8]
File(entry)\ImageY=*MemArray\a[5]<<8|*MemArray\a[6]
Break
EndIf
Else
Break
EndIf
*MemArray+*MemArray\a[2]<<8|*MemArray\a[3]+2
If *MemArray-*Buffer>=BytesRead-8; 8 Bytes Information
FileShift+*MemArray-*Buffer
FileSeek(#ImageFile,FileShift)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
*MemArray=*Buffer
EndIf
Wend
Case #ImageHeaderPNG
File(entry)\ImageX=*Buffer\a[18]<<8|*Buffer\a[19]
File(entry)\ImageY=*Buffer\a[22]<<8|*Buffer\a[23]
Case #ImageHeaderGIF
File(entry)\ImageX=*Buffer\w[3]
File(entry)\ImageY=*Buffer\w[4]
Case #ImageHeaderJP2
n=*Buffer\a[14]<<8|*Buffer\a[15]+35
If n<#ImageHeaderSize
File(entry)\ImageX=*Buffer\a[n-1]<<8|*Buffer\a[n]
File(entry)\ImageY=*Buffer\a[n-5]<<8|*Buffer\a[n-4]
EndIf
Default
Select *Buffer\w[0]&$FFFF
Case #ImageHeaderBMP
File(entry)\ImageX=*Buffer\w[9]
File(entry)\ImageY=iAbs(*Buffer\w[11]&$FFFF)
Case #ImageHeaderTIF_LSB
a=0
n=*Buffer\l[1]
If n<#ImageHeaderSize
n>>1
m=*Buffer\w[n]
n+1
While m
Select *Buffer\w[n]
Case $100
File(entry)\ImageX=*Buffer\w[n+4]
a|1
Case $101
File(entry)\ImageY=*Buffer\w[n+4]
a|2
EndSelect
If a=3
m=0
Else
n+6
m-1
EndIf
Wend
EndIf
Case #ImageHeaderTIF_MSB
a=0
n=*Buffer\a[6]<<8|*Buffer\a[7]
If n<#ImageHeaderSize
m=*Buffer\a[n]<<8|*Buffer\a[n+1]
n+2
While m
Select *Buffer\a[n]<<8|*Buffer\a[n+1]
Case $100
File(entry)\ImageX=*Buffer\a[n+8]<<8|*Buffer\a[n+9]
a|1
Case $101
File(entry)\ImageY=*Buffer\a[n+8]<<8|*Buffer\a[n+9]
a|2
EndSelect
If a=3
m=0
Else
n+12
m-1
EndIf
Wend
EndIf
Default
Select *Buffer\a[0]
Case #ImageHeaderPCX
If *Buffer\a[1]<6
File(entry)\ImageX=*Buffer\w[4]+1
File(entry)\ImageY=*Buffer\w[5]+1
EndIf
Case #ImageHeaderTGA
If *Buffer\a[1]<2 And *Buffer\a[2]&%11110100=0
File(entry)\ImageX=*Buffer\w[6]
File(entry)\ImageY=*Buffer\w[7]
EndIf
EndSelect
EndSelect
EndSelect
EndIf
FreeMemory(*Buffer)
CloseFile(#ImageFile)
EndIf
EndIf
EndProcedure
If ExamineDirectory(0,".","*.jpg")
While NextDirectoryEntry(0)
If DirectoryEntryType(0)=#PB_DirectoryEntry_File
file.s=DirectoryEntryName(0)
GetImageInformation(0,file)
Debug file+": "+Str(File(0)\ImageX)+" x "+Str(File(0)\ImageY)
EndIf
Wend
FinishDirectory(0)
EndIf
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
That was fast Michael, thank you.
So, essentially the change is: replace #ImageHeaderJPG with #ImageHeaderJPG0 and #ImageHeaderJPG1?
I'm getting a crash at FileSeek(0, n) at the moment - possibly a file hitherto untried. Time for me to experiment a bit.
So, essentially the change is: replace #ImageHeaderJPG with #ImageHeaderJPG0 and #ImageHeaderJPG1?
I'm getting a crash at FileSeek(0, n) at the moment - possibly a file hitherto untried. Time for me to experiment a bit.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
OK, in fact a number of subtle changes have been made.
I have tested the "rogue" images and as many suspect images that I can find, all of which now process beautifully. Also, it's no longer necessary to increase the buffer size in order to verify the Win7 sample images.
Brilliant job Michael!
I have tested the "rogue" images and as many suspect images that I can find, all of which now process beautifully. Also, it's no longer necessary to increase the buffer size in order to verify the Win7 sample images.
Brilliant job Michael!
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
So, of any 100 images, 2% are not being verified via the header. In my app, if the Width or Height result is zero, another procedure is called to load the image and verify with the PB functions. There is no noticable lack of speed, but of course if a whole batch of images failed rather than 2%, that could be a bit slower (2.5 seconds on my PC).
The .jpg files seem to be the most unreliable......
Here is one that SpeedRenamer verifies as 0 x 0 size. Actual size is 960 x 960 (104KB)
Denzil Washington.zip
The start of the other files is typically: FF E0 00 10 4A 46 49 46 00
Denzil Washinton.jpg: FF E2 02 1C 49 43 43 5F 50
The .jpg files seem to be the most unreliable......
Here is one that SpeedRenamer verifies as 0 x 0 size. Actual size is 960 x 960 (104KB)
Denzil Washington.zip
The start of the other files is typically: FF E0 00 10 4A 46 49 46 00
Denzil Washinton.jpg: FF E2 02 1C 49 43 43 5F 50
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Michael Vogel
- Addict
- Posts: 2808
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Get image width and height without loading image
Please check if you'll get better results than 98% by doing a small update...
Change/add the following constants:
#ImageHeaderAPP1= $E1FFD8FF; was #ImageHeaderJPG1
#ImageHeaderAPP2= $E2FFD8FF; new
Change the first line with a Case statement to:
Case #ImageHeaderJPG0,#ImageHeaderAPP1,#ImageHeaderAPP2
Change/add the following constants:
#ImageHeaderAPP1= $E1FFD8FF; was #ImageHeaderJPG1
#ImageHeaderAPP2= $E2FFD8FF; new
Change the first line with a Case statement to:
Case #ImageHeaderJPG0,#ImageHeaderAPP1,#ImageHeaderAPP2
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
Hello Michael
That has fixed Denzil Washington.jpg types
What I have not tested are tif, tga, jp2 (have not got files of those types)
Edit: Just converted mostly .jpg files to .tif and .tga files using IrfanView. Not one of them verifies....
That has fixed Denzil Washington.jpg types

What I have not tested are tif, tga, jp2 (have not got files of those types)
Edit: Just converted mostly .jpg files to .tif and .tga files using IrfanView. Not one of them verifies....
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.
- Michael Vogel
- Addict
- Posts: 2808
- Joined: Thu Feb 09, 2006 11:27 pm
- Contact:
Re: Get image width and height without loading image
So still not 100%, I fear, we'll never get very close
TGA and TIF examples

TGA and TIF examples
Code: Select all
Structure FileType
ImageX.i
ImageY.i
EndStructure
Global Dim File.FileType(0)
Procedure.i iAbs(val.i)
EnableASM
CompilerIf #PB_Compiler_Processor=#PB_Processor_x86
MOV eax, val
NEG eax
CMOVS eax, val
CompilerElse
MOV rax, val
NEG rax
CMOVS rax, val
CompilerEndIf
DisableASM
ProcedureReturn
EndProcedure
Procedure GetImageInformation(entry,filename.s)
#ImageMinimumSize= 24
#ImageHeaderSize= 2048
#ImageHeaderSizeTif= 48; Just a guess
#ImageHeaderGIF= $38464947; 'GIF8'
#ImageHeaderJPG= $E0FFD8FF; -
#ImageHeaderAPP1= $E1FFD8FF; -
#ImageHeaderAPP2= $E2FFD8FF; -
#ImageHeaderJP2= $0C000000; -
#ImageHeaderPNG= $474E5089; '‰PNG'
#ImageHeaderBMP= $4D42; 'BM'
#ImageHeaderTIF_LSB= $4949; 'II'
#ImageHeaderTIF_MSB= $4D4D; 'MM'
#ImageHeaderPCX= $0A; -
#ImageHeaderTGA= $01; -
Structure MemArray
StructureUnion
a.a[0]
w.w[0]
l.l[0]
EndStructureUnion
EndStructure
Protected *Buffer.MemArray
Protected *MemArray.MemArray
Protected BytesRead
Protected FileShift
Protected a.a,n.l,m
#ImageFile=666
File(entry)\ImageX=#Null
File(entry)\ImageY=#Null
If #True
If ReadFile(#ImageFile,FileName, #PB_File_NoBuffering|#PB_File_SharedRead)
*Buffer=AllocateMemory(#ImageHeaderSize,#PB_Memory_NoClear)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
If BytesRead>=#ImageMinimumSize
; Debug Hex(*Buffer\l[0]&$FFFFFFFF)
Select *Buffer\l[0]&$FFFFFFFF
Case #ImageHeaderJPG,#ImageHeaderAPP1,#ImageHeaderAPP2
n=*Buffer\a[4]<< 8|*Buffer\a[5]+4
If n>20
FileShift=n
FileSeek(#ImageFile,n)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
n=0
EndIf
*MemArray=*Buffer+n
While *MemArray-*Buffer+8<=BytesRead; 8 Bytes Information
If *MemArray\a[0]=$FF
a=*MemArray\a[1]
; Debug Hex(*MemArray\w[0])
If a=$c0 Or (a>>4=$C And a&3)
File(entry)\ImageX=*MemArray\a[7]<<8|*MemArray\a[8]
File(entry)\ImageY=*MemArray\a[5]<<8|*MemArray\a[6]
Break
EndIf
Else
Break
EndIf
*MemArray+*MemArray\a[2]<<8|*MemArray\a[3]+2
If *MemArray-*Buffer>=BytesRead-8; 8 Bytes Information
FileShift+*MemArray-*Buffer
FileSeek(#ImageFile,FileShift)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
*MemArray=*Buffer
EndIf
Wend
Case #ImageHeaderPNG
File(entry)\ImageX=*Buffer\a[18]<<8|*Buffer\a[19]
File(entry)\ImageY=*Buffer\a[22]<<8|*Buffer\a[23]
Case #ImageHeaderGIF
File(entry)\ImageX=*Buffer\w[3]
File(entry)\ImageY=*Buffer\w[4]
Case #ImageHeaderJP2
n=*Buffer\a[14]<<8|*Buffer\a[15]+35
If n<#ImageHeaderSize
File(entry)\ImageX=*Buffer\a[n-1]<<8|*Buffer\a[n]
File(entry)\ImageY=*Buffer\a[n-5]<<8|*Buffer\a[n-4]
EndIf
Default
Select *Buffer\w[0]&$FFFF
Case #ImageHeaderBMP
File(entry)\ImageX=*Buffer\w[9]
File(entry)\ImageY=iAbs(*Buffer\w[11]&$FFFF)
Case #ImageHeaderTIF_LSB
a=0
n=*Buffer\l[1]
If n>#ImageHeaderSize-#ImageHeaderSizeTif
FileShift=n
FileSeek(#ImageFile,n)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
n=0
EndIf
n>>1
m=*Buffer\w[n]
n+1
While m And n<#ImageHeaderSizeTif>>1
Select *Buffer\w[n]
Case $100
File(entry)\ImageX=*Buffer\w[n+4]
a|1
Case $101
File(entry)\ImageY=*Buffer\w[n+4]
a|2
EndSelect
If a=3
m=0
Else
n+6
m-1
EndIf
Wend
Case #ImageHeaderTIF_MSB
a=0
n=*Buffer\a[6]<<8|*Buffer\a[7]
If n>#ImageHeaderSize-#ImageHeaderSizeTif
FileShift=n
FileSeek(#ImageFile,n)
BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
n=0
EndIf
m=*Buffer\a[n]<<8|*Buffer\a[n+1]
n+2
While m And n<#ImageHeaderSizeTif
Select *Buffer\a[n]<<8|*Buffer\a[n+1]
Case $100
File(entry)\ImageX=*Buffer\a[n+8]<<8|*Buffer\a[n+9]
a|1
Case $101
File(entry)\ImageY=*Buffer\a[n+8]<<8|*Buffer\a[n+9]
a|2
EndSelect
If a=3
m=0
Else
n+12
m-1
EndIf
Wend
Default
Select *Buffer\a[0]
Case #ImageHeaderPCX
If *Buffer\a[1]<6
File(entry)\ImageX=*Buffer\w[4]+1
File(entry)\ImageY=*Buffer\w[5]+1
EndIf
Case #ImageHeaderTGA
If *Buffer\a[1]<2 And *Buffer\a[2]&%11110100=0
File(entry)\ImageX=*Buffer\w[6]
File(entry)\ImageY=*Buffer\w[7]
EndIf
EndSelect
EndSelect
EndSelect
EndIf
FreeMemory(*Buffer)
CloseFile(#ImageFile)
EndIf
EndIf
EndProcedure
If ExamineDirectory(0,".","*.t??")
While NextDirectoryEntry(0)
If DirectoryEntryType(0)=#PB_DirectoryEntry_File
file.s=DirectoryEntryName(0)
GetImageInformation(0,file)
Debug RSet(Str(File(0)\ImageX),5," ")+" x"+RSet(Str(File(0)\ImageY),5," ")+" | "+file
EndIf
Wend
FinishDirectory(0)
EndIf
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Get image width and height without loading image
That's strange Michael - the new code for tif does not work with your sample file P1170938.tif on my PC.
Actually, I think you have got very close already, it's a brilliant job as-is.
IrfanViewTIF.zip
IrfanViewTGA.zip
If you haven't got the time to do more, or just don't fancy it, that's fine by me, you have been brilliant.
Actually, I think you have got very close already, it's a brilliant job as-is.
IrfanViewTIF.zip
IrfanViewTGA.zip
If you haven't got the time to do more, or just don't fancy it, that's fine by me, you have been brilliant.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.