通常のカラー画像フォーマットはRGBRGB…というようにデータが並んでいますが、
セパレートタイプのTIFFとは、Rが1行、Gが1行、Bが1行というように並んでいるものです。
リモセン用語で言うと、通常のカラー画像はBIP、セパレートタイプはBILということになります。
このフォーマットの場合、libtiffでの挙動は通常のカラー画像と以下のような違いがあります。
TIFFScanlineSize()
関数は通常の画像は画像の横幅*色数の値を帰すが、
セパレートの場合は画像の横幅の値TIFFReadScanline()
関数は1色分のデータを読み込むTIFFRasterScanlineSize()
関数ならば同じ値を返す
見るからにめんどくさそうなフォーマットですが、
TIFFReadScanline()
関数に便利な4番目の引数というのがあります。
これはセパレートタイプの場合にのみ有効な引数で、読み込む色(サンプル)を指定するというものです。
これを使って、下記のサンプルコードではセパレートファイルから通常のフォーマットに書き出しています。
ちなみに、TIFFベースラインの仕様では、セパレートタイプのフォーマットは非推奨であり、
ソフトウェアはセパレートタイプのTIFFファイルを読み込む義務は無いそうです。
セパレートだ、とわかったらはじいてもいいということだそうです。
さらにちなみに、フリーのリモセンソフトのMultiSpecで、バンド別の画像を合成してTIFFファイルを出力すると
セパレートタイプとして出力されます。
以下のサンプルコードは、そのMultiSpecで合成されたセパレート8バンドのTIFFファイルから、
指定したバンド3つを合成してカラーの通常フォーマットのTIFFファイルに書き出すサンプルです。
#include "../../#libtiff/tiffio.h" int main( int argc, char *argv[] ) { int i, j; int nImageWidth, nImageLength, nSample = 0, nBits = 0, nRows = 0, nPlan = 0; unsigned char *pbIn_R, *pbIn_G, *pbIn_B, *pbOut; TIFF *pTif = TIFFOpen( argv[1], "r" ); if ( !pTif ) { fprintf( stderr, "Unable to open TIFF file [%s]n", argv[1] ); exit( 1 ); } TIFF *pOut = TIFFOpen( argv[2], "w" ); if ( !pOut ) { fprintf( stderr, "Unable to create TIFF file [%s]n", argv[2] ); TIFFClose( pTif ); exit( 1 ); } int nR = atoi( argv[3] ); int nG = atoi( argv[4] ); int nB = atoi( argv[5] ); TIFFGetField( pTif, TIFFTAG_IMAGEWIDTH, &nImageWidth ); TIFFGetField( pTif, TIFFTAG_IMAGELENGTH, &nImageLength ); TIFFGetField( pTif, TIFFTAG_SAMPLESPERPIXEL, &nSample ); TIFFGetField( pTif, TIFFTAG_BITSPERSAMPLE, &nBits ); TIFFGetField( pTif, TIFFTAG_ROWSPERSTRIP, &nRows ); TIFFGetField( pTif, TIFFTAG_PLANARCONFIG, &nPlan ); // nPlan==2ならセパレート if ( nBits != 8 ) { fprintf( stderr, "File is no 8bitn" ); TIFFClose( pTif ); TIFFClose( pOut ); exit( 1 ); } TIFFSetField( pOut, TIFFTAG_IMAGEWIDTH, nImageWidth ); TIFFSetField( pOut, TIFFTAG_IMAGELENGTH, nImageLength ); TIFFSetField( pOut, TIFFTAG_SAMPLESPERPIXEL, 3 ); TIFFSetField( pOut, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB ); TIFFSetField( pOut, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG ); TIFFSetField( pOut, TIFFTAG_BITSPERSAMPLE, nBits ); pbIn_R = (unsigned char *)_TIFFmalloc( TIFFScanlineSize( pTif ) ); pbIn_G = (unsigned char *)_TIFFmalloc( TIFFScanlineSize( pTif ) ); pbIn_B = (unsigned char *)_TIFFmalloc( TIFFScanlineSize( pTif ) ); pbOut = (unsigned char *)_TIFFmalloc( TIFFScanlineSize( pTif ) * 3 ); for ( i = 0; i < nImageLength; i++ ) { TIFFReadScanline( pTif, pbIn_R, i, nR ); TIFFReadScanline( pTif, pbIn_G, i, nG ); TIFFReadScanline( pTif, pbIn_B, i, nB ); for ( j = 0; j < nImageWidth; j++ ) { pbOut[j*3+0] = pbIn_R[j]; pbOut[j*3+1] = pbIn_G[j]; pbOut[j*3+2] = pbIn_B[j]; } TIFFWriteScanline( pOut, pbOut, i ); } _TIFFfree( pbIn_R ); _TIFFfree( pbIn_G ); _TIFFfree( pbIn_B ); _TIFFfree( pbOut ); TIFFClose( pTif ); TIFFClose( pOut ); return 0; }