2017-11-17 1 views

답변

0

이 코드는 tiff 이미지의 타일을 반복 한 다음 타일의 행을 반복합니다. 결과 데이터는 data 바이트 배열에 저장됩니다. 여기에서 bitmapsource을 만들 수 있습니다. 아래 코드는 16 비트, 8 비트, 1 비트 회색 타일 tiff 이미지에서 작동합니다.

_tiff = Tiff.Open(filepath, "r"); 

var data = new byte[header.ImageWidth * header.ImageHeight]; 
var buffer = new byte[_tiff.TileSize()];   

for (var row = 0; row < header.ImageHeight; row += header.TileHeight) 
{ 
    for (var col = 0; col < header.ImageWidth; col += header.TileWidth) 
    { 
     // Read the tile 
     if (_tiff.ReadTile(buffer, 0, col, row, 0, 0) < 0) 
     { 
      throw new Exception("Error reading data"); 
     } 

     var index = 0; 

     // Iterate the rows in the tile 
     for (var i = 0; i < header.TileHeight && i + row < header.ImageHeight; i++) 
     { 
      var length = header.TileWidth; 

      // Index of the first position in the row 
      var position = (row + i) * data.Width + col; 

      // Check we are not outside the image 
      if (col + length > header.ImageWidth) 
      { 
       length = header.ImageWidth - col; 
      } 

      switch (header.BitsPerPixel) 
      { 
       case 1: 
       { 
        for (var p = 0; p < (length + 7)/8; p++) 
        { 
         // Unpack the pixels 
         for (var b = 0; b < 8; b++) 
         { 
          data[position + p * 8 + (7 - b)] = (buffer[index/8 + p] & (1 << b)) != 0 ? byte.MaxValue : byte.MinValue; 
         } 
        } 

        break; 
       } 
       case 8: 
       { 
        for (var p = 0; p < length; p++) 
        { 
         data[position + p] = buffer[index + p]; 
        } 

        break; 
       } 
       case 16: 
       { 
        for (var p = 0; p < length; p++) 
        { 
         data[position + p] = buffer[index * 2 + p * 2]; 
        } 

        break; 
       } 
       default: 
       { 
        throw new NotImplementedException(); 
       } 
      } 

      index += header.TileWidth; 
     } 
    } 
} 

이 같은 티파니 헤더를 읽을 수 있습니다

public class TaggedImageHeader 
{ 
    public int BitsPerPixel { get; private set; } 
    public int Components { get; private set; } 
    public string Compression { get; private set; } 
    public int ImageHeight { get; private set; } 
    public int ImageWidth { get; private set; } 
    public string PlanarConfig { get; private set; } 
    public int TileHeight { get; private set; } 
    public int TileWidth { get; private set; } 

    internal static TaggedImageHeader Read(Tiff tiff) 
    { 
     var imageWidth = tiff.GetField(TiffTag.IMAGEWIDTH); 
     var imageHeight = tiff.GetField(TiffTag.IMAGELENGTH); 
     var bitsPerPixel = tiff.GetField(TiffTag.BITSPERSAMPLE); 
     var components = tiff.GetField(TiffTag.SAMPLESPERPIXEL); 
     var tileWidth = tiff.GetField(TiffTag.TILEWIDTH); 
     var tileHeight = tiff.GetField(TiffTag.TILELENGTH); 
     var compression = tiff.GetField(TiffTag.COMPRESSION); 
     var planarConfig = tiff.GetField(TiffTag.PLANARCONFIG); 

     return new TaggedImageHeader 
     { 
      ImageWidth = imageWidth?[0].ToInt() ?? 0, 
      ImageHeight = imageHeight?[0].ToInt() ?? 0, 
      BitsPerPixel = bitsPerPixel?[0].ToInt() ?? 0, 
      Components = components?[0].ToInt() ?? 0, 
      TileWidth = tileWidth?[0].ToInt() ?? 0, 
      TileHeight = tileHeight?[0].ToInt() ?? 0, 
      Compression = compression?[0].ToString() ?? "", 
      PlanarConfig = planarConfig?[0].ToString() ?? "" 
     }; 
    } 
} 

당신의 헤더를 읽기 전에 TIFF 파일과 같은 피라미드로 작업하는 경우가 _tiff.SetFrame(frame)를 호출해야합니다.

데이터 배열을 아래 코드로 바꾸면 WriteableBitmap 백 버퍼에 직접 쓸 수 있습니다. 이렇게하면 불필요한 사본이 제거됩니다.

var data = new UnsafeBuffer((byte*)bitmap.BackBuffer, bitmap.BackBufferStride, bitmap.PixelHeight); 

UnsafeBuffer

는 :

public unsafe class UnsafeBuffer : Buffer 
{ 
    private readonly byte* _data; 

    public UnsafeBuffer(byte* data, int x, int y) : base(x, y) 
    { 
     _data = data; 
    } 

    public override byte this[int x, int y] 
    { 
     get => this[y * Width + x]; 
     set => this[y * Width + x] = value; 
    } 

    public override byte this[int index] 
    { 
     get => _data[index]; 
     set => _data[index] = value; 
    } 
} 

public abstract class Buffer 
{ 
    protected Buffer(int width, int height) 
    { 
     Width = width; 
     Height = height; 
    } 

    public int Height { get; private set; } 
    public int Length => Width * Height; 
    public int Width { get; private set; } 

    public abstract byte this[int x, int y] { get; set; } 

    public abstract byte this[int index] { get; set; } 
} 

유용한 자원은 그 안에 샘플을 가지고 documentation 될 것이다. 나는 또한이 link이 나를 시작하게하는데 매우 유용하다는 것을 알았다.

관련 문제