Windows [Solved!] How to get an integer from a buffer at correct position

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
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:
Code:
//This is objective C code
unsigned int width = OSReadBigInt32(buffer + 24 - 8);
unsigned int height = OSReadBigInt32(buffer + 24 - 4);
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:
Code:
Got file size: 257616
Width: 78
height: 80

Got file size: 97
Width: 78
height: 80
This is my code I'm using to get the file, put it in a buffer and analyse it:
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);
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
 
Last edited by a moderator:

Binsk

Member
The first thing that popped out is that you are reading one byte at a time from the file but writing it as a u32 (which is 4-bytes). Since you are reading a byte at a time this means it will take FOUR reads from the file to get a single integer.

In this case, just set the alignment of the buffer to 1 and write the whole buffer byte-by-byte.

The second thing that popped out to me is this: A buffer of only 24 bytes? Now, I don't know the PNG format specifications but there is no way you can fit a 512x512 image in only 24 bytes (equivalent to 6 integers).
 
W

Wraithious

Guest
The first thing that popped out is that you are reading one byte at a time from the file but writing it as a u32 (which is 4-bytes). Since you are reading a byte at a time this means it will take FOUR reads from the file to get a single integer.

In this case, just set the alignment of the buffer to 1 and write the whole buffer byte-by-byte.

The second thing that popped out to me is this: A buffer of only 24 bytes? Now, I don't know the PNG format specifications but there is no way you can fit a 512x512 image in only 24 bytes (equivalent to 6 integers).
Hi, thanks for your reply, The reason I made such a small buffer is because I only need to read the first 24 bytes of the file without having to waste computational time by loading the whole file unnecessarily. But I tried the 2 things you said and loaded the whole file into the analytics buffer and changed the alignment to 1 and got this result: (now reporting 0 width and 0 height)
Code:
Got file size: 257616
Width: 0
height: 0
And also tried with keeping the alignment set to 4 and loading the whole file into the analytics buffer I get the same result, 0 width and 0 height.
The way .png file is set up is first the header is 8 bytes and must report
byte 1 = 137
byte 2= 80
byte 3=78
byte 4=71
byte 5=13
byte 6=10
byte 7=26
byte 8=10
if those numbers are not correct it is not a valid .png file. from checking them they are correct.
Next after the header is the IHDR chunk that contains the .png file's information which is, to quote the so post linked above,
"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."
 

Ido-f

Member
Code:
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)));
You're putting buffer_seek at the end of the buffer and then you try to offset it further.
From the manual on buffer_seek:
  • You can use negative values for the offset to seek back through the buffer as well as positive values.
  • If the buffer is of the "wrap" type and you offset past the end of the buffer, the seek position will also wrap.
  • If the buffer is not of the "wrap" type, the seek will clamp to the beginning or end of the buffer, even when the offset would take the seek outside of the buffer limits.
So you're starting to read from the end of the buffer.
Either change it to buffer_seek_start or change the offset, the third argument, to -8 and -4.
 
W

Wraithious

Guest
You're putting buffer_seek at the end of the buffer and then you try to offset it further.
From the manual on buffer_seek:
  • You can use negative values for the offset to seek back through the buffer as well as positive values.
  • If the buffer is of the "wrap" type and you offset past the end of the buffer, the seek position will also wrap.
  • If the buffer is not of the "wrap" type, the seek will clamp to the beginning or end of the buffer, even when the offset would take the seek outside of the buffer limits.
So you're starting to read from the end of the buffer.
Either change it to buffer_seek_start or change the offset, the third argument, to -8 and -4.
Ok, so I chaanged my code to this:
Code:
buffer_seek(buff2 , buffer_seek_start , -8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_start , -4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
and got this result,
Code:
Got file size: 257616
Width: 137
height: 137
which is closer, and at least the 2 values are the same, but the image is 512x512 so something still isn't right
 
Last edited by a moderator:

Ido-f

Member
You changed both arguments, I meant you should change only one of them.
Code:
buffer_seek(buff2 , buffer_seek_end , -8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , -4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
or
Code:
buffer_seek(buff2 , buffer_seek_start , 24-8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_start , 24-4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek 2nd argument puts the read position at the start, end, or where it was before, then the 3rd argument advances that position by the offset value provided. So in your last message you put the reading position at the start of the buffer, then tried to advance it by -4 and -8, which kept it clamped at the start of the buffer.
 
W

Wraithious

Guest
You changed both arguments, I meant you should change only one of them.
Code:
buffer_seek(buff2 , buffer_seek_end , -8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , -4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
or
Code:
buffer_seek(buff2 , buffer_seek_start , 24-8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_start , 24-4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek 2nd argument puts the read position at the start, end, or where it was before, then the 3rd argument advances that position by the offset value provided. So in your last message you put the reading position at the start of the buffer, then tried to advance it by -4 and -8, which kept it clamped at the start of the buffer.
hmmm, your first code gives this error:
Code:
############################################################################################
ERROR in
action number 1
of  Step Event0
for object obj_test:

Attempting to read from outside the buffer, returning 0
 at gml_Script_imageBuffer (line 30) - show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_imageBuffer (line 30)
called from - gml_Object_obj_test_StepNormalEvent_1 (line 1) - if candraw=0 && mouse_check_button_pressed(mb_left) imageBuffer();
and your second code gives these results:
Code:
Got file size: 257616
Width: 13
height: 10
So I'm at a total loss why this isn't working...

This is my complete script called imageBuffer() ;
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(filesize, buffer_fixed, 1);
    for(var i=0;i<filesize;i++;){
        buffer_write(buff2, buffer_u32, file_bin_read_byte(file));
      //if i <25*32 show_debug_message("byte "+string(i)+": "+ string(file_bin_read_byte(file)));   
   }
/*
buffer_seek(buff2 , buffer_seek_end , 24 ) ;
show_debug_message("identity1: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 23 ) ;
show_debug_message("identity2: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 22 ) ;
show_debug_message("identity3: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 21 ) ;
show_debug_message("identity4: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 20 ) ;
show_debug_message("identity5: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 19 ) ;
show_debug_message("identity6: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 18 ) ;
show_debug_message("identity7: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_end , 17 ) ;
show_debug_message("identity8: " + string(buffer_read(buff2 , buffer_u32)));
*/
buffer_seek(buff2 , buffer_seek_start , 24-8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_start , 24-4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
file_bin_close(file);
buffer_delete(buff2);
pic1 = sprite_add(fname,1,0,0,0,0);
wd = sprite_get_width(pic1);
ht = sprite_get_height(pic1);
//draw selected image on surface
s0 = surface_create(wd,ht);
surface_set_target(s0);
draw_sprite(pic1,0,0,0);
surface_reset_target();
if sprite_exists(pic1) sprite_delete(pic1);
// surface_buffer_write
    bf = buffer_create( wd * ht * 4 , buffer_fixed , 4 ) ;
//get previously created surface image
buffer_get_surface( bf , s0 , 0 , 0 , 0 ) ;
surface_free(s0);
//get the size of the surface, resize +16 to add the width and height to
//the end of the buffer
buffer_seek( bf , buffer_seek_end , 0 ) ;
buffer_resize( bf , buffer_get_size( bf ) + 16 ) ;
buffer_write( bf , buffer_u64 , wd ) ;
buffer_write( bf , buffer_u64 , ht ) ;
// surface_buffer_read( buffer , [dataControl] ) ;
var sz = buffer_get_size( bf ) ;
// read buffer to get surface size we saved in the buffer earlier
// and create a surface
buffer_seek( bf , buffer_seek_end , 16 ) ;
var ww = buffer_read( bf , buffer_u64 ) ,
    hh = buffer_read( bf , buffer_u64 ) ;
    s1 = surface_create( ww , hh ) ;
// revert buffer size to actual size (remove width and height data)
buffer_resize( bf , sz - 16 ) ;
buffer_set_surface( bf , s1 , 0 , 0 , 0 ) ;
buffer_delete( bf );
candraw=1;
text="Click image to delete, click#outside image to load new image#If no image is loaded, click #anywhere to load an image.";
}
 
Last edited by a moderator:

Ido-f

Member
I don't know why the first code throws an error, but for sure it wouldn't work when you've made the buffer contain the whole file - buffer_seek_end goes to the end of the buffer, which previously was just the metadata. With your updated code it goes to the end of the file - so setting it 4 and 8 bytes back still wouldn't get it to the correct index for the meta data.

About the second code. The result it gets you are the 5th and 6th values described in your original post to be the first in every png file.
The mix-up comes, I think, from each number actually being 4 bytes. So (24-4) for example gets you to the 6th number ((24-4)/4=5 plus 1 because starting at 0)
You need the 9th and 10th numbers, so please try -
Code:
buffer_seek(buff2 , buffer_seek_start , 40-8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_start , 40-4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
 
Last edited:
W

Wraithious

Guest
I don't know why the first code throws an error, but for sure it wouldn't work when you've made the buffer contain the whole file - buffer_seek_end goes to the end of the buffer, which previously was just the metadata. With your updated code it goes to the end of the file - so setting it 4 and 8 bytes back still wouldn't get it to the correct index for the meta data.

About the second code. The result it gets you are the 5th and 6th values described in your original post to be the first in every png file.
The mix-up comes, I think, from each number actually being 4 bytes. So (24-4) for example gets you to the 6th number ((24-4)/4=5 plus 1 because starting at 0)
You need the 9th and 10th numbers, so please try -
Code:
buffer_seek(buff2 , buffer_seek_start , 40-8 ) ;
show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
buffer_seek(buff2 , buffer_seek_start , 40-4 ) ;
show_debug_message("height: " + string(buffer_read(buff2 , buffer_u32)));
width and height reported as 0 :(
Code:
Got file size: 257616
Width: 0
height: 0
The only reason I have the buffer as the whole file size was due to @Binsk suggestion, originally I had set the analytics buffer to size 24 like the stack overflow post instructed.
 

Ido-f

Member
Welp.
Reading the stack overflow thread again I think there are more numbers after the first 8 at every .png and before the width+height.
four bytes representing the length of the chunk's data field, then the four bytes representing the chunk's name
I'm having a hard time understanding what the length of these are.
If I were you I'd just start throwing numbers at it until you've found the width and height.
I suggest you try 40, 44, 48, etc.

Edit: Okay I understood something. At the loop in which you write the bytes to the buffer you write them as buffer_u32 - which actually take 4 bytes each - while originally the first 8 numbers are stored 1 byte each.
So the resultign buffer looks like this (each [] represents a byte)

[137] [0] [0] [0] [80] [0] [0] [0] [78] [0] [0] [0] [71] [0] [0] [0] [13] [0] [0] [0] [10] [0] [0] [0] [26] [0] [0] [0] [10] [0] [0] [0] [length of the chunk's data field - 4 bytes] [chunk's name - 4 bytes] [width - 4 bytes] [ height - 4 bytes]
Which is why 24-8,24-4 got 13 and 10 earlier.
I don't think changing it to buffer_u8 would be good - some of these are supposed to be buffer_u32.
I think you can do buffer2 = buffer_load(filename); instead of the loop to get the chucks copied correctly, and then buffer_seek(buff2, buffer_seek_start, 24-8) might work.
 
Last edited:
W

Wraithious

Guest
Welp.
Reading the stack overflow thread again I think there are more numbers after the first 8 at every .png and before the width+height.

I'm having a hard time understanding what the length of these are.
If I were you I'd just start throwing numbers at it until you've found the width and height.
I suggest you try 40, 44, 48, etc.

Edit: Okay I understood something. At the loop in which you write the bytes to the buffer you write them as buffer_u32 - which actually take 4 bytes each.
Which is why 24-4,24-8 got the wrong results earlier.
Ok I'll keep trying, Here is the official .png file structure docs if they may help, page 1, and page 2
with this being important info from page 1:
A PNG file consists of a PNG signature followed by a series of chunks. This chapter defines the signature and the basic properties of chunks. Individual chunk types are discussed in the next chapter.
3.1. PNG file signature
The first eight bytes of a PNG file always contain the following (decimal) values:
137 80 78 71 13 10 26 10
This signature indicates that the remainder of the file contains a single PNG image, consisting of a series of chunks beginning with an IHDR chunk and ending with an IEND chunk.

And this being important info from page 2:
4.1. Critical chunks
All implementations must understand and successfully render the standard critical chunks. A valid PNG image must contain an IHDR chunk, one or more IDAT chunks, and an IEND chunk.
4.1.1. IHDR Image header
The IHDR chunk must appear FIRST. It contains:
Width: 4 bytes
Height: 4 bytes
Bit depth: 1 byte
Color type: 1 byte
Compression method: 1 byte
Filter method: 1 byte
Interlace method: 1 byte

Width and height give the image dimensions in pixels. They are 4-byte integers. Zero is an invalid value. The maximum for each is (2^31)-1 in order to accommodate languages that have difficulty with unsigned 4-byte values.

So if I do this to check 24 bytes at the beginning of the file:
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(filesize, buffer_fixed, 4);
    for(var i=0;i<25;i++;){
        buffer_write(buff2, buffer_u32, file_bin_read_byte(file));
   }

    file_bin_close(file);
    file = file_bin_open(fname, 0);
    for(var i=0;i<25;i++;){
        show_debug_message("byte "+string(i)+": "+ string(file_bin_read_byte(file)));  
   }
}
I get these results:
Code:
Got file size: 257616
byte 0: 137
byte 1: 80
byte 2: 78
byte 3: 71
byte 4: 13
byte 5: 10
byte 6: 26
byte 7: 10
byte 8: 0
byte 9: 0
byte 10: 0
byte 11: 13
byte 12: 73
byte 13: 72
byte 14: 68
byte 15: 82
byte 16: 0
byte 17: 0
byte 18: 2
byte 19: 0
byte 20: 0
byte 21: 0
byte 22: 2
byte 23: 0
byte 24: 8
Width: 0
height: 0
 
Last edited by a moderator:
W

Wraithious

Guest
Welp.
Reading the stack overflow thread again I think there are more numbers after the first 8 at every .png and before the width+height.

I'm having a hard time understanding what the length of these are.
If I were you I'd just start throwing numbers at it until you've found the width and height.
I suggest you try 40, 44, 48, etc.

Edit: Okay I understood something. At the loop in which you write the bytes to the buffer you write them as buffer_u32 - which actually take 4 bytes each - while originally the first 8 numbers are stored 1 byte each.
So the resultign buffer looks like this (each [] represents a byte)



Which is why 24-8,24-4 got 13 and 10 earlier.
I don't think changing it to buffer_u8 would be good - some of these are supposed to be buffer_u32.
I think you can do buffer2 = buffer_load(filename); instead of the loop to get the chucks copied correctly, and then buffer_seek(buff2, buffer_seek_start, 24-8) might work.
Ok just saw your edit, ill try that, im thinking each time you do a seperate read operation you increment the current buffer position so it definatly has something to do with that. I'll edit this post with the results
 
W

Wraithious

Guest
@Ido-f Well this is interesting, I changed over to just loading the images in buffer 2 like you sugested:
Code:
    var buff2 = buffer_load(fname);
       for(var i=0;i<25;i+=1;){
           buffer_seek(buff2 , buffer_seek_start , i ) ;
           show_debug_message("byte "+string(i)+": "+ string(buffer_read(buff2 , buffer_u32))); 
   }
and tried 2 different images, one 1024 x 768, and one 512 x 512, I'm getting the width correctly but the height is off by +8 in each case, here's the results:
512 X 512:
Code:
Got file size: 257616
byte 17: 512
byte 18: 2
byte 19: 33554432
byte 20: 131072
byte 21: 134218240
byte 22: 34078722
byte 23: 133120
byte 24: 520
1024x 768:
Code:
Got file size: 677517
byte 17: 1024
byte 18: 4
byte 19: 50331648
byte 20: 196608
byte 21: 134218496
byte 22: 50855939
byte 23: 198656
byte 24: 776
but oddly if I load a 10 x 10 image I get this weirdo result:
Code:
Got file size: 101
byte 17: 458752
byte 18: 1792
byte 19: 7
byte 20: 117440512
byte 21: 134676480
byte 22: 101189376
byte 23: 395271
byte 24: 1544
Edit: and if I load a 2048 x 2048 the width is still correct but the value I thought was the height (position 24 from my show_message loop) is an irrelevant number now
Code:
Got file size: 3532237
byte 17: 2048
byte 18: 8
byte 19: 134217728
byte 20: 524288
byte 21: 134219776
byte 22: 50855944
byte 23: 198656
byte 24: 776
 
Last edited by a moderator:

TheouAegis

Member
I get these results:
Code:
Got file size: 257616
byte 0: 137
byte 1: 80
byte 2: 78
byte 3: 71
byte 4: 13
byte 5: 10
byte 6: 26
byte 7: 10
byte 8: 0
byte 9: 0
byte 10: 0
byte 11: 13
byte 12: 73
byte 13: 72
byte 14: 68
byte 15: 82
byte 16: 0
byte 17: 0
byte 18: 2
byte 19: 0
byte 20: 0
byte 21: 0
byte 22: 2
byte 23: 0
byte 24: 8
Width: 0
height: 0
16 thru 19 and 20 thru 23 are your width and height.

$00000200 is 512


Bytes 8 thru 11 are the section size, bytes 12 thru 15 are the section name.


I hate working with PNG files. And I'm pissed that GMS2 decided to remove GIF functionality. GM8 had adequately fast GIF support and I could do a lot with it. With PNGs you have to mess with compression algorithms.

GIF-based palette swapping in GM8:
https://www.dropbox.com/s/5f9tenbv1340703/Pal-Swap Demo.zip
 
Last edited:
W

Wraithious

Guest
16 thru 19 and 20 thru 23 are your width and height.

$00000200 is 512


Bytes 8 thru 11 are the section size, bytes 12 thru 15 are the section name.


I hate working with PNG files. And I'm pissed that GMS2 decided to remove GIF functionality. GM8 had adequately fast GIF support and I could do a lot with it. With PNGs you have to mess with compression algorithms.
ahh, so it's coded in those 4 numbers of width and 4 for height, what is the formula you used to get the actual number (512 in this case) out of that? is it some sort of bitwize math that needs to go on there?
I hear you about the gif issue, they never fixed the import at runtime issue in gms 1.x so I guess they gave up on it :(
as for the compression algorythims That will be my next battle, I need to be able to chunk huge images into smaller ones that will load into gamemaker so figuring this "little" delemma out should teach me how to deal with the data I'm looking at, then I'll have to write a header for each chunk, + the beginning and end blocks and put the chunked data in between, and when I read that png doc it leads me to believe the data blocks are semi-randomly placed :(
 

TheouAegis

Member
If your documentation is right, based on the results I quoted from you, all you need to do is import the file into the buffer, seek to position 16, set width to a u32 read, then set height to a u32 read (no seek). At least I think it's width then height. Might be height then width, I haven't messed with it in a long time.

Otherwise if you have to read one byte at a time it's probably

width= 0;
repeat 4 {
width *= 256;
width += buffer_read_byte(buff, buffer_u8);
}

Or something like that.
 
Last edited:
W

Wraithious

Guest
If your documentation is right, based on the results I quoted from you, all you need to do is import the file into the buffer, seek to position 16, set width to a u32 read, then set height to a u32 read (no seek). At least I think it's width then height. Might be height then width, I haven't messed with it in a long time.

Otherwise if you have to read one byte at a team it's probably

width= 0;
repeat 4 {
width *= 256;
width += buffer_read_byte(buff, buffer_u8);
}

Or something like that.
ahh ok thank you very much, I will mess around with those ideas and see how it goes :)
 
W

Wraithious

Guest
@TheouAegis You're a genius! just a little tweaking worked perfectly! I had to seek to position 17, read as u32, then read again as u16, BAM perfect.
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_load(fname);

    buffer_seek(buff2 , buffer_seek_start , 17 ) ;
    show_debug_message("Width: " + string(buffer_read(buff2 , buffer_u32)));
    show_debug_message("height: " + string(buffer_read(buff2 , buffer_u16)));

    file_bin_close(file);
    buffer_delete(buff2);
}
results with 2 different files:
Code:
Got file size: 257616
Width: 512
height: 512

Got file size: 677517
Width: 1024
height: 768
 

TheouAegis

Member
Whenever you mess with file data, get yourself a hex editor (there are websites if you don't want to download anything). Any decent hex editor will display the bytes on the left and a "text" conversion on the right. Nearly all data headers use the same byte-to-text conversion, so you can see in the text data any notable strings. For example, 504EE7 (bytes 1, 2 and 3) are "PNG", 49484452 (bytes 12, 13, 14 and 15) are "IHDR", short for Image Header.
 
W

Wraithious

Guest
Whenever you mess with file data, get yourself a hex editor (there are websites if you don't want to download anything). Any decent hex editor will display the bytes on the left and a "text" conversion on the right. Nearly all data headers use the same byte-to-text conversion, so you can see in the text data any notable strings. For example, 504EE7 (bytes 1, 2 and 3) are "PNG", 49484452 (bytes 12, 13, 14 and 15) are "IHDR", short for Image Header.
Thanks, good advice, I do have one called codeblocks, looks like it's time to learn how to use it
 

TheouAegis

Member
One last tip. Nearly all file formats use the same style. You have either the size of the data (typically 4 bytes) in the section including the section name before the section name, or the size of the data in the section NOT including the section name after the section name (uncommon). this is the same structure that they use in GIF files, PNG files, even the data files on Nintendo DS games.
 
Top