byte[] to ushort[]

Nick Tsui picture Nick Tsui · Feb 13, 2013 · Viewed 7.6k times · Source

Here is my question. Bear with me giving a little explanation:

I am reading tiff image into buffer; Each pixel of my tiff is represented by a ushort (16 bits data, non-negtive).

My image size is 64*64 = 4096. When my tiff is loaded into buffer, the buffer length is therefore 8192 (twice as much as 4096). I guess this is because in my buffer, the computer uses 2 bytes to store a single pixel value.

I want to get the value for any particular pixel, in this case should I combine every 2 bytes to 1 ushort?

For example: 00000000 11111111 -> 0000000011111111?

Here is my code:

public static void LoadTIFF(string fileName, int pxlIdx, ref int pxlValue)
        {
            using (Tiff image = Tiff.Open(fileName, "r"))
            {
                if (image == null)
                    return;

                FieldValue[] value = image.GetField(TiffTag.IMAGEWIDTH);
                int width = value[0].ToInt();

                byte[] buffer = new byte[image.StripSize()];
                for (int strip = 0; strip < image.NumberOfStrips(); strip++)
                    image.ReadEncodedStrip(strip, buffer, 0, -1);

                // do conversion here:
                //ushort bufferHex = BitConverter.ToUInt16(buffer, 0);            

                image.Close();

            }
        }

How do I read the byte[] buffer to ensure that I can get the 16 bits ushort pixel value?

Thanks

Answer

Eric J. picture Eric J. · Feb 13, 2013

Since each pixel is represented as 16 bits, it may be more convenient from a programming perspective to represent the byte[] as a ushort[] of half the length, but it is not required.

The best solution depends on how you want to consume the buffer.

You could just as easily define a helper method

ushort GetImageDataAtLocation(int x, int y) 
{ 
    offset = y * HEIGHT + x;
    return BitConverter.ToUInt16(buffer, offset);
}

that uses the input coordinates to determine the offset in the original byte[] and returns a ushort composed of the appropriate bytes.

If the TIFF stores data big-endian and your system is little-endian, you would have to reverse the order of the bytes prior to conversion. One way to do that is:

ushort GetImageDataAtLocation(int x, int y) 
{ 
    offset = y * HEIGHT + x;
    // Switch endianness e.g. TIFF is big-endian, host system is little-endian
    ushort result = ((ushort)buffer[0]) << 8 + buffer[1];
    return result;
}

If your code might ever run on platforms with different endianness (Intel and AMD are both little-endian) you can determine the endianness at runtime using

BitConverter.IsLittleEndian

For details on BitConverter, see http://msdn.microsoft.com/en-us/library/system.bitconverter.touint16.aspx