Page 2 of 4

Re: Get image width and height without loading image

Posted: Tue Mar 17, 2015 10:04 am
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]
:
:		

Re: Get image width and height without loading image

Posted: Tue Mar 17, 2015 10:20 am
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.

Re: Get image width and height without loading image

Posted: Fri Mar 20, 2015 2:48 pm
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)

Re: Get image width and height without loading image

Posted: Tue Sep 29, 2015 9:17 am
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

Re: Get image width and height without loading image

Posted: Tue Sep 29, 2015 9:40 am
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.

Re: Get image width and height without loading image

Posted: Tue Sep 29, 2015 11:31 am
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.

Re: Get image width and height without loading image

Posted: Tue Sep 29, 2015 2:31 pm
by JHPJHP
See my Services, Stuff, and Shellhook post for an alternate solution.
- Stuff/GadgetStuff/WebGadget/ImageSize.pb

Re: Get image width and height without loading image

Posted: Tue Sep 29, 2015 3:14 pm
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

Re: Get image width and height without loading image

Posted: Tue Sep 29, 2015 7:39 pm
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...

Re: Get image width and height without loading image

Posted: Fri Oct 02, 2015 7:19 am
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.

Re: Get image width and height without loading image

Posted: Fri Oct 02, 2015 11:51 am
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

Re: Get image width and height without loading image

Posted: Fri Oct 02, 2015 2:16 pm
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.

Re: Get image width and height without loading image

Posted: Fri Oct 02, 2015 2:38 pm
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

Re: Get image width and height without loading image

Posted: Sun Oct 04, 2015 10:42 am
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:

Re: Get image width and height without loading image

Posted: Sun Oct 04, 2015 11:21 am
by Vera
Wishing you good results Fangbeast and happy celebrations Image