سؤال

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

هل كانت مفيدة؟

المحلول

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

نصائح أخرى

You need to do it in a loop: BitConverter.ToUInt16() takes 2 bytes, convert them to one ushort.

WARNING: as Eric pointed out, it has endianness problems (it always assumes endianness of the platform on which it is executing). Use Bitconverter only if you are sure the source byte stream is produced on a machine with the same endianness (in case of TIFF images, you probably cannot assume it).

You may use some LINQ... for example there is a nice Chuncks function here. You may use it as:

rawBytes.Chunks(2).Select(b => BitConverter.ToUInt16(b)).toArray()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top