はじめに
蛍光画像などでは8bitグレースケールを扱うことがあります。
Image-Jなど画像処理ソフトウェアを使っても良いですが、仕組みを知っていると効率も上がるので学習してみました。
そのひとつとしてC#とLibTiff.Netを使って8bitグレースケールsingle TIFFを表示する方法を紹介します。
WindowsのVisual C#でコンパイルして動かしました。
実行ファイルはLinuxでも動作します。
環境
WindowsではMicrosoftからVisual C#をダウンロード、プロジェクトを作成して実行ファイルを作成します。

Linuxで動かす場合はWindowsで使用した「.NET Framework」のバージョンに対応したパッケージをインストールする必要があります。

LibTiff.Net
libtiffのC#版でWindowsとLinuxで使います。
コンパイル(環境1)
「スタート」→「Microsoft Visual Studio 2019」→「Visual Studio コマンドプロンプト(2019)」を使います。
ソース名がhoge.cs、実行ファイル名をout.exeとするとき、以下のようにコンパイルします。
csc /lib:.\ /reference:BitMiracle.LibTiff.NET.dll /out:out.exe hoge.cs ファイルが複数ある場合 csc /lib:.\ /reference:BitMiracle.LibTiff.NET.dll /out:out.exe hoge1.cs hoge2.cs
コンパイル(環境2)
ソースの改行コードはLFにしてください。
mcs -r:./BitMiracle.LibTiff.NET.dll -out:out.exe hoge.cs 又は、 dmcs -r:./BitMiracle.LibTiff.NET.dll -out:out.exe hoge.cs ファイルが複数ある場合 mcs -r:./BitMiracle.LibTiff.NET.dll -out:out.exe hoge1.cs hoge2.cs 又は、 dmcs -r:./BitMiracle.LibTiff.NET.dll -out:out.exe hoge1.cs hoge2.cs 実行は以下。 chmod 755 ./out.exe ./out.exe
実行結果
Linuxで実行したときのスクリーンショットです。
Windowsでも同様になります。
DLLを登録する
TIFFの解析に「BitMiracle.LibTiff.NET.dll」を使うので「MS Visual C#」に登録します。
「プロジェクト」→「参照の追加」→「参照」タブからファイルを指定する。
出力ウィンドウの表示
「MS Visual C#」を使う場合、「Debug.WriteLine」などでデバッグ情報を出力します。
デバッグ情報は、標準では表示されないので、デバッグ中にメニューバーから操作して表示します。
「デバッグ」→「ウィンドウ」→「出力」
ソース
「8bit.tif」は自前で準備するか、以前の記事のソースを使って作成してください。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; // PixelFormat using System.Drawing.Imaging; // Marshal.Copy using System.Runtime.InteropServices; // libtiff.net using BitMiracle.LibTiff.Classic; // Debug using System.Diagnostics; namespace Tiff8bitShowForm { public partial class Form1 : Form { // TIFFの縦横サイズ static public int tif_width, tif_height; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { int i; string fileName = "8bit.tif"; byte[] tif_byte = readTiff(fileName); Debug.WriteLine(tif_width); Debug.WriteLine(tif_height); PixelFormat bmpPixelFormat = PixelFormat.Format8bppIndexed; Bitmap bmp = new Bitmap(tif_width, tif_height, bmpPixelFormat); // パレットを設定する(グレースケール) ColorPalette palette = bmp.Palette; Color[] entry = palette.Entries; for (i = 0; i < entry.Length; i++) { entry[i] = Color.FromArgb(i, i, i); } bmp.Palette = palette; // Pixelデータの領域を確保 //Rectangle rect = new Rectangle(0, 0, tif_width, tif_height); Rectangle rect = new Rectangle(Point.Empty, bmp.Size); // BitmapDataのインスタンスを生成・BitmapのLock // WriteOnly / ReadWrite / ReadOnly / UserInputBuffer BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmpPixelFormat); /* 方法1 // 方法1 for (i = 0; i < tif_height; i++) { IntPtr line = (IntPtr)((Int64)bmpData.Scan0 + i * bmpData.Stride); Marshal.Copy(tif_byte, i * tif_width, line, tif_height); } */ ///* // 方法2 // 各項目を抽出 IntPtr ptr = bmpData.Scan0; // マネージ配列からアンマネージメモリ、又はその逆のコピー。 // アンマネージメモリとは、CLR(Common Language Runtime)に // 準拠していないコードを含んでいるコードの総称。 Marshal.Copy(tif_byte, 0, ptr, tif_byte.Length); //*/ // BitmapのLock解除 bmp.UnlockBits(bmpData); // PictureBoxのサイズ設定・描画 pictureBox1.Image = bmp; pictureBox1.Location = new Point(0, 0); pictureBox1.Size = bmp.Size; // Formのサイズ設定・リサイズ禁止 //this.ClientSize = new System.Drawing.Size(tif_width, tif_height); this.ClientSize = bmp.Size; this.FormBorderStyle = FormBorderStyle.FixedSingle; } // read TIFF private static byte[] readTiff(string fname) { int i, j; ushort samplesperpixel, bitspersample; double resolution_x, resolution_y; using (Tiff tif = Tiff.Open(fname, "r")) { if (tif == null) { Debug.WriteLine("Can not read Tiff file."); } tif_width = tif.GetField(TiffTag.IMAGEWIDTH)[0].ToInt(); tif_height = tif.GetField(TiffTag.IMAGELENGTH)[0].ToInt(); resolution_x = tif.GetField(TiffTag.XRESOLUTION)[0].ToDouble(); resolution_y = tif.GetField(TiffTag.YRESOLUTION)[0].ToDouble(); bitspersample = tif.GetField(TiffTag.BITSPERSAMPLE)[0].ToUShort(); samplesperpixel = tif.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToUShort(); Debug.WriteLine(tif_width); Debug.WriteLine(tif_height); Debug.WriteLine(resolution_x); Debug.WriteLine(resolution_y); Debug.WriteLine(bitspersample); Debug.WriteLine(samplesperpixel); // 画像データの確保 byte[] buf_byte = new byte[tif_width * tif_height * sizeof(byte)]; // 1ラインのデータ配列 byte[] scanline = new byte[tif.ScanlineSize()]; Debug.Indent(); // 読み取ったデータを格納 for (i = 0; i < tif_height; i++) { tif.ReadScanline(scanline, i); for (j = 0; j < tif_width; j++) { buf_byte[tif_width * i + j] = scanline[j]; //Debug.WriteLine(scanline[j]); } } return buf_byte; } } } }
Comments