16bit grayscale TIFFの読み込み

Linux

これまで自作の関数でMulti TIFFファイルを書いたり、読んだりしていたのですが、libtiffライブラリを使ってみることにしました。

私が使うデータは主に8bit、16bitのグレースケールです。
今回は16bit(unsigned short int)グレースケールsingle TIFFの読み込みです。
Windows、Linuxで解析を行うので、両方でコンパイルできるようにしています。

その他

・確認のためにprintfでヘッダ情報を標準出力に表示しています。そのため、テキストファイルエディタなどで「read-16bit.txt」に含まれる余分なヘッダ情報を削除しておきます。
・ImageJで「read-16bit.txt」を「File」→「Import」→「Text Image」で「read-16bit.txt」を選択する。

ソース

環境によっては「nodefaultlib」を付けなくてもコンパイルは通ります。
標準出力に出力したデータには、先頭に読み取ったTIFFヘッダ情報が含まれるので、削除してからImageJで読み込みます。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef __GNUC__
#include <tiffio.h>
#endif

#ifdef _WIN32
#include "tiffio.h"
#ifdef _DEBUG
#pragma comment(linker, "/nodefaultlib:\"libcmtd.lib\"")
#else
#pragma comment(linker, "/nodefaultlib:\"libcmt.lib\"")
#endif
#pragma comment(lib, "libtiff.lib")
#endif

int main( int argc, char **argv )
{
    int     i, j;
    int     width, height;
    uint32  tifsize;
    uint16  samplesperpixel, bitspersample;
    uint16  photometric, fillorder, compression;
    uint16  orientation, resunit, planarconfig;
    uint16  *buf, *line;
    TIFF    *tif;

    tif = TIFFOpen("test-16bit.tif", "r");
    if ( tif == NULL )
    {
        printf("ERROR: Can not open tiff file \n");
        exit( EXIT_FAILURE );
    }

    // Tagを読み込む
    TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
    TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
    TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bitspersample);
    TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
    TIFFGetField(tif, TIFFTAG_COMPRESSION, &compression);
    TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric);
    TIFFGetField(tif, TIFFTAG_FILLORDER, &fillorder);
    TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planarconfig);
    TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation);
    TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);

    // 確認
    printf("width: %d \n", width);
    printf("height: %d \n", height);
    printf("bitspersample: %d \n", bitspersample);
    printf("samplesperpixel: %d \n", samplesperpixel);
    printf("compression: %d \n", compression);
    printf("photometric: %d \n", photometric);
    printf("fillorder: %d \n", fillorder);
    printf("planarconfig: %d \n", planarconfig);
    printf("resunit: %d \n", resunit);

    // Error Check
    if ( width <= 0 || height <= 0 )
    {
        printf("ERROR: width or height is error \n");
        exit( EXIT_FAILURE );
    }
    if ( samplesperpixel != 1 )
    {
        printf("ERROR: Only samples/pixel = 1 \n");
        exit( EXIT_FAILURE );
    }
    if ( bitspersample != 16 )
    {
        printf("ERROR: Only 16-bit samples \n");
        exit( EXIT_FAILURE );
    }

    // 画像の領域確保
    tifsize = width * height * sizeof( uint16 );
    buf     = ( uint16 * )malloc( tifsize );
    if ( buf == NULL )
    {
        printf("ERROR: Can not get memory [buf] \n");
        exit( EXIT_FAILURE );
    }

    // 画像1ライン分の領域確保
    line = ( uint16 * )_TIFFmalloc( TIFFScanlineSize( tif ) );
    // line = ( uint16 * )_TIFFmalloc( width * 1 * sizeof( uint16 ) );
    if ( line == NULL )
    {
        printf("ERROR: Can not get memory [line] \n");
        exit( EXIT_FAILURE );
    }

    // 画像情報を読み込む
    for ( i = 0; i < height; i++ )
    {
        if ( TIFFReadScanline( tif, line, i, 0 ) < 0 )
        {
            printf("ERROR: Can not get TIFF line [TIFFReadScanline] \n");
            exit( EXIT_FAILURE );
        }

        for ( j = 0; j < width; j++ )
        {
            buf[width * i + j] = line[j];
        }
    }

    _TIFFfree( line );
    TIFFClose( tif );

    // 画像情報を標準出力する
    for( i = 0; i < height; i++ )
    {
        for( j = 0; j < width; j++ )
        {
            if ( j == width - 1 )
            {
                printf("%d", buf[width * i + j]);
            }
            else
            {
                printf("%d ", buf[width * i + j]);
            }
        }
        printf("\n");
    }

    free( buf );
    return EXIT_SUCCESS;
}


Comments