libtiff: タイル配列のTIFF読み込み・書き込み

一般的な画像ファイルでは、画像の左上から右下まで1行ずつピクセルが並んでいますが、
タイル配列とは画像をタイルに分割して、それぞれのタイルで左上から右下まで
1行ずつ並んでいます。

スキャンライン配列タイル配列
スキャンライン配列
タイル配列

この配列の魅力は画像に対してランダムアクセスに近い形で
画像の所定の部分だけを読み出すのに適している点です。

TIFFファイルはこの形式をサポートしています。
以下の例は、入力画像から引数で指定したタイルを抽出して出力画像に保存する例です。
タイル配列のメリットがわかりやすいかと思います。

   1: 
   2: #include <tiffio.h>
   3: #include <math.h>
   4: #include <stdlib.h>
   5: 
   6: int main( int argc, char *argv[] )
   7: {
   8:   TIFF *pIn, *pOut;
   9:   int nImageLength, nImageWidth, nSample, nBits;
  10:   int nPhotometric;
  11:   int nTileLength, nTileWidth;
  12:   int nTileNumX, nTileNumY;
  13:   int i, j, x, y;
  14:   int nTileXL, nTileXR, nTileYT, nTileYB;
  15:   unsigned char *pBuf;
  16:   
  17:   pIn = TIFFOpen( argv[1], "r" );
  18:   if ( !pIn )
  19:   {
  20:     exit( 1 );
  21:   }
  22:   
  23:   // タイルファイルかどうかのチェック
  24:   if ( !TIFFIsTiled( pIn ) )
  25:   {
  26:     TIFFClose( pIn );
  27:     exit( 1 );
  28:   }
  29:   
  30:   // コピーするタイル範囲を引数から取得
  31:   nTileXL = atoi( argv[2] );
  32:   nTileXR = atoi( argv[3] );
  33:   nTileYT = atoi( argv[4] );
  34:   nTileYB = atoi( argv[5] );
  35:   
  36:   if ( nTileXL < 0 || nTileXR < 0 ||
  37:      nTileXL > nTileXR )
  38:   {
  39:     TIFFClose( pIn );
  40:     exit( 1 );
  41:   }
  42:   if ( nTileYT < 0 || nTileYB < 0 ||
  43:      nTileYT > nTileYB )
  44:   {
  45:     TIFFClose( pIn );
  46:     exit( 1 );
  47:   }
  48: 
  49:   // 入力画像の情報を取得
  50:   TIFFGetField( pIn, TIFFTAG_IMAGEWIDTH, &nImageWidth );
  51:   TIFFGetField( pIn, TIFFTAG_IMAGELENGTH, &nImageLength );
  52:   TIFFGetField( pIn, TIFFTAG_BITSPERSAMPLE, &nBits );
  53:   TIFFGetField( pIn, TIFFTAG_SAMPLESPERPIXEL, &nSample );
  54:   TIFFGetField( pIn, TIFFTAG_PHOTOMETRIC, &nPhotometric );
  55:   TIFFGetField( pIn, TIFFTAG_TILEWIDTH, &nTileWidth );
  56:   TIFFGetField( pIn, TIFFTAG_TILELENGTH, &nTileLength );
  57:   
  58:   // 縦横のタイル数の計算
  59:   nTileNumX = (int)ceil( (double)nImageWidth / nTileWidth );
  60:   nTileNumY = (int)ceil( (double)nImageLength / nTileLength );
  61:   if ( nTileXL > nTileNumX || nTileXR > nTileNumX ||
  62:      nTileYT > nTileNumY || nTileYB > nTileNumY )
  63:   {
  64:     TIFFClose( pIn );
  65:     exit( 1 );
  66:   }
  67: 
  68:   // 出力画像にタグを書き込み
  69:   pOut = TIFFOpen( argv[6], "w" );
  70:   TIFFSetField( pOut, TIFFTAG_IMAGEWIDTH, (nTileXR-nTileXL+1)*nTileWidth );
  71:   TIFFSetField( pOut, TIFFTAG_IMAGELENGTH, (nTileYB-nTileYT+1)*nTileLength );
  72:   TIFFSetField( pOut, TIFFTAG_BITSPERSAMPLE, nBits );
  73:   TIFFSetField( pOut, TIFFTAG_SAMPLESPERPIXEL, nSample );
  74:   TIFFSetField( pOut, TIFFTAG_PHOTOMETRIC, nPhotometric );
  75:   TIFFSetField( pOut, TIFFTAG_TILEWIDTH, nTileWidth );
  76:   TIFFSetField( pOut, TIFFTAG_TILELENGTH, nTileLength );
  77:   TIFFSetField( pOut, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
  78: 
  79:   // 1タイル分の領域確保
  80:   pBuf = (unsigned char *)_TIFFmalloc( TIFFTileSize( pIn ) );
  81:   
  82:   for ( i = nTileYT, y = 0; i <= nTileYB; i++, y++ )
  83:   {
  84:     for ( j = nTileXL, x = 0; j <= nTileXR; j++, x++ )
  85:     {
  86:       if ( TIFFCheckTile( pIn, j*nTileWidth, i*nTileLength, 0, 0 ) )
  87:       {
  88:         TIFFReadTile( pIn, pBuf, j*nTileWidth, i*nTileLength, 0, 0 );
  89:         TIFFWriteTile( pOut, pBuf, x*nTileWidth, y*nTileLength, 0, 0 );
  90:       }
  91:     }
  92:   }
  93:   
  94:   _TIFFfree( pBuf );
  95:   
  96:   TIFFClose( pIn );
  97:   TIFFClose( pOut );
  98:   
  99:   return 0;
 100: }
アーカイブ