2017-11-17 17 views

答えて

0

このコードは、tiffイメージ内のタイルを繰り返し、次にタイルの行を繰り返します。結果のデータはdataバイト配列に格納されます。これからbitmapsourceを作成できます。以下のコードは、16bit、8bit、1bitの灰色のタイル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; 
     } 
    } 
} 

あなたはこのようTIFFヘッダを読むことができます:

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です。

関連する問題