2013-02-13 26 views
9

Đây là câu hỏi của tôi. Hãy cùng tôi giải thích một chút:byte [] để ushort []

Tôi đang đọc hình ảnh tiff vào bộ đệm; Mỗi điểm ảnh của tiff của tôi được đại diện bởi một ushort (16 bit dữ liệu, không tiêu cực).

Kích thước hình ảnh của tôi là 64 * 64 = 4096. Khi tiff của tôi được tải vào bộ đệm, độ dài bộ đệm là 8192 (gấp đôi 4096). Tôi đoán điều này là bởi vì trong bộ đệm của tôi, máy tính sử dụng 2 byte để lưu trữ một giá trị pixel duy nhất.

Tôi muốn nhận được giá trị cho bất kỳ pixel cụ thể nào, trong trường hợp này, tôi nên kết hợp mỗi 2 byte thành 1 ushort?

Ví dụ: 00000000 11111111 -> 0000000011111111?

Đây là mã của tôi:

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

      } 
     } 

Làm thế nào để đọc các byte [] đệm để đảm bảo rằng tôi có thể nhận được 16 bit ushort giá trị pixel?

Cảm ơn

Trả lời

4

Do mỗi pixel được biểu diễn dưới dạng 16 bit, nó có thể là thuận tiện hơn từ góc độ lập trình để đại diện cho byte[] như một ushort[] của một nửa chiều dài, nhưng nó không phải là bắt buộc.

Giải pháp tốt nhất phụ thuộc vào cách bạn muốn tiêu thụ bộ đệm.

Bạn có thể chỉ là một cách dễ dàng xác định một phương pháp helper

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

sử dụng đầu vào tọa độ để xác định bù đắp trong bản gốc byte[] và trả về một ushort gồm các byte thích hợp.

Nếu TIFF lưu trữ dữ liệu lớn về cuối và hệ thống của bạn là nhỏ gọn, bạn sẽ phải đảo ngược thứ tự của các byte trước khi chuyển đổi. Một cách để làm điều đó là:

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

Nếu mã của bạn bao giờ có thể chạy trên nền tảng với endianness khác nhau (Intel và AMD đều ít về cuối nhỏ), bạn có thể xác định endianness khi chạy bằng

BitConverter.IsLittleEndian

để biết chi tiết về BitConverter, xem http://msdn.microsoft.com/en-us/library/system.bitconverter.touint16.aspx

+0

Yup, tôi nghĩ mình có điểm ảnh mình muốn. Cảm ơn nhiều! –

+0

Mặc dù bù trừ dường như nhân 2, và y thực sự là (y-1), và tương tự cho x. Cũng tùy thuộc vào chỉ số dựa trên 0 hoặc 1. –

1

Bạn cần phải làm điều đó trong một vòng lặp: BitConverter.ToUInt16() mất 2 byte, chuyển đổi chúng sang một ushort.

CẢNH BÁO: như Eric đã chỉ ra, nó có vấn đề về tính cuối cùng (nó luôn luôn giả định tính xác thực của nền tảng mà nó đang thực thi). Chỉ sử dụng Bitconverter nếu bạn chắc chắn luồng byte nguồn được tạo ra trên một máy có cùng độ bền (trong trường hợp hình ảnh TIFF, bạn có thể không thể giả định nó).

Bạn có thể sử dụng một số LINQ ... ví dụ: có chức năng Chuncks đẹp here.Bạn có thể sử dụng nó như:

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

Không có nó ... nó không có cách nào ngầm biết nếu TIFF lưu trữ dữ liệu lớn hay nhỏ. Nó jus giả định dữ liệu là cùng một endianness như nền tảng NET đang chạy trên 'Thứ tự của byte trong mảng phải phản ánh endianness của kiến ​​trúc của hệ thống máy tính' http://msdn.microsoft.com/en-us/library /system.bitconverter.touint16.aspx –

+0

LINQ khi thao tác với dữ liệu hình ảnh có thể hơi chậm. –

+0

@EricJ. oh, bạn nói đúng ... Tôi cứ quên nó, và tôi từng làm việc trên hình ảnh TIFF để ... Tôi đã chỉnh sửa câu trả lời của tôi, và upvoted của bạn vì nó hoàn chỉnh hơn –