メモリバッファへキャプチャする

ここではFrameQueueBufferクラスライブラリリファレンス>クラス>FrameQueueBufferオブジェクトに確保したメモリバッファを使用し、FrameSnapSinkクラスライブラリリファレンス>クラス>FrameSnapSinkを使って画像データを直接取り込む方法を示しています。

このサンプルは IC Imaging Controlインストールディレクトリの %TOPLEVEL%\samples\VC\UserAllocatedBuffersにあります。プログラムを実行するため、ディレクトリ内のソリューションファイルUserAllocatedBuffers.slnを開き メニューからビルド -> ビルド UserAllocatedBuffersと選択します。そこからデバッグ -> スタートと選択することでプログラムを実行することができます。

デバイスを開く

この例では%TOPLEVEL%\Samples\VC\Common\CmdHelper.hにあるsetupDeviceFromFile関数を使用します。この関数はデバイス選択ダイアログを表示し、そこで選択されたデバイスをコンフィギュレーションファイルに保存します。その情報は再度関数がコールされた際にロードされます

Grabber grabber;
if( !setupDeviceFromFile( grabber ) )
{
  return -1;
}

必要なバッファサイズを特定する

必要なユーザー割り当てバッファのサイズを特定するために、最適なカラーフォーマットでFrameSnapSinkクラスライブラリリファレンス>クラス>FrameSnapSinkを設定し(このサンプルではeY800 )、Grabber::prepareLiveクラスライブラリリファレンス>クラス>Grabber>Grabber::prepareLive Methodをコールしています。この後、FrameSnapSink::getOutputFrameTypeクラスライブラリリファレンス>クラス>FrameSnapSink>FrameSnapSink::getOutputFrameType Methodを呼び出すことでsink formatを取得することができます。

// イメージバッファのフォーマットをeY800に設定。 eY800はモノクロ、各ピクセル8bit(1 byte)のフォーマット。
// 1つのバッファでシンクにMemBufferCollectionを作成させる
tFrameSnapSinkPtr pSink = FrameSnapSink::create( eY800 );

// sinkの設定
grabber.setSinkType( pSink );

// sinkの出力サイズを取得するためにライブ画像の準備
if( !grabber.prepareLive( false ) )
{
  std::cerr << "Could not render the VideoFormat into a eY800 sink.";
  return -1;
}

// 出力タイプとシンクのサイズを取得
// フィルタを使用している場合、シンクのサイズはVideoFormatによって変わります。
FrameTypeInfo info;
pSink->getOutputFrameType( info );

FrameQueueBuffersにバッファを確保する

シンクのフォーマットを取得したので適切なサイズのバッファを作成することができるようになりました。
FrameTypeInfo::buffersizeクラスライブラリリファレンス>クラス>FrameTypeInfo>FrameTypeInfo::buffersize Propertyは1枚のイメージのバイト数が格納されています。
各メモリバッファはnewを使って割り当てられますが、これは他の場所へのポインタで簡単に置き換えることができ、サードパーティのライブラリバッファとして使用できます。
メモリバッファへのポインタを渡してcreateFrameQueueBufferクラスライブラリリファレンス>関数>createFrameQueueBuffer Methodをコールすることで、各バッファに対して FrameQueueBufferクラスライブラリリファレンス>クラス>FrameQueueBufferオブジェクトが作成されます。

BYTE* pBuf[5] = {};
// ユーザーバッファへの5つのポインターアレイを宣言する
tFrameQueueBufferList lst;
for( int i = 0; i < 5; ++i )
{
    pBuf[i] = new BYTE[info.buffersize];
    // メモリバッファをラップしたFrameQueueBufferオブジェクトを作成する
    tFrameQueueBufferPtr ptr;
    Error err = createFrameQueueBuffer( ptr, info, pBuf[i], info.buffersize, NULL );
    if( err.isError() )
    {
        std::cerr << "Failed to create buffer due to " << err.toString() << "\n";
        return -1;
    }
    lst.push_back( ptr );
}

画像のキャプチャと保存

FrameQueueBufferのリストが作成された後、プログラムはFrameSnapSink::snapSequenceクラスライブラリリファレンス>クラス>FrameSnapSink>FrameSnapSink::snapSequence Methodをコールしてバッファに イメージを保持します。画像の取得に成功すると、それらはストレージに保存されます。

// 高速にイメージを取得するため、ライブモードを開始します。
// startLive()にfalseを指定しているため、ライブ画像はディスプレイ表示されません。
grabber.startLive( false );

// 5枚のイメージをキャプチャします。バッファリストはSinkが受け取った5枚のイメージで満たされます。
Error err = pSink->snapSequence( lst, lst.size() );
if( err.isError() ) {
    std::cerr << "Failed to snap into buffers due to " << err.toString() << "\n";
    return -1;
}

// ライブモードの停止
grabber.stopLive();

// デバイスをクローズする
grabber.closeDev();

// 5枚の取得した画像をBMPとして保存する
for( int idx = 0; idx < 5; ++idx )
{
    wchar_t buf[MAX_PATH] = {};
    swprintf_s( buf, L"file%d.bmp", idx );
    saveToFileBMP( *(lst[idx]), buf );
}

Cleanup

FrameQueueBufferクラスライブラリリファレンス>クラス>FrameQueueBufferとメモリバッファはそれぞれ独立したオブジェクトの寿命を持っています。FrameQueueBufferクラスライブラリリファレンス>クラス>FrameQueueBufferオブジェクトにはメモリバッファへのポインタが含まれているため、先に破棄する必要があります。