PNG Dimensions Question

General FreeBASIC programming questions.
Post Reply
datwill310
Posts: 355
Joined: May 29, 2015 20:37

PNG Dimensions Question

Post by datwill310 »

Hi all,

In my program I load dozens of images. Rn I have to hard-code all the dimensions of each PNG image along with the loading code. But to help me add more images to this list faster, I was wondering if I could gather such dimensional information with each file instead.

I have researched into the PNG format, and I have found this, the IHDR chunk. I figured reading the figures directly from the file instead of having to use FreeImage functions was preferable. Within the chunk is supposed to be the information I am after (i.e. the width and height of the image), right after the declaration of the chunk using the bytes "IHDR".
I have used a hex editor with a few images and I can't seem to find their dimensions at all within the chunk, using any sized register i.e. 4bytes, 8bytes etc., and at any position within the chunk.
AFAI knew, this chunk wasn't compressed because it is "(13 data bytes total)" and the wiki page doesn't mention compression at this point of the article.

In short, where exactly are these bytes of information (width and height of image) located in a PNG file, and what size are the values storing the width and height (I am assuming 4 bytes but idrk)?

Thanks for reading
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: PNG Dimensions Question

Post by srvaldez »

try this, no guarantee it will work on all your png's

Code: Select all

dim as ubyte n
dim as long x, y
open "yourimage.png" for binary as 1
	Get #1,19 , n
	x=n*256
	Get #1,20 , n
	x=x+n
	? x
	Get #1,23 , n
	y=n*256
	Get #1,24 , n
	y=y+n
	? y
close 1
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: PNG Dimensions Question

Post by srvaldez »

the image I looked at had the bytes 17 and 18 as 0 and bytes 21 and 22 as 0 so I don't know if they are part of the image dimension or not.
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: PNG Dimensions Question

Post by datwill310 »

srvaldez wrote:the image I looked at had the bytes 17 and 18 as 0 and bytes 21 and 22 as 0 so I don't know if they are part of the image dimension or not.
It appears as 0 too for all the images I've tried with it...
EDIT: Whoops... I used the wrong path for the image files, that's why it wasn't working xD.
Fixed that and it works very well! Thanks srvaldez!
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: PNG Dimensions Question

Post by srvaldez »

the problem is that the size info is big endian?
I thought FB had a byte-swap macro but can't find it in the help.

Code: Select all

dim as ushort x, y

open "yourimage.png" for binary as 1
	Get #1,19 , x
	asm
		mov		ax, [x]
		xchg	al, ah
		mov		[x], ax
	end asm
	? x
	Get #1,23 , y
	asm
		mov		ax, [y]
		xchg	al, ah
		mov		[y], ax
	end asm
	? y
close 1
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: PNG Dimensions Question

Post by fxm »

For example:

Code: Select all

#macro byte_swap(short_variable)
  Swap Cptr(Byte Ptr, @(short_variable))[0], Cptr(Byte Ptr, @(short_variable))[1]
#endmacro
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: PNG Dimensions Question

Post by srvaldez »

thank you fxm :-)
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: PNG Dimensions Question

Post by srvaldez »

after thinking about it, more than likely the size info is a long, though you'd have to have a really huge image, nevertheless thanks to fxm's macro modified a bit.

Code: Select all

dim as ulong x, y

#macro byte_reverse(long_variable)
	Swap Cptr(Byte Ptr, @(long_variable))[0], Cptr(Byte Ptr, @(long_variable))[3]
 	Swap Cptr(Byte Ptr, @(long_variable))[1], Cptr(Byte Ptr, @(long_variable))[2]
#endmacro

open "yourimage.png" for binary as 1
	Get #1,17 , x
	byte_reverse(x)
	Print x
	Get #1,21 , y
	byte_reverse(y)
	Print y
close 1
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: PNG Dimensions Question

Post by MrSwiss »

PNG can easily be loaded with FBImage (by D.J.Peters), thereafter, because it's a FBImage,
one can use ImageInfo(), to obtain the Image's sizes (if still required, after loading).
datwill310
Posts: 355
Joined: May 29, 2015 20:37

Re: PNG Dimensions Question

Post by datwill310 »

Thanks for the help guys, and the info!
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: PNG Dimensions Question

Post by counting_pine »

From an endian-neutral point of view, it would be better to avoid byte-swapping, and just compose the bytes into a long yourself. e.g. a(0) shl 24 + a(1) shl 16 + a(2) shl 8 + a(3).
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: PNG Dimensions Question

Post by fxm »

Yes:
-The faster:

Code: Select all

#macro byte_reverse(long_variable)
   long_variable = Cptr(Byte Ptr, @(long_variable))[0] Shl 24 + _
                   Cptr(Byte Ptr, @(long_variable))[1] Shl 16 + _
                   Cptr(Byte Ptr, @(long_variable))[2] Shl 08 + _
                   Cptr(Byte Ptr, @(long_variable))[3]
#endmacro
- The slower:

Code: Select all

#macro byte_reverse(long_variable)
   long_variable = ((long_variable) And &h000000FF) Shl 24 + _
                   ((long_variable) And &h0000FF00) Shl 08 + _
                   ((long_variable) And &h00FF0000) Shr 08 + _
                   ((long_variable) And &hFF000000) Shr 24
#endmacro
- Between the two previous ones:

Code: Select all

#macro byte_reverse(long_variable)
   Swap Cptr(Byte Ptr, @(long_variable))[0], Cptr(Byte Ptr, @(long_variable))[3]
   Swap Cptr(Byte Ptr, @(long_variable))[1], Cptr(Byte Ptr, @(long_variable))[2]
#endmacro
Post Reply