Get image width and height without loading image

Just starting out? Need help? Post your questions and find answers here.
User avatar
Michael Vogel
Addict
Addict
Posts: 2808
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Get image width and height without loading image

Post by Michael Vogel »

Hm,
had some time to investigate wilberts code - like the method using the memory array!

Maybe I can include the other formats (jpeg2, bmp etc.) into wilberts scheme next weekend.

Just two small things...
*) the check for fileextensions could be problematic for extensions different to 3 characters ("something.nojpeg")
*) FFCC seems to be excluded as well for JPEGs, so what about changing the code to...

Code: Select all

:
:
			If *MemArray\w[0] & $F0FF= $C0FF
						a = *MemArray\a[1]
						If a=$C0 Or a&3
							*Size\Width = *MemArray\a[5] << 8 | *MemArray\a[6]
							*Size\Height = *MemArray\a[3] << 8 | *MemArray\a[4]
:
:		
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Get image width and height without loading image

Post by wilbert »

Michael Vogel wrote:*) the check for fileextensions could be problematic for extensions different to 3 characters ("something.nojpeg")
I am aware of that but all normal file extensions for images I know of are 3 or 4 characters.
It will accept your .nojpeg example as well but since it's only a pre-check, such a file will be recognized as not being an image later on when you check the first four bytes of the file.
When I compared my procedure with the FindString/LCase/GetExtensionPart construction you were using it was about 10 times faster so even with a few false positives it will probably still be a faster approach.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Michael Vogel
Addict
Addict
Posts: 2808
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Get image width and height without loading image

Post by Michael Vogel »

Converted the source code into "Wilbert-style" - supports BMP, GIF, JPEG, JPEG2000, PCX, PNG, TGA, TIF images.

Code: Select all

Structure ImageSizeType
	Width.l
	Height.l
EndStructure

Procedure.l CheckImageName(*Name)

	!xor eax, eax
	!xor ecx, ecx
	CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
		!mov rdx, [p.p_Name]
		!iiname_loop:
		!shrd eax, ecx, 8
		CompilerIf #PB_Compiler_Unicode
			!mov cx, [rdx]
			!add rdx, 2
		CompilerElse
			!movzx cx, byte [rdx]
			!inc rdx
		CompilerEndIf
	CompilerElse
		!mov edx, [p.p_Name]
		!iiname_loop:
		!shrd eax, ecx, 8
		CompilerIf #PB_Compiler_Unicode
			!mov cx, [edx]
			!add edx, 2
		CompilerElse
			!movzx cx, byte [edx]
			!inc edx
		CompilerEndIf
	CompilerEndIf
	!test cx, cx
	!jnz iiname_loop
	!or eax, 0x20202020
	!cmp eax, '.bmp'
	!je iiname_exit
	!cmp eax, '.gif'
	!je iiname_exit
	!cmp eax, '.jp2'
	!je iiname_exit
	!cmp eax, '.jpg'
	!je iiname_exit
	!cmp eax, '.pcx'
	!je iiname_exit
	!cmp eax, '.png'
	!je iiname_exit
	!cmp eax, 'jpeg'
	!je iiname_exit
	!cmp eax, '.tif'
	!je iiname_exit
	!cmp eax, '.tga'
	!je iiname_exit
	!xor eax, eax
	!iiname_exit:

	ProcedureReturn

EndProcedure
Procedure ImageFileDimension(filename.s,*imagesize.ImageSizeType)

	#ImageMinimumSize=		24
	#ImageHeaderSize= 		2048

	#ImageHeaderGIF=	$38464947;		'GIF8'
	#ImageHeaderJPG=	$E0FFD8FF;		-
	#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.i
	Protected a.a,n.l,m

	#ImageFile=666

	*imagesize\width=#Null
	*imagesize\height=#Null

	If CheckImageName(@FileName)
		If ReadFile(#ImageFile,FileName, #PB_File_NoBuffering)
			*Buffer=AllocateMemory(#ImageHeaderSize,#PB_Memory_NoClear)
			BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)

			If BytesRead>=#ImageMinimumSize
				Select *Buffer\l[0]&$FFFFFFFF

				Case #ImageHeaderJPG
					n=*Buffer\a[4]<< 8|*Buffer\a[5]+4
					If n>20
						FileSeek(0,n)
						BytesRead=ReadData(#ImageFile,*Buffer,#ImageHeaderSize)
						n=0
					EndIf
					*MemArray=*Buffer+n
					While *MemArray-*Buffer+6<BytesRead
						If *MemArray\a[0]=$FF
							a=*MemArray\a[1]
							If a=$c0 Or (a>>4=$C And a&3)
								*imagesize\width=*MemArray\a[7]<<8|*MemArray\a[8]
								*imagesize\height=*MemArray\a[5]<<8|*MemArray\a[6]
								Break
							EndIf
						Else
							Break
						EndIf
						*MemArray+*MemArray\a[2]<<8|*MemArray\a[3]+2
					Wend

				Case #ImageHeaderPNG
					*imagesize\width=*Buffer\a[18]<<8|*Buffer\a[19]
					*imagesize\height=*Buffer\a[22]<<8|*Buffer\a[23]

				Case #ImageHeaderGIF
					*imagesize\width=*Buffer\w[3]
					*imagesize\height=*Buffer\w[4]

				Case #ImageHeaderJP2
					n=*Buffer\a[14]<<8|*Buffer\a[15]+35
					If n<#ImageHeaderSize
						*imagesize\width=*Buffer\a[n-1]<<8|*Buffer\a[n]
						*imagesize\height=*Buffer\a[n-5]<<8|*Buffer\a[n-4]
					EndIf

				Default
					Select *Buffer\w[0]&$FFFF

					Case #ImageHeaderBMP
						*imagesize\width=*Buffer\w[9]
						n=*Buffer\w[11]&$FFFF
						If n<0
							n=-n
						EndIf
						*imagesize\height=n

					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
									*imagesize\width=*Buffer\w[n+4]
									a|1
								Case $101
									*imagesize\height=*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
									*imagesize\width=*Buffer\a[n+8]<<8|*Buffer\a[n+9]
									a|1
								Case $101
									*imagesize\height=*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
								*imagesize\width=*Buffer\w[4]+1
								*imagesize\height=*Buffer\w[5]+1
							EndIf
							
						Case #ImageHeaderTGA
							If *Buffer\a[1]<2 And *Buffer\a[2]&%11110100=0
								*imagesize\width=*Buffer\w[6]
								*imagesize\height=*Buffer\w[7]
							EndIf
					EndSelect

					EndSelect

				EndSelect
			EndIf
			FreeMemory(*Buffer)
			CloseFile(#ImageFile)
		EndIf
	EndIf
	
	Debug "------ "+GetFilePart(filename)+" ------"
	Debug Str(*imagesize\Width)+" x "+Str(*imagesize\Height)
	
EndProcedure


x.ImageSizeType
ImageFileDimension("Data\PB.gif",x)
ImageFileDimension("Data\LSB.tif",x)
ImageFileDimension("Data\MSB.tif",x)
ImageFileDimension("Data\Willi.jpg",x)
ImageFileDimension("Data\Logo.jp2",x)
ImageFileDimension("Data\Bird.png",x)
ImageFileDimension("Data\Logo.bmp",x)
ImageFileDimension("Data\Bert.bmp",x)
ImageFileDimension("Data\Logo.pcx",x)
ImageFileDimension("Data\Logo.tga",x)
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Get image width and height without loading image

Post by Fangbeast »

Using the code above, I just added the below code to get the dimensions of images. 2 jpeg files failed although WIndows can see them and I can load them manually.

How do I get the bit depth as well?

Code: Select all

  DirectoryEntryId.i = ExamineDirectory(#PB_Any, "Pictures\", "*.*")
  
  If DirectoryEntryId.i
    Repeat
      TypeOfFile = NextDirectoryEntry(DirectoryEntryId.i) 
      FileName.s = DirectoryEntryName(DirectoryEntryId.i)
      If TypeOfFile = 1
        If FileName.s <> "." And FileName.s <> ".." 
          ImageFileDimension("Pictures\" + FileName.s, x)
        EndIf
      EndIf 
    Until TypeOfFile = 0 
  EndIf
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Get image width and height without loading image

Post by wilbert »

Fangbeast wrote:Using the code above, I just added the below code to get the dimensions of images. 2 jpeg files failed although WIndows can see them and I can load them manually.
You can try if there's a difference between the implementation I did ( http://www.purebasic.fr/english/viewtop ... 70#p462670 ) and the one Michael did ( http://www.purebasic.fr/english/viewtop ... 53#p462853 ).
If it doesn't make a difference, you can try to increase the #ImageHeaderSize value from 2048 to 3072 or 4096.
If it still isn't working, I don't know. You could share the jpg to take a look at it.
Fangbeast wrote:How do I get the bit depth as well?
That would be different for each image type.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Get image width and height without loading image

Post by Fangbeast »

I would change things if I knew what I was doing but this is assembly/assembler so I am out of luck.

Not to worry, I will try something else for now, thanks for the help.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
User avatar
JHPJHP
Addict
Addict
Posts: 2258
Joined: Sat Oct 09, 2010 3:47 am

Re: Get image width and height without loading image

Post by JHPJHP »

See my Services, Stuff, and Shellhook post for an alternate solution.
- Stuff/GadgetStuff/WebGadget/ImageSize.pb
Last edited by JHPJHP on Fri Feb 12, 2016 2:30 am, edited 3 times in total.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
Kiffi
Addict
Addict
Posts: 1504
Joined: Tue Mar 02, 2004 1:20 pm
Location: Amphibios 9

Re: Get image width and height without loading image

Post by Kiffi »

here is a COMate-Solution:

Code: Select all

EnableExplicit

IncludePath "YourPathTo\COMatePLUS\"
XIncludeFile "COMatePLUS.pbi"

Procedure.s GetVbsCode(Filename.s)
  
  Protected VbsCode.s
  
  VbsCode = "CONST cWIDTH  = 162" + #CRLF$ + 
            "CONST cHEIGHT = 164" + #CRLF$ + 
            "Set oShell = CreateObject(" + Chr(34) + "Shell.Application" + Chr(34) + ")" + #CRLF$ + 
            "Set oFolder = oShell.Namespace(#FOLDER#)" + #CRLF$ + 
            "Set oFile = oFolder.ParseName(#FILE#)" + #CRLF$ + 
            "width = oFolder.GetDetailsOf(oFile, cWIDTH)" + #CRLF$ + 
            "height = oFolder.GetDetailsOf(oFile, cHEIGHT)" + #CRLF$
            
  VbsCode = ReplaceString(VbsCode, "#FOLDER#", Chr(34) + GetPathPart(Filename) + Chr(34))
  VbsCode = ReplaceString(VbsCode, "#FILE#", Chr(34) + GetFilePart(Filename) + Chr(34))
  
  ProcedureReturn VbsCode
  
EndProcedure

Define.COMateObject scriptObject, errorObject
Define Filename.s
Define width.s, height.s

Filename = "YourImage"

scriptObject = COMate_CreateObject("MSScriptControl.ScriptControl.1") 

If scriptObject
  scriptObject\SetProperty("Language = 'VBScript'")
  If scriptObject\Invoke("AddCode('" + GetVbsCode(Filename) + "')") = #S_OK
    width.s  = scriptObject\GetStringProperty("Eval('width')")
    height.s = scriptObject\GetStringProperty("Eval('height')")
    MessageRequester(GetFilePart(Filename), "Width: " + width + #CRLF$ +  "Height: " + height)
  Else
    errorObject = scriptObject\GetObjectProperty("Error")
    If errorObject  
      MessageRequester("Script demo - error reported!", Chr(34) + errorObject\GetStringProperty("Text") + Chr(34) + #LF$ + " produced the following error : " + #LF$ + #LF$ + errorObject\GetStringProperty("Description"))
      errorObject\Release()
    EndIf
  EndIf
  scriptObject\Release()
Else
  MessageRequester("COMate - Scripting demo", "Couldn't create the scripting object!")
EndIf
Greetings ... Peter
Hygge
User avatar
Michael Vogel
Addict
Addict
Posts: 2808
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Get image width and height without loading image

Post by Michael Vogel »

Fangbeast wrote:Using the code above, I just added the below code to get the dimensions of images. 2 jpeg files failed although WIndows can see them and I can load them manually.
Maybe you can upload them somewhere - this would allow to do check what's going on...
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Get image width and height without loading image

Post by Fangbeast »

Michael Vogel wrote:
Fangbeast wrote:Using the code above, I just added the below code to get the dimensions of images. 2 jpeg files failed although WIndows can see them and I can load them manually.
Maybe you can upload them somewhere - this would allow to do check what's going on...
Thanks Michael but I went back to the pb way of doing it originally. Limited time in october, blood tests, hospital visits, birthdays etc. The little picture database now works fine.

Just need to decide whether to allow a default category during mass import and then I am finished.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: Get image width and height without loading image

Post by RASHAD »

Hi Fangles
- Download ImageMagick (It is freeware)
- Use the command line identify.exe "Your image file name" through PB command Runprogram()
- You will get what you want in no time
Egypt my love
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4790
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: Get image width and height without loading image

Post by Fangbeast »

RASHAD wrote:Hi Fangles
- Download ImageMagick (It is freeware)
- Use the command line identify.exe "Your image file name" through PB command Runprogram()
- You will get what you want in no time
Thanks RASHAD but as I said to Michael above "Thanks Michael but I went back to the pb way of doing it originally. Limited time in october, blood tests, hospital visits, birthdays etc. The little picture database now works fine.
Amateur Radio/VK3HAF, (D-STAR/DMR and more), Arduino, ESP32, Coding, Crochet
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Re: Get image width and height without loading image

Post by RASHAD »

I wish you the best with October Fang
BTW identify.exe will cover a lot of formats much more than what PB cover
Beside it can analyze more than one image file in one run
Do test it after October
My best wishes for you my friend
Egypt my love
User avatar
Michael Vogel
Addict
Addict
Posts: 2808
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Get image width and height without loading image

Post by Michael Vogel »

Fangbeast, all the best for you - hopefully you will have better times soon...

...then, if you like, we'll continue with this thread here :wink:
User avatar
Vera
Addict
Addict
Posts: 858
Joined: Tue Aug 11, 2009 1:56 pm
Location: Essen (Germany)

Re: Get image width and height without loading image

Post by Vera »

Wishing you good results Fangbeast and happy celebrations Image
Post Reply