libtiff: 一般的なTIFFファイルの読み込み

TIFFファイルの読み方などはlibtiffのチュートリアルにあるとおりですが、
まとめてみました。

最低限読み込んでおきたいタグ

TIFFのタグはたくさんの種類がありますが、必須のものはいくつかです。
大体以下のタグを読み込んでおけば何とかなります。

TIFFTAG_IMAGEWIDTH、およびTIFFTAG_IMAGELENGTH
画像の縦横サイズ
TIFFTAG_SAMPLESPERPIXEL
ピクセルあたりの色数
TIFFTAG_BITSPERSAMPLE
ピクセルの色深度(ビット数)
TIFFTAG_PHOTOMETRIC
正確な表現かどうかわかりませんが、画像の種別
TIFFTAG_PLANARCONFIG
このタグの数値が1(CONTIG)ならばBIP配列、2(SEPARATE)ならBIL配列

TIFFTAG_PHOTOMETRICは、タグの数値によって以下のように定義されています。
以下の表は一般的なものをピックアップしました。
そのほかのものはよくわかりません(見たこともありません)。

0モノクロ2階調(※)
1グレースケール
2RGBカラー
3インデックスカラー
6YCbCrカラー、JPEG圧縮ならこうなる

POHOTOMETRICが0は、min-is-whiteなので、libtiffの定義と違うように思われますが、
この値で代用しているのかもしれません。

このほか、タイル配列の場合はTIFFTAG_TILEWIDTHTIFFTAG_TILELENGTHを読み込む必要があります。
タイル配列の読み込みはJPEG/TILEのTIFF読み込み方法を参照してください。

また、念のため読んでおきたいタグとして以下のものが挙げられると思います。

TIFFTAG_ROWSPERSTRIP
数行をひとまとめにして1ストリップと定義している場合
TIFFTAG_ORIENTATION
普通はORIENTATION_TOPLEFTだが、まれに別の場所が画像原点として定義されており、この場合は表示のときに画像を回転する必要がある

8bit、RGBまたはグレースケールの場合の読み込み

例として、8bitのRGBもしくはグレースケール画像、スキャンライン配列、CONTIG配列の読み込みを以下に示します
(多分大丈夫だと思います)。
エラー処理などは省略しているところがあります。

bool ReadTIFF( LPCTSTR lpszFName )
{
  int nImageLength;
  int nImageWidth;
  int nBitsPerSample;
  int nSamplePerPixel;
  int nPhotometric;
  int nRowsPerStrip;
  int i;
  int nRow;
  TIFF *pTif;
  LPBYTE pBuf;

  pTif = TIFFOpen( lpszFName, "r" );

  if (!pTif) return false;

  if ( TIFFGetField( pTif, TIFFTAG_IMAGEWIDTH,       &nImageWidth     ) != 1 )
    return false;
  if ( TIFFGetField( pTif, TIFFTAG_IMAGELENGTH,      &nImageLength    ) != 1 )
    return false;
  if ( TIFFGetField( pTif, TIFFTAG_BITSPERSAMPLE,    &nBitsPerSample  ) != 1 )
    return false;
  if ( TIFFGetField( pTif, TIFFTAG_SAMPLESPERPIXEL,  &nSamplePerPixel ) != 1 )
    return false;
  //ストリップ1つあたりの行数 エラーの場合はデフォルト値
  if ( TIFFGetField( pTif, TIFFTAG_ROWSPERSTRIP,     &nRowsPerStrip   ) != 1 )
    nRowsPerStrip = 1;
  if ( TIFFGetField( pTif, TIFFTAG_PHOTOMETRIC,      &nPhotometric    ) != 1 )
    return false;

  pBuf = new BYTE[nImageWidth*nSamplePerPixel*nRowsPerStrip];

  for ( i = 0; i < nImageLength; i += nRowsPerStrip )
  {
    /* ストリップの行数を計算 */
    nRow = (i + nRowsPerStrip > nImageLength) ? nImageLength - i : nRowsPerStrip;
    
    /* バッファに1ストリップ分読み込み */
    if ( TIFFReadEncodedStrip( pTif, TIFFComputeStrip( pTif, i, 0 ),
         pBuf, nRow*nImageWidth*nSamplePerPixel ) == -1 )
    {
      fprintf( stderr, "errorn" );
      delete[] pBuf;
      return false;
    }
    else
    {
      /* バッファに入っているピクセルに対する処理 */
    }
  }
  
  delete[] pBuf;
  TIFFClose( pTif );
  
  return true;
}

インデックスカラー、モノクロ2階調、16bit画像の場合はもう一工夫が必要です。

参考文献

アーカイブ