Reading 16-bit raw data

Discussion in 'C++' started by junk5@microserf.org.uk, Dec 15, 2005.

  1. Guest

    Hi

    I need to read raw 16 bit data from a file, where the first byte is the
    most significant byte of the first data value and the second byte is
    the least significant byte of the first data value (the next pair or
    bytes and the next etc. specify the second and third values).

    For example, if I had a file containing

    0xff22
    0xfe23
    0x11ff
    0x1000

    then the two values I should read back would be:

    0x01002023
    and
    0x00120F00

    I wrote the following code snippet which I thought would read the data:

    // The input and output variables are ifstream and ofstream objects
    respectively.
    char currentByte[1]; // A buffer for reading the file.
    unsigned int thisValue;
    bool oddByte = true; // The first byte is odd-numbered, the second is
    even-numbered, etc.
    while(input->good()) // While we can extract data from the input
    file.
    {
    // Get the next byte, and write the next value if the byte read
    is an even byte.
    input->read(currentByte, 1); // Probably inefficient, but I'll
    speed things up later.
    if(oddByte)
    {
    thisValue = (unsigned int)(*currentByte); // Most significant byte.
    *output << "No mult.: thisValue is: " << thisValue << std::endl; //
    Debug noise.

    thisPixel *= 256; // Equiv. to leftshift by 8 places.
    *output << "Current thisValue is: " << thisVaule << std::endl; //
    Debugg noise.
    }
    else
    {
    thisValue += (unsigned int)(*currentByte); // Least significant
    byte.
    *output << "Current thisValue is: " << thisValue << std::endl; //
    Debug noise.
    *output << thisValue << " "; // Write out the computed value
    in decimal.
    }

    // Invert oddByte.
    oddByte = !oddByte;
    }

    If the above is a bit impenetrable, here's my thinking: each value in
    the file is represented by two bytes, an odd byte (the MSB) and an even
    byte (the LSB). oddByte is inverted after every read. If we just read a
    MSB, then we need to left-shift the bits read by 8 binary places (I do
    a multiply by 256 above, but it's the same thing). If we just read a
    LSB, then we need to add this onto the result of doing the left-shift
    by 8. After adding the LSB I write out the value to an output stream
    (the other writes are just for debugging purposes).

    I compile the above using gcc -Wall and it compiles cleanly. The code
    runs OK, but I don't get out what I expect; instead I get values like:

    4294967229
    4294950144
    4294950263
    4294967241
    4294953216
    4294953122

    which are far too big to have come from 16-bit values. (They look like
    pointer addresses to me.)

    It's been a long while since I've needed to do any bit-twiddling (or
    used C++ in anger). Which bit of basic C/C++ have I forgotten?

    Thanks,

    C
     
    , Dec 15, 2005
    #1
    1. Advertising

  2. wrote:
    > [..]
    > I compile the above using gcc -Wall and it compiles cleanly. The code
    > runs OK, but I don't get out what I expect; instead I get values like:
    >
    > 4294967229
    > 4294950144
    > 4294950263
    > 4294967241
    > 4294953216
    > 4294953122


    Display them in hex.

    > which are far too big to have come from 16-bit values. (They look like
    > pointer addresses to me.)


    They are just large numbers (0xffff....).

    > It's been a long while since I've needed to do any bit-twiddling (or
    > used C++ in anger). Which bit of basic C/C++ have I forgotten?



    Perhaps you need to have your "currentbyte" as _unsigned_char_...

    V
     
    Victor Bazarov, Dec 15, 2005
    #2
    1. Advertising

  3. Guest

    wrote:

    > thisValue = (unsigned int)(*currentByte); // Most significant byte.
    > *output << "No mult.: thisValue is: " << thisValue << std::endl; //
    > Debug noise.


    It's the conversion - try instead:

    thisValue = (unsigned int)(*currentByte & 0xff)
    , and it' will work.

    /Patrick
     
    , Dec 15, 2005
    #3
  4. On 15 Dec 2005 13:14:24 -0800, wrote:

    >
    > wrote:
    >
    >> thisValue = (unsigned int)(*currentByte); // Most significant byte.
    >> *output << "No mult.: thisValue is: " << thisValue << std::endl; //
    >> Debug noise.

    >
    >It's the conversion - try instead:
    >
    >thisValue = (unsigned int)(*currentByte & 0xff)
    >, and it' will work.


    Don't you mean:

    thisValue = ((unsigned int)(*currentByte)) & 0xff;

    ??

    --
    Bob Hairgrove
     
    Bob Hairgrove, Dec 15, 2005
    #4
  5. Guest

    Hi all, and thanks for your responses.

    A few minutes after posting I tried using the "int get()" function
    instead of the "get(char*)" version, and things seem to work fine.

    C
     
    , Dec 15, 2005
    #5
  6. Kaz Kylheku Guest

    Bob Hairgrove wrote:
    > On 15 Dec 2005 13:14:24 -0800, wrote:
    >
    > >
    > > wrote:
    > >
    > >> thisValue = (unsigned int)(*currentByte); // Most significant byte.
    > >> *output << "No mult.: thisValue is: " << thisValue << std::endl; //
    > >> Debug noise.

    > >
    > >It's the conversion - try instead:
    > >
    > >thisValue = (unsigned int)(*currentByte & 0xff)
    > >, and it' will work.

    >
    > Don't you mean:
    >
    > thisValue = ((unsigned int)(*currentByte)) & 0xff;


    This is not necessary if currentByte were of type pointer to unsigned
    char, rather than plain char! Use unsigned char for binary data.

    An unsigned char will promote to signed int, or to unsigned int,
    depending on whichever will hold all values of its type, including
    sign.

    On most platforms, unsigned char will promote to int, because it's
    narrower, and so int can hold all unsigned char values.

    The only remaining issue then is that the & 0xFF may be done against a
    signed int zero value that doesn't have an all-bits-zero
    representation. Under sign-magnitude, you are okay, because a negative
    zero still has all-zero bits in the mantissa, but under one's
    complement, zero can be represented by a bit pattern of all 1's.
    Masking out the least significant 8 bits of that produces 255.

    But even on hardware that uses one's complement for signed integers, I
    wouldn't expect an unsigned char zero to promote to the negative flavor
    of zero! That zero would have to be the result of some arithmetic
    computation involving negative values.

    So basically, you are worried to portability to one's complement
    machines on which conversions are pathologically behaved.

    If hardware like that were designed to day, it wouldn't see the light
    of day. The reams of nonportable code that would not run on it would
    seal its fate in the marketplace. :)
     
    Kaz Kylheku, Dec 15, 2005
    #6
  7. Old Wolf Guest

    wrote:
    >
    > I need to read raw 16 bit data from a file, where the first byte is the
    > most significant byte of the first data value and the second byte is
    > the least significant byte of the first data value (the next pair or
    > bytes and the next etc. specify the second and third values).
    >
    > For example, if I had a file containing
    >
    > 0xff22


    Do you mean the file contains 0xFF followed by 0x22 ?

    > 0xfe23
    > 0x11ff
    > 0x1000
    >
    > then the two values I should read back would be:
    >
    > 0x01002023
    > and
    > 0x00120F00


    Does anyone else follow this? I haven't had my coffee today
     
    Old Wolf, Dec 16, 2005
    #7
  8. Guest

    Old Wolf wrote:
    > wrote:
    > >
    > > I need to read raw 16 bit data from a file, where the first byte is the
    > > most significant byte of the first data value and the second byte is
    > > the least significant byte of the first data value (the next pair or
    > > bytes and the next etc. specify the second and third values).
    > >
    > > For example, if I had a file containing
    > >
    > > 0xff22

    >
    > Do you mean the file contains 0xFF followed by 0x22 ?
    >
    > > 0xfe23
    > > 0x11ff
    > > 0x1000
    > >
    > > then the two values I should read back would be:
    > >
    > > 0x01002023
    > > and
    > > 0x00120F00

    >
    > Does anyone else follow this? I haven't had my coffee today


    You're right - it should of course be 0xff followed by 0x22. In his
    example he used 16bit numbers, shifted the first one 8 bits and added
    the next one.
    (0xff22 << 8) + 0xfe23 = 0x1002023
     
    , Dec 16, 2005
    #8
  9. Guest

    >>Do you mean the file contains 0xFF followed by 0x22 ?
    >> 0xfe23
    >> 0x11ff

    > 0x1000
    >
    >> then the two values I should read back would be:

    >
    >> 0x01002023
    >> and
    >> 0x00120F00

    >
    >Does anyone else follow this? I haven't had my coffee today


    Obviously neither had I! Sorry all---I was 'forgetting' that one hex
    digit was four bits, rather than two, but I hope the example served its
    purpose.
     
    , Dec 16, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    1,799
    Timothy Bendfelt
    Jan 19, 2007
  2. Replies:
    4
    Views:
    1,176
  3. Replies:
    9
    Views:
    1,006
    Juha Nieminen
    Aug 22, 2007
  4. harijay
    Replies:
    2
    Views:
    492
    Gabriel Genellina
    Feb 19, 2009
  5. Jeff.M
    Replies:
    6
    Views:
    186
    Lasse Reichstein Nielsen
    May 4, 2009
Loading...

Share This Page