Reputation: 1879
In the SEG-D seismic data format, some header parameters are formatted as three bytes, two’s complement, signed binary. All values are big-endian.
Using String#unpack, Ruby core can only convert 16-bit and 32-bit values, but not 24-bit.
How can I get the binary values converted into integers in the following two’s complement way:
"\x00\x00\x00" => 0x000000 (0)
"\x00\x00\x01" => 0x000001 (1)
"\x7F\xFF\xFF" => 0x7FFFFF (8388607)
"\xFF\xFF\xFF" => -0x000001 (-1)
"\x80\x00\x00" => -0x800000 (-8388608)
Upvotes: 1
Views: 740
Reputation: 1879
Convert the fist byte as signed 8-bit (two’s complement) and the second and third as unsigned 16-bit.
# String to be converted (-8388608)
bin = "\x80\x00\x00"
# Convert as signed 8-bit and unsigned 16-bit (big-endian)
values = bin.unpack("c S>")
# Add with the first byte weighted
converted = values[0] * 2**16 + values[1]
Alternate version of the last line using bitwise operations shift and OR (probably more efficient):
converted = values[0] << 16 | values[1]
Upvotes: 3