W
Wraithious
Guest
Hello, I am trying to get the image width and height from a .png file IHDR chunk inside a buffer so I can make the correct sized surface to write my buffer to. I have followed (converted) this stack overflow post's advice
but i am getting the wrong values from it, in fact I loaded a 512 x 512 image and a 10 x 10 image and they both gave the same results in my compile window of 78 x 80:
This is my code I'm using to get the file, put it in a buffer and analyse it:
So I've created a buffer with a size of 24 bytes,
I've used an alignment of 4 because that's what gamemaker says to use with 32 bit unsigned integers, and I've set my read offset to 16 and 20 the way the so post said to do it, and I'm assuming gamemaker buffers of this type are of big endian type? (big number in the byte first then smaller after)
So where am I going wrong here? I've tried changing the offset and found I get different results but none of them are close to being correct, please help if you can, thanks
The first eight bytes of a PNG file always contain the following (decimal) values: 137 80 78 71 13 10 26 10
So you have to read those to make sure you really have a PNG file.
Then,
The IHDR chunk must appear FIRST. It contains:
Width: 4 bytes
Height: 4 bytes
So according to the structure of chunks, you first have to read the four bytes representing the length of the chunk's data field, then the four bytes representing the chunk's name, then the two 32-bit integers representing width and height, eight bytes in total.
So, the exact minimal number of bytes you must read in order to determine width and height is 8 + 4 + 4 + 8 = 24 bytes.
Width and height can be accessed as big-endian encoded unsigned ints at offset 24 minus 8 and minus 4 bytes respectively:
So you have to read those to make sure you really have a PNG file.
Then,
The IHDR chunk must appear FIRST. It contains:
Width: 4 bytes
Height: 4 bytes
So according to the structure of chunks, you first have to read the four bytes representing the length of the chunk's data field, then the four bytes representing the chunk's name, then the two 32-bit integers representing width and height, eight bytes in total.
So, the exact minimal number of bytes you must read in order to determine width and height is 8 + 4 + 4 + 8 = 24 bytes.
Width and height can be accessed as big-endian encoded unsigned ints at offset 24 minus 8 and minus 4 bytes respectively:
Code:
//This is objective C code
unsigned int width = OSReadBigInt32(buffer + 24 - 8);
unsigned int height = OSReadBigInt32(buffer + 24 - 4);
Code:
Got file size: 257616
Width: 78
height: 80
Got file size: 97
Width: 78
height: 80
Code:
fname = get_open_filename("Image file|*.png;*.jpg;*.gif;*.tif", "");// get the requested image's address
if(fname !="") {
file = file_bin_open(fname, 0);
filesize = file_bin_size(file);//get the file size of the image
show_debug_message("Got file size: "+string(filesize));
var buff2 = buffer_create(24, buffer_fixed, 4);
for(var i=0;i<24;i++;){
buffer_write(buff2, buffer_u32, file_bin_read_byte(file));
}
buffer_seek(buff2 , buffer_seek_end , 24-8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 24-4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
file_bin_close(file);
buffer_delete(buff2);
I've used an alignment of 4 because that's what gamemaker says to use with 32 bit unsigned integers, and I've set my read offset to 16 and 20 the way the so post said to do it, and I'm assuming gamemaker buffers of this type are of big endian type? (big number in the byte first then smaller after)
So where am I going wrong here? I've tried changing the offset and found I get different results but none of them are close to being correct, please help if you can, thanks
Last edited by a moderator: