【问题标题】:byte[] to ushort[]字节[] 到 ushort[]
【发布时间】:2013-01-29 04:55:32
【问题描述】:

这是我的问题。请耐心解释一下:

我正在将 tiff 图像读入缓冲区;我的 tiff 的每个像素都由一个 ushort 表示(16 位数据,非负数)。

我的图像大小是 64*64 = 4096。当我的 tiff 加载到缓冲区时,缓冲区长度因此为 8192(是 4096 的两倍)。我猜这是因为在我的缓冲区中,计算机使用 2 个字节来存储单个像素值。

我想获取任何特定像素的值,在这种情况下,我应该将每 2 个字节组合成 1 个 ushort 吗?

例如:00000000 11111111 -> 0000000011111111?

这是我的代码:

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();

            }
        }

如何读取 byte[] 缓冲区以确保可以获得 16 位 ushort 像素值?

谢谢

【问题讨论】:

    标签: c# bytebuffer data-conversion ushort


    【解决方案1】:

    由于每个像素都表示为 16 位,因此从编程的角度来看,将byte[] 表示为一半长度的ushort[] 可能更方便,但这不是必需的。

    最佳解决方案取决于您希望如何使用缓冲区。

    你可以很容易地定义一个辅助方法

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

    使用输入坐标确定原始byte[] 中的偏移量并返回由适当字节组成的ushort

    如果 TIFF 存储数据大端且您的系统是小端,则必须在转换之前反转字节顺序。一种方法是:

    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;
    }
    

    如果您的代码可能曾经在具有不同字节序的平台上运行(Intel 和 AMD 都是小字节序),您可以在运行时使用来确定字节序

    BitConverter.IsLittleEndian

    BitConverter 详情请见http://msdn.microsoft.com/en-us/library/system.bitconverter.touint16.aspx

    【讨论】:

    • 虽然偏移量似乎是 2 的乘积,而 y 实际上是 (y-1),x 也是如此。那么取决于基于 0 或基于 1 的索引。
    【解决方案2】:

    您需要循环执行:BitConverter.ToUInt16() 占用 2 个字节,将它们转换为一个 ushort。

    警告:正如 Eric 指出的那样,它存在字节顺序问题(它总是假定它正在执行的平台的字节顺序)。仅当您确定源字节流是在具有相同字节顺序的机器上生成时才使用 Bitconverter(对于 TIFF 图像,您可能无法假设它)。

    你可以使用一些 LINQ...例如有一个很好的Chuncks 函数here。您可以将其用作:

    rawBytes.Chunks(2).Select(b => BitConverter.ToUInt16(b)).toArray()
    

    【讨论】:

    • 不,它没有......它无法隐式知道 TIFF 是存储数据大端还是小端。它只是假设数据与在The order of bytes in the array must reflect the endianness of the computer system's architecturemsdn.microsoft.com/en-us/library/…上运行的平台.NET 的字节顺序相同。
    • @EricJ。哦,你是对的......我一直忘记它,我曾经在 TIFF 图像上工作......我编辑了我的答案,并赞成你的答案,因为它更完整
    • @EricJ。我会在生产中使用它之前对其进行测量。不过,在某些情况下,IEnumerable 的优化程度让我经常感到惊讶。特别是如果您将它用于类似流的处理。它有 PLINQ。很高兴阅读:)
    • 对于我遇到的几乎所有用例,与传统替代方案相比,Linq 的速度都非常快(通常会慢一些,但对整个用例而言并不重要)。我怀疑图像处理就是这种情况:-)
    • 嗯....坏消息我必须做一个双循环,但这绝对是有用的信息。谢谢!
    猜你喜欢
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    相关资源
    最近更新 更多