Sunday, December 21, 2008

Reading Visual Basic Binary encoding for screen coordinates

Reading Visual Basic Binary encoding for screen positions, X and y.



This is a slight departure from Ajax-related topics, but since I've been heavily involved with transforming older binary files to modern XML, there was one challenge that took some unexpected calculating that I want to document here.



The older binary files were created by Visual Basic 6, apparently it writes the screen coordinate positions in big endian formats.



In my binary files, I knew these eight bytes contain the screen position and size of a block. Another way to describe this would be a the top left corner and lower right corner, the coordinates (x1, y1) and (x2, y2).



Here are some bytes that describe 4 boxes in a row, with varying widths, but all with the same height,effectively making a table.



4 rows of 8 bytes in hex code format:



00 8C 00 08 01 31 00 69

00 8C 00 69 01 31 00 C5

00 8C 01 C4 01 31 02 7F

00 8C 02 7F 01 31 03 16







In each row, the first two bytes are x1. Next two are y1. Then x2, and last is y2. Little endian doesn't work, the numbers get too big. Using big endian:



ypos1, xpos1, ypos2, xpos2



140, 8, 305, 105

140, 105, 305, 453

140, 452, 305, 639

140, 639, 305, 790





Since we know the y values are the same, column 1 would be y1 and column 3 would be y2.

This would leave column 2 as x1 and column 4 as x2. This works since each row starts where the previous row left off. Note that to find the width, just subtract xpos1 from xpos2 and to find the height, subtract ypos1 from ypos2.



The only reason this was any problem, is that the Intel machines are little endian, the built-in readUint16() gave results that were way too high to be screen positions. Therefore, an extra processing function was needed to make the calculation.



Here is an example from the internet (devx.com) showing a conversion between little endian and big endian.





int SHORT_little_endian_TO_big_endian(int i)

{

return ((i>>8)&0xff)+((i << 8)&0xff00);

}






Here was my own coded solution that reads one byte at a time while parsing through the binary file:



highb = inf.ReadByte()

lowb = inf.ReadByte()

highb = (highb * &H100&)

ypos1 = highb + lowb

No comments: