Easy Web Camera LIBrary
EWCLIB 2.8
"ewclib.h" by I.N. 2021/5/21

  内容

1.はじめに
  特長動作環境環境設定インストール方法アンインストール方法使用手順

2.説明
  基本的なことメディアサブタイプについてフレームバッファについてリングバッファについて

3.サンプルプログラム
  最も単純なプログラムESPLIBを併用した例対応フォーマットの一覧を表示する例
  カメラおよびフォーマットを選択してから画像入力する例NV12出力のカメラを使う例
  MJPGのデータをそのまま取得する例1MJPGのデータをそのまま取得する例2
  各種設定の変更を行う例3台までのカメラ画像を表示する例
  300フレーム遅れた映像を表示する例CPU使用率を下げた低速度な画像入力
  OpenCVと組み合わせて使用した例OpenCV&ESPLIBと組み合わせて使用した例

4.関数リファレンス
  基本関数フレームバッファ関連グローバル変数
  カメラ設定の取得・変更・保存・読込画像変換対応フォーマットの取得

5.おわりに
  著作権・使用許諾バージョンアップ履歴作者のウェブサイト開発環境謝辞


はじめに

本製品をお買い上げいただき誠にありがとうございます.(無料です)
このライブラリ関数を使えば,誰でも手軽にウェブカメラ(USBカメラ/DirectShow)画像入力プログラムを作成できます.
最近は低価格なウェブカメラがたくさん出回っていますが,それらの画像を処理するプログラムの作成に便利です.


特長

(1) 最低3つの関数を使用するだけで簡単に画像入力ができます.
(2) 複数カメラの同時接続に対応します.
(3) カメラ毎に解像度,フレームレートの設定ができます.
(4) 明るさ,コントラスト,ホワイトバランス等の取得・設定ができます.
(5) 画像の更新確認,サンプル時刻の取得,フレームバッファの変更ができます.
(6) カメラのフォーマット取得やフォーマット指定ができます.
(7) リングバッファの数を指定することができます.


動作環境

 OS:Windows XP/Vista/7/8/10※4
 必要ソフト:例1 Visual C++ 2010以降 + qedit.h ※1
        例2 Visual C++ 2008 Professional ※2
        例3 Visual C++ 2008 Express Edition ※3
      ※1 Visual C++ 2010以降にはqedit.hがない.
         「Windows SDK for Windows Server 2008 and .NET Framework 3.5」にqedit.hが入っている.
      ※2 DirectX SDKはなくてもよい.
      ※3 Express EditionではWindows SDKが必要.
         (Windows SDKのうち,少なくともヘッダーファイルとx86ライブラリがあればよい)
※4 補足
Windows 10でEWC_Open()等のエラーコード7が出た場合,
設定→プライバシー→カメラ→「アプリがカメラにアクセスできるようにする」がオンであるか確認
してください.

動作確認したカメラ環境:
    (1) Cam Link 4K (YUY2/NV12/I420, 1920x1080, 60fps)
    (2) The Imaging Source DMK27BUR0135 (Y800/Y16, 120fps)
    (3) Logicool C270, C310
    (4) Logicool c922 Pro Stream Webcam (MJPG, 1280x720, 60fps)
    (5) Logicool HD Pro Webcam C920 (1920x1080, 30fps)
    (6) Microsoft LifeCam Studio (1920x1080, 30fps, Microsoft LifeCamはインストールしない)
    (7) Logicool Qcam Ultra Vision, Qcam Pro 4000
    (8) Buffalo BSW13K08H
    (9) Buffalo BSW200MBK (MJPG, 1920x1080, 30fps)
    (10) Buffalo PC-SDVD/U2G (USBキャプチャーケーブル)
    (11) The Imaging Source DMK22AUC03
    (12) BSW50KM01H(640x480まで), WebCam Pro, WebCam Pro eX, ノートPC内蔵カメラ
    (*) その他 OpenCV 2.1と組み合わせて使用

(上記以外の機器・環境については不明です.また上記以外の機器が接続されている環境下も不明です.)
(Visual C++ .NET 2003などの古い開発環境の場合には,EWCLIBのバージョン1.2を使用してください.)


環境設定

Visual C++ のインストール
 あらかじめ,Visual C++ をインストールしておいて下さい.

Visual C++ 2008では
 インストール以外,特にすることはありません.

Visual C++ 2010以降では
 Visual C++ 2010以降にはqedit.hがありませんので,何らかの方法で入手してください.
 例えば,Visual C++ 2008についてきたqedit.hをVisual C++ 2010以降の方にもコピーする.
 例えば,C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include\qedit.hをC:\Program Files\Microsoft SDKs\Windows\v7.0A\Include\へコピーする.
 また,別の例として,適当な(古めの?)バージョンのWindows SDKをインストールすると,それに含まれていたりします.


インストール方法

 Visual C++ 2008の場合

 以下の方法を例として挙げておきます.(他の方法でも構いません.)

 ewclib.h を適当なフォルダに置いておく.Visual C++ で「ツール」→「オプション」→「プロジェクトおよびソリューション」→「VC++ディレクトリ」→「ディレクトリを表示するプロジェクト:インクルードファイル」の画面を表示させ,ewclib.h を置いた先のフォルダ名を追加登録する.


 Visual C++ 2010以降の場合

 各プロジェクトのプロパティ(VC++ディレクトリ - インクルードディレクトリ)に,ewclib.hが置いてあるディレクトリを追加する.


アンインストール方法

 インストールの時と同じ手順で「ディレクトリを表示するプロジェクト:インクルードファイル」の画面を表示させ,自分が追加したフォルダ名の登録を削除する.


使用手順

 プログラムの先頭で ewclib.h をインクルードするだけです.
 OpenCVを併用する場合は,cv.hの方を先にインクルードしておいてください.
 ソースファイルの拡張子は .cpp にして下さい.



説明

基本的なこと

カメラの使用を開始するためにEWC_Open()を最初に呼んで下さい.複数のカメラを使用する場合,カメラ毎にEWC_Open()を呼んで下さい.

新しい画像の到着を知るためにはEWC_IsCaptured()を使います.

画像データを取得するにはEWC_GetImage()を使います.

終了処理のためにEWC_Close()またはEWC_CloseAll()を最後に呼んで下さい.

接続されているカメラの数を知るにはEWC_GetCamera()を使います.この関数はEWC_Open()で開始していなくても使えますので,事前にカメラ台数を把握できます.

カメラの名前を知るにはEWC_GetCameraName()を使用します.この関数もEWC_Open()で開始していなくても使えますので,事前にカメラ情報を把握できます.

カメラがサポートする解像度,ビット数,フレームレート等の情報を取得するにはEWC_GetFormat()を使います.

画像データの格納に必要なフレームバッファのサイズを得るにはEWC_IsCaptured()あるいはEWC_GetBufferSize()を使います.

明るさ,コントラスト等の設定を変更するにはカメラ設定の取得・変更・保存・読込関数を使います.

EWC_Open()によってフレームバッファは自動的に確保されますが,自前で用意したフレームバッファを使用するときはフレームバッファ関連関数を使います.

初期化関数EWC_Open()の実行には多少時間がかかる場合があります(特に初回).また,この関数がエラー終了する原因として,カメラのドライバがインストールされていない,そのカメラが対応していない解像度やフレームレートを指定した場合,指定した台数だけのカメラが接続されていない場合などが挙げられます.

カメラを複数接続して使用できますが,同時入力(同期した画像入力)が保証されるわけではありません.

カメラを複数使用する場合,USBバスの帯域不足のため初期化に失敗することがあります.このとき,解像度を下げたり,別のUSBポートを使用することで問題が解消する場合があります.


メディアサブタイプについて

EWCLIBではデバイス出力ピンのメディアサブタイプ(以下,デバイスフォーマット)と取得画像時のメディアサブタイプ(以下,画像フォーマット)を別々に指定できます.デバイスフォーマットから画像フォーマットへの変換はDirectShow内で自動的に行われますが,対応していない変換の組み合わせではEWC_Open()がエラー終了となります.

デバイスフォーマットはカメラ側が用意しているフォーマットです.デバイスフォーマットや解像度等の情報を得るにはEWC_GetFormat()を使用します.

デバイスフォーマットを指定しなければ,(デフォルトの)最初に見つかったものが使われます.デバイスフォーマットはMEDIASUBTYPE_YUY2であることが多いです.カメラの使用開始後にEWC_GetDeviceSubtype()を使うと,選択されたメディアサブタイプ名を知ることができます.

ハードウェアエンコード機能を持つカメラなど,カメラによっては同じ解像度でも複数のデバイスフォーマットをサポートしている場合があります.デバイスフォーマットを指定するには次の(1)〜(3)のいずれかのようにします.
 (1)EWC_Open()の引数dev_mstypeを使う
   例 EWC_Open(0,640,480,30,-1,ewc_type,MEDIASUBTYPE_MJPG);
 (2)EWC_Open()より前にewc_device_typeに値を代入する
   例 ewc_device_type=MEDIASUBTYPE_MJPG;
 (3)ewclib.hのインクルードより前にEWC_DEVICE_TYPEを定義する
   例 #define EWC_DEVICE_TYPE MEDIASUBTYPE_MJPG

デフォルトの画像フォーマットは,OpenCVのヘッダファイル(cv.h)が読み込まれていなければMEDIASUBTYPE_RGB32,読み込まれていればMEDIASUBTYPE_RGB24になります.
 MEDIASUBTYPE_RGB32の場合,画像データの並び(バイト単位)は[B][G][R][0]です.また,MEDIASUBTYPE_RGB24の場合,画像データの並び(バイト単位)は[B][G][R]です.
 デフォルト以外の画像フォーマットを使用したい場合,次の(4)〜(6)のいずれかのようにします.
 (4)EWC_Open()の引数mstypeを使う
   例 EWC_Open(0,640,480,30,-1,MEDIASUBTYPE_RGB24);
 (5)EWC_Open()より前にewc_typeに値を代入する
   例 ewc_type=MEDIASUBTYPE_RGB24;
 (6)ewclib.hのインクルードより前にEWC_TYPEを定義する
   例 #define EWC_TYPE MEDIASUBTYPE_RGB24

カメラの使用開始後にEWC_GetSubtype()を使うと,選択された画像フォーマット名を知ることができます.

カメラの使用開始後にEWC_GetSubtype()を使うと,選択された画像フォーマット名を知ることができます.

カメラの出力するフォーマットで画像データをそのまま取得するには,EWC_RawMode()で1を設定した後,デバイスフォーマットと画像フォーマットを同じものに指定してEWC_Open()を呼んで下さい.詳しくはEWC_RawMode()を参照してください.

NV12, Y16, Y800からRGB32へ画像データの変換を行う各関数EWC_CnvNV12toRGB32(), EWC_CnvY16toRGB32(), EWC_CnvY800toRGB32()も用意されています.

フォーマットの種類についてはDirectX SDKのヘルプでAM_MEDIA_TYPE構造体(Media Types, Video Subtypes)を参照してください.なお,カメラやPC環境(中間変換フィルタの提供状況)によって使用可能なフォーマットは異なります.


フレームバッファについて

関数リファレンス フレームバッファ関連

EWCLIBではEWC_Open()の実行時に画像データを格納するためのフレームバッファを内部で自動的に確保します.カメラからの画像データは取得(サンプル)時刻毎にそのフレームバッファへ格納されます.EWC_GetImage()はそのフレームバッファからユーザが指定したポインタへ画像データをユーザ側のタイミングで転送(コピー)する関数です.

もし「自前でフレームバッファを用意するから,そのフレームバッファに画像データを取得(サンプル)時刻毎に自動で転送(格納)してくれ」という場合には,EWC_SetBuffer()を使います. なお,リングバッファに複数枚を指定しており,かつ,EWC_SetBuffer()で自前のフレームバッファへ変更する場合は,RGB32相当のバイトサイズで枚数分だけ連続した長いフレームバッファ(メモリ領域)を設定してください. また,自前のフレームバッファにアクセスする際,コールバック関数がバックグラウンドで勝手にバッファを書き換える可能性があるため,アクセス開始時にEWC_BufferLock(),アクセス終了時にEWC_BufferUnlock()を使用して下さい.

新しい画像データが到着したかどうかは,EWC_IsCaptured()を使うことによって知ることができます.また,画像データの先頭アドレス,画像データのバイト数,フレーム番号,リングバッファの読み出し位置,画像取得時刻を知るためにもEWC_IsCaptured()は使えます.

現在設定されているリングバッファの先頭アドレスを知るにはEWC_GetBuffer()を使います.EWC_Open()直後には,EWC_GetBuffer()で得られるアドレスは内部で確保されたリングバッファのアドレスになっています.EWC_SetBuffer()で別のバッファを設定した場合には,EWC_GetBuffer()はその変更された方のアドレスを返します.

double ewc_s[int num].ftimeというグローバル変数は,最新のフレーム周期(単位:秒)が常に格納されています.num はカメラ番号です.このewc_s[].ftimeの値はバックグラウンドで勝手に変化します.この変数の逆数(1.0/ewc_s[].ftime)を計算すればフレームレート(FPS)が得られます.


リングバッファについて

複数のフレームバッファへ順番に画像データを格納し,格納した順序で読み出します.バッファが1つしかない(EWCLIBの初期設定)ときは,毎回同じバッファを使うため,リングバッファとは呼ばれません.バッファが複数あるときバッファは順番に使われ,最後のバッファまで行くと,再び最初のバッファに戻ってきます.格納した画像データを読み出すときも同様です.リングのように最初と最後がつながった構造で動作するため,リングバッファと呼ばれます.

リングバッファの目的は,画像データの読み出し時期が何らかの理由で一時的に遅れたとしても,リングバッファ内には読み出していない画像データが(しばらくの間は)残っているため,後から急いで読み出せば,コマ落ち(フレーム落ち/ドロップフレームとも呼ばれる)しないで,すべての画像データを読み出せるようにすることです.

EWCLIBでは,ewclib.h のインクルードより前にEWC_BUF_NUMを定義することで,リングバッファに使うバッファ数(枚数)を指定できます.(リングバッファを使うための記述は,これだけです.必要なフレームバッファは自動的に確保されます.)
使用例
#define EWC_BUF_NUM 2    //バッファ数(枚数)を2に設定
#include <ewclib.h>

EWC_BUF_NUMが未定義のとき,デフォルト値としてバッファ数は1となります.

内部処理がリングバッファ仕様になりましたが,画像の更新確認EWC_IsCaptured()や読み出しEWC_GetImage()の使い方はこれまで通りでよく,通常は修正不要のはずです.ただし,これらの関数の引数や戻り値の仕様が若干変更されたので,プログラムソースがそのままでよいか確認してください.

EWC_IsCaptured()の戻り値の仕様が変更され,この関数でコマ落ちの発生を検出できるようになりました.

リングバッファ内が読み出されていない画像データで一杯になるまでは,読み出し時期が遅くなっても耐えられることになります.一杯になった後は,一番古い画像が新しい画像で上書きされます.このとき読み出しポインタの位置は強制的に1つ後になります(バッファ内で最も古いデータから読み出すため).

画像を読み出す平均的な周期が,画像入力の周期より大きければ,バッファの数をいくら多くしても,コマ落ちは避けられません.リングバッファで解決できるのは「瞬間的に」読み出し時期が遅れる場合だけです.バッファ数を大きくするほど,その「瞬間」の長さは大きくなりますが,同時にメモリ消費も大きくなります.

リングバッファを追加したきっかけ
 ノートPCで動作するプログラムの開発中,ある問題の発生がコマ落ちに因るものと判明しました.その原因の1つはLCD表示が一定時間後にオフになる際,メインのスレッドが1秒ほど止められることでしたが,これは自動オフをしない設定にすると解消しました.また別の原因もあり,それはCPU温度が上昇して冷却ファンの回転数が切り替わる際,割り込みが入ってメインのスレッドが十数ミリ秒くらい止められるというものでした.電源管理オプションの変更やWindowsの様々な設定の変更では解消できず,最終的にはフレームレートを80 fpsから60 fpsへ下げ,今回のリングバッファを追加することでコマ落ちの問題がなくなりました.



サンプルプログラム

最も単純なプログラム(コンソールアプリ)

 最も単純なWin32 コンソール アプリケーションの例です.
 画像サイズは320x240ピクセル,フレームレートは30fpsに設定しています.
 カメラを開き,画像を10枚取得したら,カメラを閉じて,終了します.

//2021.5.17
#include <ewclib.h>
int buffer[320*240];
int main(void)
{
    EWC_Open(0, 320, 240, 30.);
    int i= 0;
    for(;;){
        if(EWC_IsCaptured(0)){
            EWC_GetImage(0, buffer);
            //ここでbufferへアクセスすればよい
            printf("i=%d\n",i++);
            if(i==10) break;
        }
    }
    EWC_Close(0);
    return 0;
}



ESPLIBを併用した例

 EWCLIBとESPLIBを使ってカメラ画像を表示する例です.
 1台目のカメラのみ表示します.
 プログラム実行後,Startをクリックしてください.
 カメラを初期化した後,画像の表示が開始されます.Stopのクリックで停止します.
 ESPLIBのインストール方法や使用方法は割愛させていただきます.



//EWCLIBのサンプル(ESPLIB併用) by I.N.
//画像データを取得して表示するだけ
//2010.5.13

#include <esplib.h>
#include <ewclib.h>
#define WX 640
#define WY 480

void ESP_Ready(void)
{
    ESP_CreateImage(0,"Camera",0,0,WX,WY,100);
    ESP_OpenTextWindow(0,86,512,439,135);
    ESP_Printf("Startをクリックしてください.\n");
}

void ESP_Main(void)
{
    ESP_Printf("初期化中...\n");
    int r= EWC_Open(0,WX,WY,30.);
    if(r){
        ESP_Printf("Error %d\n",r);
        return;
    }
    for(;;){
        if(ESP_STOP) break;
        if(EWC_IsCaptured(0)){
            EWC_GetImage(0,ESP_VramPtr[0]);
            ESP_Update_(0);
            ESP_Printf("*");
        }
    }
    EWC_Close(0);
    ESP_Printf("Stopped\n");
}

void ESP_Finish(void)
{
}



対応フォーマットの一覧を表示する例(コンソールアプリ)

 実行すると,まず,EWCLIBで検出されたすべてのカメラについてFriendlyNameおよびDevicePathを表示します.
 続いて,カメラごとにフォーマット(メディアサブタイプ,解像度,ビット数,フレーム周期(単位:100ns),フレームレート)の一覧を表示します.

プログラムソース:
//対応フォーマットの一覧を表示して終了
//2021.05.17 by I.N.
#include <stdio.h>
#include <ewclib.h>

int main(void)
{
        int r;
        int nc; //カメラ数
        ewc_camera stc[10];
        nc= 10; //取得数の上限
        r= EWC_GetCameraName(stc,&nc);
        printf("EWC_GetCameraName()=%d, Number of cameras: %d\n",r,nc);
        if(r) return 1;
        for(int i=0; i<nc; i++){
                printf("%d: %s\n   %s\n", i, stc[i].FriendlyName, stc[i].DevicePath);
        }

        int nf; //フォーマット数
        #define MAXFORMAT 1000                  //取得数の上限
        ewc_format f[MAXFORMAT];

        for(int i=0; i<nc; i++){
            nf= MAXFORMAT;  
            r= EWC_GetFormat(i,f,&nf);      //フォーマット取得
            printf("EWC_GerFormat()=%d, Number of formats=%d\n",r,nf);
            if(r) continue;
              printf("Device %d: '%s'\n", i, stc[i].FriendlyName);
              for(int j=0; j<nf; j++){        //フォーマット一覧の表示
                printf(" %2d: %s %dx%d(%d) %I64d %.4f[fps]\n"
                ,j, f[j].subtype_t, f[j].width, f[j].height, f[j].bit, f[j].AvgTimePerFrame, f[j].fps);
              }
        }

        printf("Hit enter key to end.");
        char s[8];
        fgets(s,sizeof(s),stdin);
        return 0;
}

出力サンプル
EWC_GetCameraName()=0, Number of cameras: 2
0: Logicool HD Webcam C310
   \\?\usb#vid_046d&pid_081b&mi_00#7&189bd067&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\{bbefb6c7-
2fc4-4139-bb8b-a58bba724083}
1: USB_Camera
   \\?\usb#vid_0458&pid_708c&mi_00#7&29a4ead7&2&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global
EWC_GerFormat()=0, Number of formats=38
Device 0: 'Logicool HD Webcam C310'
  0: RGB24 640x480(24) 333333 30.0000[fps]
  1: RGB24 160x120(24) 333333 30.0000[fps]

・・・(途中,省略)

 36: I420 1280x720(12) 333333 30.0000[fps]
 37: I420 1280x960(12) 333333 30.0000[fps]
EWC_GerFormat()=0, Number of formats=16
Device 1: 'USB_Camera'
  0: YUY2 640x480(16) 333333 30.0000[fps]
  1: YUY2 160x120(16) 333333 30.0000[fps]

・・・(途中,省略)

 14: MJPG 1280x720(24) 333333 30.0000[fps]
 15: MJPG 1920x1080(24) 333333 30.0000[fps]
Hit enter key to end.



カメラおよびフォーマットを選択してから画像入力する例

 複数のカメラが検出された場合,その一覧が表示されるので,番号で選択してください(カメラが1台のみの場合は,この選択はありません).
 次に,選択したカメラがサポートするフォーマット(デバイスフォーマットと解像度の組み合わせ)の一覧が表示されるので,
 番号で選択してください.また,FPS値も入力してください.指定されたフォーマットおよびFPSで画像入力を開始します.
 画像フォーマットはRGB32です.
 画像取得が開始すると,テキストウィンドウには,EWC_IsCaptured()の戻り値,同関数の*buffer_r,*frame,*stime,ewc_s[].ftime,*sizeを表示します.このとき,EWC_IsCaptured()の戻り値が2以上だったときは,コマ落ち発生ということで,その行は赤色表示となります.
 画像取得中にPropertyボタンを押すと,プロパティのダイアログが表示されます.
 Pauseボタンを押すと,EWC_Pause()を実行します.
 Runボタンを押すと,EWC_Run()を実行します.
 Stopボタンを押すと,EWC_Stop()を実行します.
 OneShotボタンを押すと,500 ms間隔でEWC_OneShot()を実行します.
 Sleep()ボタンを押すと,50 msのスリープを実行します.
 30 FPS動作でEWC_BUF_NUMを1にして実行すると,リングバッファがないので,50 msのスリープでコマ落ちが発生するのが確認できるでしょう.
 EWCLIBとESPLIBを併用しています.



//まず,カメラが複数あれば,番号で選択
//次に,対応フォーマットの一覧を表示し,番号で選択して画像入力
//2021.05.14 (for EWCLIB 2.8)

#include <esplib.h>
#define EWC_BUF_NUM 3
#include <ewclib.h>

void ESP_Ready(void)
{
        ESP_OpenTextWindow(0,-7,0,512,846);
        ESP_OpenButtonBox(507,0,1,6);
        ESP_ResizeButtonBox(120,238);
        ESP_SetButtonBoxTitle(0,"Property");
        ESP_SetButtonBoxTitle(1,"Pause");
        ESP_SetButtonBoxTitle(2,"Run");
        ESP_SetButtonBoxTitle(3,"Stop");
        ESP_SetButtonBoxTitle(4,"OneShot");
        ESP_SetButtonBoxTitle(5,"Sleep()");
        ESP_PlaceMain(265,878);
        ESP_SetForeground(ESPMAINWINDOW);
        ESP_START= 1;
}

void ESP_Main(void)
{
        char str[10];
        int r;
        int d= 0;       //物理カメラ番号

        ewc_camera ewcc[10];
        int nc= 10;
        EWC_GetCameraName(ewcc,&nc);
        if(nc>=2){
                for(int i=0;i<nc;i++){
                        ESP_Printf("%d: %s\n",i,ewcc[i].FriendlyName);
                }
                ESP_Printf("Select[0-%d]:",nc-1);
                ESP_Input(str);         //カメラを番号で選択
                d= atoi(str);
        }

        #define MAXFORMAT 100   //取得数の上限
        ewc_format f[MAXFORMAT];
        int n= MAXFORMAT;       
        r= EWC_GetFormat(d,f,&n);       //フォーマット取得
        ESP_Printf("EWC_GetFormat()=%d n=%d \n",r,n);
        if(r) return;

        //フォーマット一覧の表示
        for(int i=0; i<n; i++){
                ESP_Printf(" %2d: %s %dx%d(%d) %I64d %.4f[fps]\n"
                ,i, f[i].subtype_t, f[i].width, f[i].height, f[i].bit, f[i].AvgTimePerFrame, f[i].fps);
        }

        ESP_Printf("Select[0-%d]:",n-1);
        ESP_Input(str);         //フォーマットを番号で選択
        int s= atoi(str);
        int wx= f[s].width;
        int wy= f[s].height;
        double fps= f[s].fps;
        ewc_device_type= f[s].subtype; //デバイス出力ピンのフォーマット指定
        ESP_Printf("FPS=");
        ESP_Input(str);         //FPSを入力
        fps= atof(str);

        ESP_CreateImage(0,"Camera",629,0,wx,wy,100);    //ウィンドウ作成

        r=EWC_Open(0,wx,wy,fps,d);      //カメラ使用開始

        ESP_Printf("EWC_Open(0,%d,%d,%f,%d)=%d\n",wx,wy,fps,d,r);
        ESP_Printf("EWC_GetDeviceName():%s\n",EWC_GetDeviceName(0));
        ESP_Printf("EWC_GetDeviceSubtype():%s\n",EWC_GetDeviceSubtype(0));
        ESP_Printf("EWC_GetSubtype():%s\n",EWC_GetSubtype(0));

        int osflag=0;
        DWORD tt;

        //画像入力&表示
        for(;;){
                if(ESP_STOP) break;
                int frm,sel,size;
                double st;

                int ic= EWC_IsCaptured(0,NULL,&size,&frm,&sel,&st);
                if(ic){
                        EWC_GetImage(0,ESP_VramPtr[0]);
                        ESP_Update();
                        int tc= (ic==1) ? 0xffffff : 0xff0000;
                        ESP_SetColor(tc);
                        ESP_Printf("ic=%d sel=%d frm:%d stm:%fs ftm:%fs siz=%d\n"
                            , ic, sel, frm, st, ewc_s[0].ftime, size);
                }
                if(ESP_GetButtonBox(0)) EWC_PropertyPage(0);
                if(ESP_GetButtonBox(1)) EWC_Pause(0), osflag= 0;
                if(ESP_GetButtonBox(2)) EWC_Run(0), osflag= 0;
                if(ESP_GetButtonBox(3)) EWC_Stop(0), osflag= 0;
                //One shot
                if(ESP_GetButtonBox(4)){
                        EWC_OneShot(0);
                        EWC_GetImage(0,ESP_VramPtr[0]);
                        ESP_Update();
                        osflag= 1;
                        tt= GetTickCount();
                }
                if(ESP_GetButtonBox(5)) Sleep(50);

                if(osflag){
                        if(GetTickCount()-tt>500){
                                ESP_SetButtonBox(4);
                        }
                }

                Sleep(1);
        }

        r= EWC_Close(0);                //カメラ終了
        ESP_Printf("EWC_Close(0)=%d\n\n",r);
        ESP_DestroyImage(0);    //ウィンドウ終了
}

void ESP_Finish(void)
{
}



NV12出力のカメラを使う例

 色々試しましたが,デバイスフォーマットがNV12の場合,どうやってもRGB32への変換を自動的に行うことはできませんでした.
 サンプルされたデータをそのままバッファへ格納してから,ユーザ側で,NV12からRGB32へ変換することで画像を取得・表示できました.
 サンプルされたデータをそのまま格納するには,EWC_Open()の前に EWC_RawMode(*, 1); を書いておきます.
 また,NV12からRGB32への変換のために,EWC_CnvNV12toRGB32()を用意しました.なお,この変換はソフトウェア処理のため,
 その分の処理時間が必要となります.下のサンプルプログラムは,Cam Link 4Kで動作を確認しました.
 デバイスフォーマットがY16やY800の場合も,こんな感じで画像取得が行えます.

//NV12カメラの画像入力
//2021.04.20 (for EWCLIB 2.7)
#include <esplib.h>
#include <ewclib.h>
int wx= 1920;
int wy= 1080;
int fps= 60;
int zoom= 50;

void ESP_Ready(void)
{
        ESP_CreateImage(0,"Camera",459,0,wx,wy,zoom);
        ESP_OpenTextWindow(0,-7,0,464,540);
        ESP_OpenButtonBox(314,572,1,1);
        ESP_ResizeButtonBox(143,51);
        ESP_SetButtonBoxTitle(0,"Property");
        ESP_PlaceMain(-7,572);
        ESP_SetForeground(ESPMAINWINDOW);
        ESP_START= 1;
}

void ESP_Main(void)
{
        EWC_RawMode(0,1);     //NV12のときは必要
        int r= EWC_Open(0,wx,wy,fps,0,MEDIASUBTYPE_NV12,MEDIASUBTYPE_NV12);
        if(r){
                ESP_Printf("errcode=%d\n",r);
                return;
        }
        int size= EWC_GetBufferSize(0);
        unsigned char *buf= new byte [size];
        ESP_Printf("Camera opened (buffer size= %d)\n",size);

        for(;;){
                if(ESP_STOP) break;
                int ic= EWC_IsCaptured(0);
                if(ic){
                        EWC_GetImage(0,buf);
                        EWC_CnvNV12toRGB32(ESP_VramPtr[0],buf,wx,wy);
                        ESP_Update();
                        ESP_Printf("ic=%d period=%f[ms]\n",ic,ewc_s[0].ftime);
                }
                if(ESP_GetButtonBox(0)) EWC_PropertyPage(0);
        }

        delete[] buf;
        EWC_Close(0);
        ESP_Printf("Camera closed\n");
}

void ESP_Finish(void)
{
}



MJPGのデータをそのまま取得する例1(コンソールアプリ)

 MJPG(MEDIASUBTYPE_MJPG)では毎回取得される画像のフォーマットがJPEGとなっています.
 そのため,データのバイト数は毎回異なります.EWCLIB 2.8より,EWC_IsCaptured()の引数でこのデータの
 バイト数が取得できるようになりました.
 ただし,JPEGデータのデコードはEWCLIBでは用意していませんので,何か別のソフトを使ってください.
 以下のサンプルでは,rawモードで画像データをそのまま取得し,jpeg画像ファイルとして保存する例です.
 なお,MJPG出力に対応するカメラ(BSW200MBK,c922等)が必要です.

// MJPGのまま画像データを取得するサンプル1
// 連続10フレーム取得し,最後の1枚のみファイル(.jpg)保存
// (コンソールアプリ)
// 2021.05.14 for EWCLIB 2.8

#include <ewclib.h>
int wx= 640;
int wy= 480;
double fps= 30.0;

int main(void)
{
        EWC_RawMode(0,1);
        int r= EWC_Open(0,wx,wy,fps,0,MEDIASUBTYPE_MJPG,MEDIASUBTYPE_MJPG);
        printf("EWC_Open()=%d\n",r);
        if(r) return 1;

        BYTE *buf= new BYTE[sizeof(int)*wx*wy]; //大きめのサイズで確保

        for(int i=0; i<10;){
                int size,frame;
                int rtn= EWC_IsCaptured(0,NULL,&size,&frame);
                if(rtn){
                        EWC_GetImage(0,buf);    //画像データをbufへコピー
                        printf("%d: rtn=%d frame=%d size=%d\n",i,rtn,frame,size);
                        //最後の1枚だけファイル保存
                        if(i==9){       
                                char name[32];
                                sprintf_s(name,sizeof(name),"test%04d.jpg",i);
                                FILE* fp;
                                fopen_s(&fp,name,"wb");
                                fwrite(buf,size,1,fp);
                                fclose(fp);
                                printf("[%s] saved.\n",name);
                        }
                        i++;
                }
        }

        delete[] buf;
        EWC_Close(0);
        return 0;
}



MJPGのデータをそのまま取得する例2(コンソールアプリ)

 上の例1と同じ結果ですが,EWC_SetBuffer()とリングバッファ(3枚)を組み合わせた場合の例です.
 EWC_SetBuffer()を使うと,画像データの転送が省略できます(コールバック関数内で行われる1回だけで済む).
 あと,2枚以上のリングバッファでは,画像フォーマットにかかわらず常にRGB32のサイズで自前バッファを用意しなければならない仕様となっている点に注意して下さい.
 さらに,データサイズをEWC_IsCaptured()で取得するのは例1と同じですが,リングバッファ内のアドレスも同じEWC_IsCaptured()で取得している点に注意してください.

// MJPGのまま画像データを取得するサンプル2
// (EWC_BUF_NUMとEWC_SetBuffer()の使用例)
// 2021.05.14 for EWCLIB 2.8

#define EWC_BUF_NUM 3   //バッファ数
#include <ewclib.h>
int wx= 640;
int wy= 480;
double fps= 30.0;

int main(void)
{
        EWC_RawMode(0,1);
        int r= EWC_Open(0,wx,wy,fps,0,MEDIASUBTYPE_MJPG,MEDIASUBTYPE_MJPG);
        printf("EWC_Open()=%d\n",r);
        if(r) return 1;
        
        //バッファ数が2以上のとき1枚のサイズはRGB32相当で自前バッファを用意する
        BYTE *my_buf= new BYTE[EWC_BUF_NUM*sizeof(int)*wx*wy];
        EWC_SetBuffer(0,my_buf);
        
        for(int i=0; i<10;){
                //バッファ数が2以上のときは,データのアドレスは毎回異なるので
                //bufのアドレスをEWC_IsCaptured()へ渡して,データの格納先を取得する
                int size,frame,sel;
                BYTE *buf;
                int rtn= EWC_IsCaptured(0,&buf,&size,&frame,&sel);

                if(rtn){
                      //この時点で画像データはmy_bufの(sel+1)番目へ既に格納済み
                      //よって,画像データのコピーは不要
                        
                      EWC_BufferLock(0);      //コールバック関数での書き換えを保留させるため
                        
                      //画像処理はここで行う
                      //例として,最後の1枚だけファイル保存
                      printf("%d: rtn=%d frame=%d size=%d buf=%p sel=%d\n",i,rtn,frame,size,buf,sel);
                      if(i==9){       
                            char name[32];
                            sprintf_s(name,sizeof(name),"test%04d.jpg",i);
                            FILE* fp;
                            fopen_s(&fp,name,"wb");
                            fwrite(buf,size,1,fp);
                            fclose(fp);
                            printf("[%s] saved.\n",name);
                      }
                        
                      EWC_BufferUnlock(0);    //バッファの使用終了およびバッファ管理情報の更新
                      i++;
                }
        }

        EWC_Close(0);           //自前バッファの削除より先にカメラをクローズ
        delete[] my_buf;
        return 0;
}



各種設定の変更を行う例

 カメラの各種プロパティの表示と変更が行えます.
 また,EWC_SaveProperty()EWC_LoadProperty()による設定値の保存,読み込みも試せます.
 ESPLIB(ver.7.9以降推奨)を併用しています.



//EWCLIBサンプル(各種設定, PropertyPage, Save, Load)
//2014.04.21 EWCLIB 2.4
//2018.05.29 EWCLIB 2.5
//2020.06.26 EWCLIB 2.6
//2021.05.14 EWCLIB 2.8

#include <esplib.h>
#include <ewclib.h>

const char *itemtitle[17]={
    "BRIGHTNESS","CONTRAST","HUE","SATURATION","SHARPNESS",
    "GAMMA","COLORENABLE","WHITEBALANCE","BACKLIGHTCOMPENSATION","GAIN",
    "PAN","TILT","ROLL","ZOOM","EXPOSURE","IRIS","FOCUS"
};

//設定の読み出し
void read_value(void)
{
    for(int i=0;i<17;i++){
        int mode=0;
        double v=EWC_GetValue(0,i,&mode);
        ESP_SetInputBoxD(i,v);
        char s[256];
        strcpy_s(s,256,itemtitle[i]);
        if(mode) strcat_s(s,256," [Auto]");else strcat_s(s,256,"        ");
        ESP_SetInputBoxTitle(i,s);
    }
}

void ESP_Ready(void)
{
    // [Image Window]
    ESP_CreateImage(0,"Camera 320x240",0,0,320,240,100);
    // [Text Window]
    ESP_OpenTextWindow(0,0,278,374,190);
    ESP_OpenTextWindow(1,0,506,374,154);
    // [Input Box]
    ESP_OpenInputBox(390,0,17);
    ESP_ResizeInputBox(198,162);
    // [Button Box]
    ESP_OpenButtonBox(778,0,3,18);
    ESP_ResizeButtonBox(270,508);
    for(int i=0;i<17;i++){
        ESP_SetButtonBoxTitle(3*i+0,"変更");
        ESP_SetButtonBoxTitle(3*i+1,"初期値");
        ESP_SetButtonBoxTitle(3*i+2,"自動/手動");
    }
    ESP_SetButtonBoxTitle(51,"Property");
    ESP_SetButtonBoxTitle(52,"Save");
    ESP_SetButtonBoxTitle(53,"Load");
    // [Main Window]
    ESP_PlaceMain(433,540);
    ESP_SetForeground(ESPMAINWINDOW);
    ESP_SelectTW(0);

    ESP_Printf("カメラ初期化中...\n");
    int r=EWC_Open(0,320,240,30);
    if(r){
        ESP_Printf("Error %d\n",r);
        return;
    }
    ESP_Printf("デバイス名:%s\n",EWC_GetDeviceName(0));

    ESP_START=1;
}

void ESP_Main(void)
{
    int en=0;
    char s[256];
    double t=0.;

    EWC_Run(0);
    ESP_Printf("Run\n");
    read_value();    //設定の読み出し

    for(;;){
        if(ESP_STOP)break;

        ESP_SelectTW(1);
        int ct;
        double st;
        if(EWC_IsCaptured(0,NULL,NULL,&ct,NULL,&st)){
            EWC_GetImage(0,ESP_VramPtr[0]);     //画像取得
            ESP_Update_(0);                     //画像更新
            ESP_Printf("count=%d stime=%f rate=%4.2f\n",ct,st,1.0/ewc_s[0].ftime);
        }
        ESP_UnSelectTW();

        if(ESP_GetButtonBox(51)) EWC_PropertyPage(0), read_value();
        if(ESP_GetButtonBox(52)){
            ESP_Printf("Save...%s\n",EWC_SaveProperty(0)?"NG":"OK");
        }
        if(ESP_GetButtonBox(53)){
            ESP_Printf("Load...%s\n",EWC_LoadProperty(0)?"NG":"OK");
            read_value();
        }

        for(int b=0;b<51;b++){
            //ボタンが押されたとき
            if(ESP_GetButtonBox(b)){
                int r;
                int item=b/3;
                switch(b%3){
                    case 0:
                        r=EWC_SetValue(0,item,ESP_GetInputBoxD(item));
                        break;
                    case 1:
                        r=EWC_SetDefault(0,item);
                        break;
                    case 2:
                        int mode;
                        EWC_GetValue(0,item,&mode);
                        if(mode) r=EWC_SetManual(0,item);
                        else r=EWC_SetAuto(0,item);
                        break;
                }
                //メッセージの表示
                en++;
                if(r>=4){
                    ESP_Printf("[%d]",en);
                    EWC_GetLastMessage(s,256);
                    ESP_Printf("%s",s);
                }else if(r==3){
                    ESP_Printf("[%d]この機能はサポートされていません\n",en);
                }else if(r>0){
                    ESP_Printf("[%d]エラー\n",en);
                }else{
                    ESP_Printf("[%d]OK\n",en);
                }
                read_value();
            }
        }
    }
    EWC_Stop(0);
    ESP_Printf("Stop\n");
}

void ESP_Finish(void)
{
    EWC_Close(0);
}



3台までのカメラ画像を表示する例

 カメラ3台まで表示します.
 カメラ毎に動作の停止と再開,プロパティページの起動が行えます.
 EWCLIBとESPLIBを使用しています.



//カメラ3台まで表示
//2021.04.19 by I.N. (for EWCLIB 2.7)
#include <esplib.h>
#include <ewclib.h>
#define N 3
#define WX 320
#define WY 240

void ESP_Ready(void)
{
    // [Image Window]
    ESP_CreateImage(0,"Camera 0", -7, 0,320,240,100);
    ESP_CreateImage(1,"Camera 1",315, 0,320,240,100);
    ESP_CreateImage(2,"Camera 2",637, 0,320,240,100);
    // [Text Window]
    ESP_OpenTextWindow(0,637,272,208,237);
    // [Button Box]
    ESP_OpenButtonBox(289,272,2,3);
    ESP_ResizeButtonBox(189, 155);
    ESP_SetButtonBoxTitle(0,"#0\nRun/Stop");
    ESP_SetButtonBoxTitle(1,"Property");
    ESP_SetButtonBoxTitle(2,"#1\nRun/Stop");
    ESP_SetButtonBoxTitle(3,"Property");
    ESP_SetButtonBoxTitle(4,"#2\nRun/Stop");
    ESP_SetButtonBoxTitle(5,"Property");
    // [Main Window]
    ESP_PlaceMain(-7,272);
    ESP_SetForeground(ESPMAINWINDOW);

    ESP_Printf("EWC_GetCamera()=%d\n", EWC_GetCamera());
    ESP_Printf("Click 'Start'.\n");
}

void ESP_Main(void)
{
    int tgl[N],r[N];
    double fps[N];

    ESP_Printf("Starting...\n");
    r[0]= EWC_Open(0,320,240,30);
    r[1]= EWC_Open(1);
    r[2]= EWC_Open(2);

    for(int i=0; i<N; i++){
        ESP_Printf("EWC_Open(%d)=%d\n", i, r[i]);
        tgl[i]= 1;
        fps[i]= 0;
    }

    for(;;){
        if(ESP_STOP) break;

        int f= 0;
        for(int i=0; i<N; i++){
            if(EWC_IsCaptured(i)){
                EWC_GetImage(i, ESP_VramPtr[i]);
                ESP_Update_(i);
                fps[i]= 1. /ewc_s[i].ftime;
                f++;
            }
        }
        if(f) ESP_Printf("FPS: %5.1f %5.1f %5.1f\n", fps[0], fps[1], fps[2]);

        for(int i=0; i<N; i++){
            if(ESP_GetButtonBox(i*2)) {
                if(tgl[i]) EWC_Stop(i); else EWC_Run(i);
                tgl[i]= 1 -tgl[i];
            }
            if(ESP_GetButtonBox(i*2+1)) EWC_PropertyPage(i);
        }
    }

    EWC_CloseAll();
    ESP_Printf("fin.\n");
}

void ESP_Finish(void)
{
}



300フレーム遅れた映像を表示する例

 300フレーム(10秒)遅れたカメラ映像を表示します.
 EWCLIBとESPLIBを使用しています.
 プログラムは短いですが,メモリは400MBくらい消費します.

// 10秒遅延したカメラ映像を実現するプログラム
// (300フレーム(10秒)だと,メモリを400MBくらい消費する!)
// 2009.04.30 ver.1.0
// 2010.05.12 ver.1.1  EWCLIB2.0対応版
// 2020.06.26 ver.1.2  EWCLIB2.6対応版

#include <esplib.h>
#include <ewclib.h>

#define FRAMES 300
#define WX 640
#define WY 480
int img[FRAMES][WX*WY];
 
void ESP_Ready(void)
{
        ESP_CreateImage(0,"Camera",0,0,640,480,100);
        ESP_OpenTextWindow(0,40,512,536,162);
        ESP_PlaceMain(606,561);
        ESP_SetForeground(ESPMAINWINDOW);

    ESP_Printf("Startをクリックしてください\n");
}

void ESP_Main(void)
{
    int w= 0;   // これから書き込むフレーム番号[0〜(FRAMES-1)]
    int r= 0;   // これから読み出すフレーム番号[0〜(FRAMES-1)]

    ESP_Printf("カメラ初期化中...");
    int t= EWC_Open(0,WX,WY,30.);
    ESP_Printf("戻り値:%d\n",r);
    if(r) return;

    for(;;){
        // 新しいフレームが来るまで待つ
        for(;;){
            if(EWC_IsCaptured(0)){
                EWC_GetImage(0,img[w]);
                break;
            }
            if(ESP_STOP) break;
            Sleep(0);
        }
        if(ESP_STOP) break;

        // フレーム番号 w の表示
        ESP_Locate(0,2);
        ESP_Printf("w=%03d\n",w);

        w= (w+1)%FRAMES;    // wは0〜(FRAMES-1)を繰り返す
        r= w;               // rには最も古いフレーム番号を指定する
        CopyMemory(ESP_VramPtr[0],img[r],WX*WY*4); 
        ESP_Update_(0);

        // フレーム番号 r の表示
        ESP_Printf("r=%03d\n",r);
    }
    ESP_Printf("カメラ終了中...");
    t= EWC_Close(0);
    ESP_Printf("戻り値:%d\n",t);
}

void ESP_Finish(void)
{
}



CPU使用率を下げた低速度な画像入力

 EWC_OneShot()を利用した,低速度(周期:約1秒)な画像入力の例です.
 画像入力時以外はキャプチャがポーズ状態になるためCPU使用率が下がります.
 ESPLIBを併用しています.

 プログラム起動後,「Interval 1s」ボタンをクリックすると約1秒周期の画像取得となります.



//EWC_OneShot()のサンプル
//2014.4.17 (EWCLIB 2.4)
#include <esplib.h>
#include <ewclib.h>

#define INTERVAL 1000    //取得間隔(ms)

void ESP_Ready(void)
{
    ESP_CreateImage(0,"Camera",0,0,640,480,100);
    ESP_OpenTextWindow(0,656,0,323,235);
    ESP_OpenButtonBox(669,278,1,5);
    ESP_SetButtonBoxTitle(0,"Property");
    ESP_SetButtonBoxTitle(1,"Pause");
    ESP_SetButtonBoxTitle(2,"Run");
    ESP_SetButtonBoxTitle(3,"Stop");
    ESP_SetButtonBoxTitle(4,"Interval 1s");
    ESP_PlaceMain(662,476);
    ESP_SetForeground(ESPMAINWINDOW);
    ESP_START=1;
}

void ESP_Main(void)
{
    int r;
    r= EWC_Open(0);
    ESP_Printf("EWC_Open(0)=%d\n",r);
    if(r) return;

    int updf=0;  //画像更新フラグ
    int osf=0;   //OneShot連続フラグ
    DWORD t;     //時刻(ms)用

    for(;;){     //画像入力&表示
        if(ESP_STOP) break;
        Sleep(1);    //処理が何もないときはこれでCPU使用率を下げる

        if(ESP_GetButtonBox(0)) EWC_PropertyPage(0);
        if(ESP_GetButtonBox(1)) EWC_Pause(0), osf=0;
        if(ESP_GetButtonBox(2)) EWC_Run(0), osf=0;
        if(ESP_GetButtonBox(3)) EWC_Stop(0), osf=0;
        if(ESP_GetButtonBox(4)) EWC_OneShot(0), updf=1, osf=1, t=GetTickCount();

        if(osf && GetTickCount()-t >= INTERVAL) ESP_SetButtonBox(4);  //4:Intervalボタン

        if(!osf && EWC_IsCaptured(0)) updf=1;    //画像が来た
        
        if(updf){    //画像更新
            EWC_GetImage(0,ESP_VramPtr[0]);
            ESP_Update();
            ESP_Printf("*");
            updf=0;
        }
    }

    r= EWC_Close(0);
    ESP_Printf("\nEWC_Close(0)=%d\n",r);
}

void ESP_Finish(void)
{
}



OpenCVと組み合わせて使用した例

 EWCLIBとOpenCVを使って,カメラ画像を入力し処理するプログラム例です.
 OpenCVの関数を利用して特徴点(Harris)を抽出します.
 アプリケーションの種類は,Win32 コンソール アプリケーションを指定してください.
 OpenCVのインストール方法や使用方法は割愛させていただきます.



//EWCLIBとOpenCVを使って,USBカメラ画像を入力し処理するプログラム例
//  by I.N.
//動作確認ソフト:
//  Windows XP Professional SP3
//  Visual C++ 2008 Professional
//  EWCLIB 2.0
//  OpenCV 2.1.0
//履歴:
//  2009.04.24 ver.1.0 動作確認
//  2010.05.12 ver.1.1 EWCLIB2.0/OpenCV2.1対応版

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#pragma comment(lib, "cv210.lib") 
#pragma comment(lib, "cxcore210.lib") 
#pragma comment(lib, "highgui210.lib") 

#include <ewclib.h>     //cv.hより後でインクルードする
#define WX 640
#define WY 480
#define FPS 30

int main(void)
{
        char *winc="Camera";    //ウィンドウの名前
        char *win1="Image1";

        int r=EWC_Open(0,WX,WY,FPS);    //カメラ初期化
        if(r){
                printf("カメラを初期化できません(%d)\n",r);
                return 1;
        }

        cvNamedWindow(win1,CV_WINDOW_AUTOSIZE); //ウィンドウ作成
        cvMoveWindow(win1,0,0);

        IplImage *imgc=cvCreateImage(cvSize(WX,WY),8,3);        //画像作成(カラー用)
        IplImage *img1=cvCreateImage(cvSize(WX,WY),8,1);        //画像作成(グレー用)
        IplImage *img2;

        EWC_SetBuffer(0,imgc->imageData);       //カメラ画像格納先の変更

        //特徴点抽出用
        #define CNTMAX 128
        CvPoint2D32f ppts[CNTMAX];
        IplImage *imge=cvCreateImage(cvSize(WX,WY),32,1);
        IplImage *imgt=cvCreateImage(cvSize(WX,WY),32,1);

        //処理ループ
        while(1){
                int key=cvWaitKey(1);
                if (key==0x1B) break;           //ESCキーで終了

                if (EWC_IsCaptured(0)){
                        cvCvtColor(imgc,img1,CV_BGR2GRAY);      //カラーからグレーへ変換

                        //特徴点(Harris)抽出
                        int cnt=CNTMAX;
                        cvGoodFeaturesToTrack(img1,imge,imgt,ppts,&cnt,0.1,15,NULL,3,1,0.01);
                        cvFindCornerSubPix(img1,ppts,cnt,cvSize(3,3),cvSize(-1,-1),
                                cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03));
                        //描画
                        img2=cvCloneImage(imgc);
                        for (int i=0;i<cnt;i++) cvCircle(img2,cvPointFrom32f(ppts[i]),3,CV_RGB(255,0,0),2);
 
                        cvShowImage(win1,img2);         //処理した画像の表示
                        cvReleaseImage(&img2);
                }

        }

        //終了処理
        EWC_Close(0);
        cvReleaseImage(&imgt);
        cvReleaseImage(&imge);
        cvReleaseImage(&img1);
        cvReleaseImage(&imgc);
        cvDestroyWindow(win1);

        return 0;
}




OpenCV&ESPLIBと組み合わせて使用した例

 OpenCVとESPLIBとEWCLIBを使って,カメラ画像を入力し処理するプログラム例です.
 OpenCVの関数を利用して特徴点(Harris)を抽出します.
 アプリケーションの種類は,Win32 アプリケーションを指定してください.
 OpenCVやESPLIBのインストール方法や使用方法は割愛させていただきます.



//OpenCV,EWCLIB,ESPLIBを使って,USBカメラ画像を入力し処理するプログラム例
//  by I.N.
//動作確認ソフト:
//  Windows XP Professional SP3
//  Visual C++ 2008 Professional
//  OpenCV 2.1.0
//  EWCLIB 2.0
//  ESPLIB 7.4
//履歴:
//  2009.05.01 ver.1.0 動作確認
//  2010.05.12 ver.1.1 EWCLIB2.0/OpenCV2.1対応版

#include <cv.h>
#include <cxcore.h>
#pragma comment(lib, "cv210.lib") 
#pragma comment(lib, "cxcore210.lib") 

#include <esplib.h>
#include <ewclib.h>     //cv.hより後でインクルードする
#define WX 640
#define WY 480
#define FPS 30

void ESP_Ready(void)
{
        ESP_CreateImage(0,"Camera",0,0,WX,WY,100);
        ESP_OpenTextWindow(0,672,0,152,469);
        ESP_SetForeground(ESPMAINWINDOW);
        ESP_Printf("Startをクリック\n");
}

void ESP_Main(void)
{
        int t,t0;
        int r=EWC_Open(0,WX,WY,FPS);    //カメラ初期化
        if(r) {ESP_Printf("カメラを初期化できません(%d)\n",r); return;}

        IplImage *imgc=cvCreateImage(cvSize(WX,WY),8,3);        //画像(カメラ画像用)
        IplImage *img1=cvCreateImage(cvSize(WX,WY),8,1);        //画像(グレー用)
        IplImage *img2=NULL;

        EWC_SetBuffer(0,imgc->imageData);       //カメラ画像格納先の変更

        //特徴点抽出用
        #define CNTMAX 100
        CvPoint2D32f ppts[CNTMAX];
        IplImage *imge=cvCreateImage(cvSize(WX,WY),32,1);
        IplImage *imgt=cvCreateImage(cvSize(WX,WY),32,1);

        ESP_StartClock();
        //処理ループ
        while(1){
                if(ESP_STOP) break;

                if (EWC_IsCaptured(0)){
                        t0=ESP_GetClock();
                        cvCvtColor(imgc,img1,CV_BGR2GRAY);      //カラーからグレーへ変換

                        //特徴点(Harris)抽出
                        int cnt=CNTMAX;
                        cvGoodFeaturesToTrack(img1,imge,imgt,ppts,&cnt,0.1,5,NULL,3,1,0.01);
                        cvFindCornerSubPix(img1,ppts,cnt,cvSize(3,3),cvSize(-1,-1),
                                cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03));

                        //描画
                        img2=cvCloneImage(imgc);
                        for (int i=0;i<cnt;i++) cvCircle(img2,cvPointFrom32f(ppts[i]),3,CV_RGB(255,0,0),2);
                        EWC_Cnv24to32(ESP_VramPtr[0],(unsigned char*)img2->imageData,WX*WY);

                        ESP_Update_(0);
                        cvReleaseImage(&img2);
                        
                        //周期の表示
                        t=ESP_GetClock();
                        ESP_Printf("t=%dms\n",t-t0);
                        t0=t;
                }
        }

        //終了処理
        EWC_Close(0);
        cvReleaseImage(&imgt);
        cvReleaseImage(&imge);
        cvReleaseImage(&img1);
        cvReleaseImage(&imgc);
        ESP_Printf("Stopped");
}

void ESP_Finish(void)
{
}




関数リファレンス

基本関数

<1.デバイス番号指定>
int EWC_Open(int num, int wx=0, int wy=0, double fps=0, int device=-1, GUID mstype=ewc_type, GUID dev_mstype=ewc_device_type);
<2.デバイス名指定>
int EWC_Open(int num, int wx, int wy, double fps, char *devicename, GUID mstype=ewc_type, GUID dev_mstype=ewc_device_type);
<3.デバイス名指定(wx/wy/fps省略)>
int EWC_Open(int num, char *devicename, GUID mstype=ewc_type, GUID dev_mstype=ewc_device_type);
説明
 カメラの使用を開始します.カメラ毎に最初に呼びます.
 EWCLIBで使用できるカメラの台数や名前を事前に知りたいときは,EWC_GetCamera()EWC_GetCameraName()が使えます.
 新しい画像が読み出せる状態になったかどうかを知るにはEWC_IsCaptured()を使います.
 画像データを取得(データ転送)するにはEWC_GetImage()を使います.
 カメラの使用が終わったらEWC_Close()またはEWC_CloseAll()で終了処理を行ってください.
引数
 num:論理カメラ番号(0〜9)
   EWCLIBの各関数でカメラを指定するため使う番号(任意)を設定します.
   この論理カメラ番号は,必ずしも0から順に詰めて使う必要はありません.
   実際に使用される物理デバイス(カメラ)は,numに関わらず,見つかったものから順に割り当てられます.
   物理デバイスを指定する場合は,引数deviceや引数devicenameを使用してください.
 wx,wy:画像サイズ(幅および高さ) [単位:ピクセル](この引数はオプション)
   カメラによって利用できる解像度は異なります.
   利用できない解像度を指定した場合,エラー終了となります.
   代表的なサイズとしては160x120,320x240,640x480があります.
   利用できる解像度の情報を取得するためにEWC_GetFormat()が用意されています.
   省略時あるいは0を指定した場合,1つ前のEWC_Open()で設定された値が適用されます.
   ただし,初めてEWC_Open()が呼ばれる場合のデフォルト値は640x480です.
   また,ここに指定されたものは,以降のEWC_Open()のデフォルト値となります.
 fps:フレームレート(この引数はオプション)
   使用するカメラによって利用できるフレームレートは異なります.
   指定した通りのフレームレートが得られるとは限りませんので注意してください.
   利用できないフレームレートを指定した場合,エラー終了となります.
   代表的なフレームレートは30や29.97や15ですが,任意の値を設定できます.
   省略時あるいは0を指定した場合,1つ前のEWC_Open()で設定された値が適用されます.
   ただし,初めてEWC_Open()が呼ばれる場合のデフォルト値は30です.
   また,ここに指定されたものは,以降のEWC_Open()のデフォルト値となります.
 device:実際に対応するカメラの物理番号(この引数はオプション)
   複数のカメラが接続されている場合で,論理カメラ番号numに対応する実際のカメラを指定する場合に使います.
   物理番号は見つかったものから順に0,1,2...と割り振られています.
   省略時あるいは-1が指定された場合,未使用のもので若い番号から使用されていきます.
   なお,EWC_GetDeviceName()を使うと使用開始されたカメラのデバイス名が取得できます.
 devicename:実際に対応するカメラのデバイス名(この引数はオプション)
   論理カメラ番号numに対応する,実際のカメラを指定する場合に使います.
   デバイス名は,Windowsデバイスマネージャーのイメージングデバイス等に表示されています.
   ここに指定した文字列を含むカメラが見つかった場合,使用されます.(照合にはstrstr()が使われる)
   同じデバイス名が複数あれば,見つかった順で,未使用のものから使われます.
   なお,EWC_GetDeviceName()を使うと使用開始されたカメラのデバイス名が取得できます.
 mstype:画像フォーマット(この引数はオプション)
   デフォルトの画像フォーマットから変更したい場合,この引数を使います.
   カメラ毎に異なる画像フォーマットを指定することができます.
   ここに指定されたものは,以降のEWC_Open()のデフォルト値となります.
   この引数を使わずに,グローバル変数ewc_typeで指定する方法もあります.
 dev_mstype:デバイスフォーマット(この引数はオプション)
   デフォルトのデバイスフォーマットから変更したい場合,この引数を使います.
   デフォルトのデバイスフォーマットは,カメラがサポートするフォーマットの中で最初に登録されているものであり,
   カメラによって異なります.
   利用できるデバイスフォーマットに関する情報を知りたい場合はEWC_GetFormat()を使います.
   この引数を使わなずに,グローバル変数ewc_device_typeで指定する方法もあります.
戻り値
 0:正常終了
 0以外:エラー終了
使用例
 EWC_Open(0); //画像サイズ,FPS等はデフォルト値(640,480,30)を使用
 EWC_Open(0, 320, 240, 30); //画像サイズ,FPSを指定
 EWC_Open(0, 320, 240, 30, 1); //対応カメラは2番目を指定(2台以上の接続が前提)
 EWC_Open(0, 0, 0, 0, -1, MEDIASUBTYPE_RGB24); //画像フォーマットのみ指定,あとはデフォルト
 EWC_Open(0, "HD Pro Webcam C920"); //デバイス名のみ指定
 EWC_Open(0, 320, 240, 30, "USB2.0 Camera"); //画像サイズ,FPS,デバイス名を指定
 <複数カメラの2台目以降が同じ設定なら,引数は省略できます>
 EWC_Open(0, 320, 240, 30, 0, MEDISUBTYPE_RGB24);
 EWC_Open(1);
 EWC_Open(2);


int EWC_Close(int num);
int EWC_CloseAll(void);
説明

 終了処理を行います.カメラの使用を終了させるため最後に1回呼びます.
 カメラ毎に行うのがEWC_Close()です.また,EWC_Open()で開始された使用中のカメラをまとめて終了させるのがEWC_CloseAll()です.
 この関数が実行されるまでは,他のアプリケーションはそのカメラにアクセスできません.
 EWC_CloseAll()はEWC_Open()により開始された順番の逆順で終了処理を行います.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない
 上記以外:エラー終了
使用例
 EWC_Close(0);
 EWC_CloseAll();


int EWC_IsCaptured(int num, BYTE **buffer=NULL, int *size=NULL, int *frame=NULL, int *buffer_r=NULL, double *stime=NULL);
説明

 現時点でEWC_GetImage()によって読み出すことができる画像のフレーム番号と前回読み出した画像のフレーム番号との差を返します.
 新しい画像データが到着していない場合,この関数は0を返します.
 この関数の戻り値が1以上であることを確認した後,EWC_GetImage()を使って画像データを読み出す(データ転送),というのが標準的な流れです.
 また,戻り値が1のとき,前回の読み出しからコマ落ちなしで次の画像データを読み出せることを意味します.
 また仮に,戻り値が2であれば,これから読み出す画像は前回読み出した画像から2フレーム後の画像になることを意味します(1フレーム落とした).
 bufferに0以外の有効なポインタを渡すと,読み出す画像データの先頭アドレスを取得できます.ただし,EWC_GetImage()を使う限り,先頭アドレスを知る必要は生じません.
 sizeに0以外の有効なポインタを渡すと,読み出す画像データのサイズ(バイト数)を取得できます.MJPGをrawモードで読み出す場合は,画像が圧縮されていてデータサイズは毎回異なるため,この情報が必要となります.
 frameに0以外の有効なポインタを渡すと,フレーム番号を取得できます.読み出す画像のフレーム番号を知りたいとき使います.フレーム番号は新しい画像が到着するたびに1ずつ増加する値です.
 buffer_r に0以外の有効なポインタを渡すと,リングバッファの何番目であるかを知ることができます.例えば,バッファ数が3のとき,*buffer_r の値は 0, 1, 2 のいずれかになります.
 stimeに0以外の有効なポインタを渡すと,画像がサンプルされた時刻(秒)の情報を取得できます.サンプル時刻はその画像が取得された(カメラをオープンした時からの)時間です.
引数
 num:論理カメラ番号(0〜9)
 buffer:データ先頭アドレスを格納するBYTEポインタ型変数へのポインタ(この引数はオプション)
 size:データサイズ(単位:バイト)を格納するint型変数へのポインタ(この引数はオプション)
 frame:フレーム番号を格納するint型変数へのポインタ(この引数はオプション)
 buffer_r:リングバッファの読み出し番号を格納するint型変数へのポインタ(この引数はオプション)
 stime:サンプル時刻(単位:秒)を格納するdouble型変数へのポインタ(この引数はオプション)
戻り値
 0:新しい画像データはまだ来ていません or 引数numの値が不正です
 1以上:新しい画像データが到着しています.
使用例
 while(1){
  if(EWC_IsCaptured(0)){
   // ここで画像データの読み出し,および,画像処理など
  }
 }
使用例
 BYTE* buf;
 int size,frm,sel;
 double st;
 int n= EWC_IsCaptured(0, &buf, &size, &frm, &sel, &st);


int EWC_GetImage(int num, void *buffer);
説明

 カメラの画像データを取得します.
 EWCLIB内部にあるフレームバッファ(リングバッファ)から buffer へ画像データをコピーします.
 このとき,MJPGのような毎回バイト数が異なる画像フォーマットでも過不足なくコピーします.ただし,バイト数はこの関数では分からないので,EWC_IsCaptured()でバイト数情報は取得してください.
 また,その後,1フレームを読み出したとして,リングバッファの管理情報を更新します.
 bufferが0(NULL)の場合,画像データの転送は省略し,バッファの管理情報の更新のみ行います.
 EWC_SetBuffer()によって画像データ転送先の変更が行われている場合,この関数を使用する必要はなくなります.
 EWC_SetBuffer()を使ってフレームバッファを変更している場合にこの関数を使うと,変更された方のフレームバッファから buffer へ画像データをコピーします.
引数
 num:論理カメラ番号(0〜9)
 buffer:画像データを格納する領域の先頭アドレス(ポインタ)
      格納されたデータの構造はフォーマットによって異なります.
      MEDIASUBTYPE_RGB32の場合,1ピクセル=int型(4バイト,0xrrggbb)です.
      MEDIASUBTYPE_RGB24の場合,1ピクセル=3バイト,[B][G][R]…です.
      OpenCVを使用する場合(ewclib.hより先にcv.hがインクルードされたとき),EWCLIBは
      MEDIASUBTYPE_RGB24に設定します.それ以外はMEDIASUBTYPE_RGB32がデフォルト値です
      他のフォーマットにおけるデータ構造はDirectX SDKヘルプを参照してください.
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない or 論理カメラ番号が範囲外
使用例
 int buffer[320*240];
 EWC_GetImage(0, buffer);
 int cnt;
 double tim;
 EWC_GetImage(0, buffer, &cnt);
 EWC_GetImage(0, buffer, &cnt, &tim);


char *EWC_GetDeviceName(int num);
説明

 カメラのデバイス名(デバイスマネージャーの“イメージングデバイス”や“カメラ”に表示される名前)を取得します.
 EWC_Open()で使用開始されているカメラに対して,この関数は使えます.
引数
 num:論理カメラ番号(0〜9)
戻り値
 デバイス名の文字列へのポインタ
 NULL:EWC_Open()で初期化されていない
使用例
 printf("%s\n", EWC_GetDeviceName(0));


char *EWC_GetDeviceSubtype(int num);
説明

 使用開始されたカメラのデバイスフォーマット名を取得します.
 例えば,MEDIASUBTYPE_YUY2であれば"YUY2"という文字列が得られます.
 EWC_Open()で使用開始されているカメラに対して,この関数は使えます.
引数
 num:論理カメラ番号(0〜9)
戻り値
 デバイスフォーマット名の文字列へのポインタ
 NULL:EWC_Open()で初期化されていない
使用例
 printf("%s\n", EWC_GetDeviceSubtype(0));


char *EWC_GetSubtype(int num);
説明

 使用開始されたカメラの画像フォーマット名を取得します.
 例えば,MEDIASUBTYPE_RGB32であれば"RGB32"という文字列が得られます.
 EWC_Open()で使用開始されているカメラに対して,この関数は使えます.
引数
 num:論理カメラ番号(0〜9)
戻り値
 デバイスフォーマット名の文字列へのポインタ
 NULL:EWC_Open()で初期化されていない
使用例
 printf("%s\n", EWC_GetSubtype(0));


int EWC_GetCamera(void);
説明

 接続されているカメラの台数を返します.
 Ver. 2.7より,カメラを開始する前でも,単独で使用できます.
引数
 なし
戻り値
 カメラ台数
使用例
 int n;
 n= EWC_GetCamera();


int EWC_GetCameraName(ewc_camera *ewcc, int *nmax);
説明

 接続されているすべてのカメラについてFriendlyName等の文字列情報を取得します.
 カメラを開始する前でも,単独で使用できます.
 構造体ewc_cameraの説明は次のとおりです.
 struct ewc_camera{
   char FriendlyName[256]; FriendlyNameに関する文字列が格納されます
   char Description[256]; Descriptionに関する文字列が格納されます
   char DevicePath[256]; DevicePathに関する文字列が格納されます
 };
引数
 ewcc:構造体(ewc_camera)配列へのポインタ
 nmax:配列の最大要素数を入れた変数へのポインタ
    実行後は,*nmaxには検出されたカメラの数(有効な配列要素数)が格納されます.
戻り値
 0:正常終了
 上記以外:エラー終了
使用例
 ewc_camera ewcc[10];
 int n= 10;
 EWC_GetCameraName(ewcc, &n);
 for(int i=0; i<n; i++) printf("%s\n", ewcc[i].FriendlyName);


int EWC_GetBufferSize(int num);
説明

 現在バッファにある画像データについて,データのバイト数を返します.
 画像のバイト数は縦横のピクセル数(解像度)やフォーマットによって変わります.
 EWC_Open()の実行後にこの関数を使ってください.そうしないと,カメラの有無に関わらず0を返します.
引数
 num:論理カメラ番号(0〜9)
戻り値
 画像データの大きさ [単位:バイト]
使用例
 int size;
 size=EWC_GetBufferSize(0);


int EWC_Stop(int num);
説明
 カメラの動作(キャプチャ)を一時的に停止させます.
 カメラに動作ランプが備わっていれば,停止中は消灯します.
 停止中に画像データの取得を行うと,停止直前の内容が読み出されます.
 再開させるにはEWC_Run()を使います.
 この関数はEWC_Close()/EWC_CloseAll()の内部でも自動で実行されるので,カメラの使用を終了するためにわざわざこの関数を呼ぶ必要はありません.また,すでに停止している場合,実行しても影響はありません.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない or 論理カメラ番号が範囲外
 上記以外:エラー終了
使用例
 EWC_Stop(0);


int EWC_Run(int num);
説明
 カメラの動作(キャプチャ)を再開させます.
 カメラに動作ランプが備わっていれば,再点灯します.
 すでに動作(再開)している場合,実行しても影響はありません.
 停止させるにはEWC_Stop()を使います.
 ポーズ(一時停止)させるにはEWC_Pause()を使います.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない or カメラ番号が範囲外
 上記以外:エラー終了
使用例
 EWC_Run(0);


int EWC_Pause(int num);
説明
 カメラの動作(キャプチャ)をポーズ(一時停止)させます.
 カメラの動作ランプは点灯のままですが,新しい画像は到着しなくなります.
 EWC_Stop()による停止と比較すると,EWC_Pause()の方が再開が早い特徴があります.
 再開させるにはEWC_Run()を使います.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない or カメラ番号が範囲外
 上記以外:エラー終了
使用例
 EWC_Pause(0);


int EWC_OneShot(int num);
説明
 カメラのキャプチャ動作を開始させ,画像を1フレーム取得した後,ポーズ状態にします.
 CPU使用率を下げることを目的とした低速度(低フレームレート)の画像入力のために使用します.
 具体的な使用例はサンプルプログラム(CPU使用率を下げた低速度な画像入力)を参照してください.
 この関数の内部では,EWC_Run(),画像2枚の入力,EWC_Pause()を順に実行しています.
 2枚取得している理由は,再開直後の1枚は画像内容が乱れているので飛ばし,2枚目を採用しているためです.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない or 論理カメラ番号が範囲外
使用例
 EWC_OneShot(0);


フレームバッファ関連

int EWC_SetBuffer(int num, void *buffer);
説明

 フレームバッファを指定のアドレスへ変更します.
 指定されたフレームバッファには,コールバック関数により一定時間毎に画像データが勝手に格納(上書き)されます.このため,EWC_BufferLock()/EWC_BufferUnlock()も併用して下さい.
 bufferには画像データが格納されるため,あらかじめユーザ側で必要なサイズのメモリ領域を確保しておいてください.
 なお,リングバッファのために複数の枚数を設定している場合は,その枚数分だけつながった長いメモリ領域の先頭アドレスを指定してください.このとき,1枚あたりのデータサイズは使用している画像フォーマットに関係なく,常にRGB32相当のサイズでメモリ領域のサイズを計算して下さい.
引数
 num:論理カメラ番号(0〜9)
 buffer:変更後のバッファのアドレス
戻り値
 0:正常終了
 1:エラー(論理カメラ番号が正しくない or カメラが接続されていない など)
使用例
 //---通常---
 int buf[640*480];
 EWC_SetBuffer(0, buf);
 //---リングバッファの枚数が複数の例---
 #define EWC_BUF_NUM 6
 #include <ewclib.h>
 int my_buf[EWC_BUF_NUM*640*480];
 EWC_SetBuffer(0, my_buf);


int EWC_BufferLock(int num);
int EWC_BufferUnlock(int num);
説明

 通常は使う必要はありませんが,EWC_SetBuffer()を使用した場合はEWCLIB内部のコールバック関数が勝手に自前のバッファへアクセス(書き換え)するので,これらの関数を用いてそのアクセスを制限できます.
 EWC_BufferLock()とEWC_BufferUnlock()は必ずセットで1回ずつ使います.
 EWC_BufferLock()が呼ばれると,その後は,EWC_BufferUnlock()が呼ばれるまで,コールバック関数によるバッファへのアクセスは制限され,データの書き換えは保留となります.このため,ユーザは安心してバッファにある画像データを読み出せます.また,EWCLIBの他のいくつかの関数も(同じカメラ番号に関して)制限され,呼び出しても制御が戻って来なくなります.
 バッファの使用が終了したら,必ずEWC_BufferUnlock()を呼び出して下さい.
 EWC_BufferLock()とEWC_BufferUnlock()の間に書くプログラムは,処理時間があまり長くならないように気をつけます.リングバッファの枚数が多ければ,コールバック関数の処理もその分,たくさん保留できますが,それでもすべてのリングバッファが一杯になるような長時間の処理をここに入れてしまうと,コマ落ちの原因となります.
 また,EWC_BufferUnlock()は画像を1枚読み出したとして,リングバッファの管理情報も更新しますので,EWC_GetImage()を使わない代わりに,この関数を使う必要があります.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:エラー(論理カメラ番号が正しくない or カメラが接続されていない など)
使用例
 if(EWC_IsCaptured(0)){
   EWC_BufferLock(0);
   //ここにバッファ内データにアクセスするプログラムを書く
   EWC_BufferUnlock(0);
 }


int EWC_GetBuffer(int num, void **buffer);
説明

 EWCLIB内部で画像格納先として登録されているフレームバッファのアドレスを取得します.
 2枚以上のリングバッファではその先頭アドレスの情報となります.
 EWC_SetBuffer()で画像の格納先を返納している場合は,その変更後のアドレスの情報となります.
引数
 num:論理カメラ番号(0〜9)
 buffer:フレームバッファのアドレスを格納するための変数へのポインタ
戻り値
 0:正常終了
 1:エラー(論理カメラ番号が正しくない or カメラが接続されていない など)
使用例
 int *p;
 EWC_GetBuffer(0, (void **)&p);


int EWC_RawMode(int num, int rawmode);
説明

 rawモード/非rawモードを切り換えます.rawmodeが1のとき,rawモードとなり,EWCLIBが内部でサンプルされたデータをフレームバッファに格納する際,上下反転の処理を行わず,サンプルデータをフレームバッファへそのまま格納します.RGB24やRGB32では上下反転が必要なので,初期設定は非rawモードです.
 画像フォーマットをMEDIASUBTYPE_RGB32やMEDIASUBTYPE_RGB24以外に指定した場合,rawモードにしておくことで,生データのまま取得できます. 画像データのサイズ(バイト数)はカメラ開始後にEWC_IsCaptured()EWC_GetBufferSize()を使うと分かります.MEDIASUBTYPE_MJPGのように毎回のデータサイズが変化する場合もこれらの関数でサイズ(バイト数)が分かります.
 EWC_Open()より前に設定しておくと,最初の画像データから適用されます.EWC_Open()の後に呼び出しても構いませんが,その場合は,次の新しい画像データ到着分から適用されることになります.
引数
 num:論理カメラ番号(0〜9)
 rawmode:0=非rawモード(標準:上下反転あり),1=rawモード(そのまま転送)
戻り値
 0:正常終了
 1:エラー(論理カメラ番号が範囲外)
使用例
 EWC_RawMode(0, 1);
 EWC_Open(0,640,480,30,0,MEDIASUBTYPE_MJPG,MEDIASUBTYPE_MJPG);


グローバル変数


double ewc_s[int num].ftime;
説明

 最新のフレーム周期が格納されています.
 この変数の値はバックグラウンドで常に更新されます.
 隣接したサンプル時刻の差から計算していますので,この値の逆数を求めればフレームレート(FPS)となります.
引数
 num:論理カメラ番号(0〜9)
戻り値
 前回のフレーム周期(単位:秒)
使用例
 printf("Frame period= %f [s]\n", ewc_s[0].ftime);
 printf("Frame rate= %f [fps]\n", 1.0/ewc_s[0].ftime);


int ewc_s[int num].w_count;
説明

 内部ですでに到着している最新の画像データのフレーム番号が格納されています.
 新たな画像が到着する毎に1ずつ増加します.
引数
 num:論理カメラ番号(0〜9)
戻り値
 フレーム番号


GUID ewc_type;
説明

 EWC_Open()で使用されるデフォルトの画像フォーマットが記憶されています.
 値を変更することもできます.
戻り値
 EWC_Open()で使用されるデフォルトの画像フォーマット


GUID ewc_device_type;
説明

 EWC_Open()で使用されるデフォルトのデバイスフォーマットが記憶されています.
 値を変更することもできます.
戻り値
 EWC_Open()で使用されるデフォルトのデバイスフォーマット


カメラ設定の取得・変更・保存・読込

double EWC_GetValue(int num, int prop [, int *mode] );
説明

 現在のドライバ設定値を読み出します.
 ウェブカメラの種類によってはサポートされていない項目もあります.
 また,各項目の設定値はもともと整数値であり,範囲や刻み幅は項目毎にまちまちですが,EWCLIBでは,全項目について0.0〜100.0の割合(%)に変換して値を返します.
引数
 num:論理カメラ番号(0〜9)
 prop:設定項目
   以下から1つを指定します
    EWC_BRIGHTNESS (明るさ)
    EWC_CONTRAST (コントラスト)
    EWC_HUE (色相)
    EWC_SATURATION (彩度)
    EWC_SHARPNESS (鮮明度)
    EWC_GAMMA (ガンマ補正)
    EWC_COLORENABLE (カラー/モノクロ)
    EWC_WHITEBALANCE (ホワイトバランス)
    EWC_BACKLIGHTCOMPENSATION (バックライト補正)
    EWC_GAIN (ゲイン)
    EWC_PAN (パン/左右の向き)
    EWC_TILT (チルト/上下の向き)
    EWC_ROLL (ロール/光軸回りの回転)
    EWC_ZOOM (ズーム/拡大)
    EWC_EXPOSURE (露出)
    EWC_IRIS (絞り)
    EWC_FOCUS (焦点)
 mode:現在のモードを取得したいときには,ここにモードを格納する変数の
    先頭アドレス(ポインタ)を渡してください.
    (この引数modeはオプションであり,省略できます.)
    modeの戻り値:0は手動モード,1は自動モードを意味します.
戻り値
 実数(double型):設定項目の値を0〜100[%]の範囲で返します.
 -1.0:サポートされていない or 引数が不正 or その他のエラー
使用例
 double d;
 d=EWC_GetValue(0, EWC_BRIGHTNESS);
 int mode;
 d=EWC_GetValue(0, EWC_EXPOSURE, &mode);


int EWC_SetValue(int num, int prop, double value);
説明

 制御を手動モードにし,設定値を変更します.
 ウェブカメラの種類によってはサポートされていない項目もあります.
 また,各項目の設定値はもともと整数値であり,範囲や刻み幅は項目毎にまちまちですが,EWCLIBでは,全項目について0.0〜100.0の割合(%)で値を指定します.
引数
 num:論理カメラ番号(0〜9)
 prop:設定項目
    (指定できる項目についてはEWC_GetValue()と同じです)
 value:設定値(0.0〜100.0の間で指定します.単位:%)
戻り値
 0:正常終了
 1:カメラ番号が範囲外またはカメラは接続されていない
 2:項目が範囲外
 3:指定された項目はこのカメラではサポートされていない
 4 or 5:その他のエラー(詳しい内容はEWC_GetLastMessage()で取得できます)
使用例
 EWC_SetValue(0, EWC_WHITEBALANCE, 50.);


int EWC_SetDefault(int num, int prop);
説明

 指定した項目を初期値に戻します.
 ウェブカメラの種類によってはサポートされていない項目もあります.
 初期値はドライバが提供する値に従います.
 項目やカメラの種類によっては初期値を適用すると(暗すぎたり明るすぎたりして)画像内容が見えなくなる場合もあります.その場合はEWC_SetValue()を使用して適切な値を手動で設定してください.
引数
 num:論理カメラ番号(0〜9)
 prop:設定項目
    (指定できる項目についてはEWC_GetValue()と同じです)
戻り値
 0:正常終了
 1:カメラ番号が範囲外またはカメラは接続されていない
 2:項目が範囲外
 3:指定された項目はこのカメラではサポートされていない
 4 or 5:その他のエラー(詳しい内容はEWC_GetLastMessage()で取得できます)
使用例
 EWC_SetDefault(0, EWC_WHITEBALANCE);


int EWC_SetAuto(int num, int prop);
説明

 制御を自動モードにします.
 ウェブカメラの種類によってはサポートされていない項目もあります.
 項目によってはモード変更できない場合もあります.
 また,指定しない他の項目も連動して自動モードに設定されることもあります.
引数
 num:論理カメラ番号(0〜9)
 prop:設定項目
    (指定できる項目についてはEWC_GetValue()と同じです)
戻り値
 0:正常終了
 1:カメラ番号が範囲外またはカメラは接続されていない
 2:項目が範囲外
 3:指定された項目はこのカメラではサポートされていない
 4 or 5:その他のエラー(詳しい内容はEWC_GetLastMessage()で取得できます)
使用例
 EWC_SetAuto(0, EWC_WHITEBALANCE);


int EWC_SetManual(int num, int prop);
説明

 制御を手動モードにします.
 ウェブカメラの種類によってはサポートされていない項目もあります.
 項目によってはモード変更できない場合もあります.
引数
 num:論理カメラ番号(0〜9)
 prop:設定項目
    (指定できる項目についてはEWC_GetValue()と同じです)
戻り値
 0:正常終了
 1:カメラ番号が範囲外またはカメラは接続されていない
 2:項目が範囲外
 3:指定された項目はこのカメラではサポートされていない
 4 or 5:その他のエラー(詳しい内容はEWC_GetLastMessage()で取得できます)
使用例
 EWC_SetManual(0, EWC_WHITEBALANCE);


int EWC_SaveProperty(int num, char *filename=NULL);
説明

 すべてのカメラ設定をテキスト形式のファイルへ保存します.
 保存形式の例を下に示します.
BRIGHTNESS            = 45.777777777777779
CONTRAST              = 40.
HUE                   = -1.
SATURATION            = 66.5
SHARPNESS             = 54.
GAMMA                 = -1.
COLORENABLE           = -1.
WHITEBALANCE          = 22.199999999999999, AUTO
BACKLIGHTCOMPENSATION = 0.
GAIN                  = -1.
PAN                   = 50.
TILT                  = 50.
ROLL                  = -1.
ZOOM                  = 0.
EXPOSURE              = 61.53846153846154, AUTO
IRIS                  = -1.
FOCUS                 = 50.
 サポートされていない項目は -1と表記されます.
 また,自動モードに設定されている項目はAUTOの表記が付加されます.
 カメラ設定をファイルから読み込むには,EWC_LoadProperty()を使います.
引数
 num:論理カメラ番号(0〜9)
 filename:作成するファイル名 (省略時は [デイバス名].txt が使われます)
戻り値
 0:正常終了
 1:カメラ番号が範囲外またはカメラは接続されていない
 2:書き込み用ファイルがオープンできなかった
使用例
 EWC_SaveProperty(0, "web_camera.txt");
 EWC_SaveProperty(1);


int EWC_LoadProperty(int num, char *filename=NULL);
説明

 カメラ設定値をテキスト形式のファイルから読み込んで設定します.
 テキストファイルの形式についてはEWC_SaveProperty()を参照してください.
 カメラ設定を保存するには,EWC_SaveProperty()を使います.
引数
 num:論理カメラ番号(0〜9)
 filename:設定を読み込むファイル名 (省略時は [デイバス名].txt が使われます)
戻り値
 0:正常終了
 1:カメラ番号が範囲外またはカメラは接続されていない
 2:読み込み用ファイルがオープンできなかった
使用例
 EWC_LoadProperty(0, "web_camera.txt");
 EWC_LoadProperty(1);


void EWC_GetLastMessage(char *s, int size);
説明

 EWCLIBの様々な関数でエラー終了となったとき,エラーの詳しい内容を文字列で得ることができます.
 ただし,EWCLIBの内部で最後に実行されたDirectShow関数に限定されるので,得られたメッセージが当たっていない場合もあります.
引数
 s:メッセージの文字列を格納する領域の先頭アドレス(ポインタ)
 buf:領域sのサイズ(単位:バイト)
使用例
 int r;
 r=EWC_SetValue(0,EWC_EXPOSURE, 30.0);
 if(r){
  char s[160];
  EWC_GetLastMessage(s,sizeof(s));
  printf("%s",s);
 }


int EWC_PropertyPage(int num);
説明

 カメラのドライバが用意する,設定のためのプロパティページを表示します.
 何らかのダイアログが開かれますので,対話形式で設定内容の確認・変更ができます.
 ダイアログを閉じるときは「OK」「閉じる」「保存」等のボタンをクリックしてください.
 Ver. 2.7より別スレッドで起動する仕様となり,プロパティページが表示されると,制御はすぐに戻ってきます.
 スレッド仕様になったことで,画像入力をさせながら,プロパティページの内容を変える使い方ができるようになりました.
 (プロパティページの元々の動作が,そのように独立して起動するものもありますが)
 同じカメラ番号による多重呼び出しはできないようにEWCLIB側でチェックしています.
 なお,メーカーが同じカメラを複数使用する場合,カメラ番号が異なっていても,ドライバの方で複数のプロパティページが表示されるのを制限していることもあるようです.
 ちなみに,非スレッド仕様の従来版はEWC_PropertyPage1()として残されています.
引数
 num:論理カメラ番号(0〜9)
戻り値
 0:正常終了
 1:EWC_Open()で初期化されていない or カメラ番号が範囲外
 2:同じ論理カメラ番号のプロパティページがすでに表示されている
使用例
 EWC_PropertyPage(0);


画像変換

void EWC_Cnv32to24(unsigned char *dst, unsigned int *src, int pxl);
説明

 32ビット画像を24ビット画像へ変換します.
 ESPLIB,OpenCVと組み合わせて使うときに,あれば便利かもしれない関数です.
 他の関数とは独立しており,単独で使えます
 ESPLIBのカラー画像は32ビット形式[B][G][R][0]…です.
 OpenCVのカラー画像は24ビット形式[B][G][R]…です.
 <注意>画像の横ピクセル数が4の倍数ではない場合,この関数は使えません.
引数
 dst:24ビット画像を格納するメモリ領域の先頭アドレス(ポインタ)
 src:32ビット画像の先頭アドレス(ポインタ)
 pxl:画像のピクセル数(横幅×高さ)
使用例
 unsigned int img32[320*240];
 unsigned char img24[320*240*3];
 EWC_Cnv32to24(img24,img32,320*240);


void EWC_Cnv24to32(unsigned int *dst, unsigned char *src, int pxl);
説明

 24ビット画像(RGB24)を32ビット画像(RGB32)へ変換します.
 ESPLIB,OpenCVと組み合わせて使うときに,あれば便利かもしれない関数です.
 他の関数とは独立しており,単独で使えます
 ESPLIBのカラー画像は32ビット形式[B][G][R][0]…です.
 OpenCVのカラー画像は24ビット形式[B][G][R]…です.
 <注意>画像の横ピクセル数が4の倍数ではない場合,この関数は使えません.
引数
 dst:32ビット画像を格納するメモリ領域の先頭アドレス(ポインタ)
 src:24ビット画像の先頭アドレス(ポインタ)
 pxl:画像のピクセル数(横幅×高さ)
使用例
 unsigned int img32[320*240];
 unsigned char img24[320*240*3];
 EWC_Cnv24to32(img32,img24,320*240);


void EWC_CnvNV12toRGB32(void* rgb, void* yuv, int wx, int wy);
説明

 NV12画像をRGB32画像へ変換します.
 他の関数とは独立しており,単独で使えます
引数
 rgb:RGB32画像を格納するメモリ領域の先頭アドレス(ポインタ)
 yuv:NV12画像の先頭アドレス(ポインタ)
 wx:画像の横幅(単位:ピクセル)
 wy:画像の高さ(単位:ピクセル)


void EWC_CnvY16toRGB32(void* rgb, void* y16, int wx, int wy);
説明

 Y16画像をRGB32画像へ変換します.16ビットの輝度のうち上位8ビットのみが残ります(下位8ビット分の情報は失われます).
 他の関数とは独立しており,単独で実行できます.
引数
 rgb:RGB32画像を格納するメモリ領域の先頭アドレス(ポインタ)
 y16:Y16画像の先頭アドレス(ポインタ)
 wx:画像の横幅(単位:ピクセル)
 wy:画像の高さ(単位:ピクセル)


void EWC_CnvY800toRGB32(void* rgb, void* y800, int wx, int wy);
説明

 Y800画像をRGB32画像へ変換します.
 他の関数とは独立しており,単独で使えます
引数
 rgb:RGB32画像を格納するメモリ領域の先頭アドレス(ポインタ)
 y800:Y800画像の先頭アドレス(ポインタ)
 wx:画像の横幅(単位:ピクセル)
 wy:画像の高さ(単位:ピクセル)


対応フォーマットの取得

int EWC_GetFormat(int devn, ewc_format *fmt, int *nmax);
int EWC_GetFormat(char *devicename, ewc_format *fmt, int *nmax);
説明

 カメラがサポートする解像度等の情報を取得します.
 EWC_Open(),EWC_GetDeviceName()等の他の関数とは独立しており,単独で使用できます.
 カメラの指定は,物理デバイス番号またはデイバス名で行います.
 得られた情報は構造体fmtに格納されますので,fmtの配列を事前に用意しておきます.
 また,その配列の要素数も必要です.nmaxには事前に値を入れておきます.
 構造体ewc_formatの説明は次のとおりです.
 struct ewc_format{
  int width; 画像の横幅
  int height; 画像の高さ
  int bit; 画像のビット数
  REFERENCE_TIME AvgTimePerFrame; フレーム周期(単位:100ns)
  double fps; フレームレート(frame/s) ※単に10000000を上のAvgTimePerFrameで割った値
  GUID subtype; メディアサブタイプ
  char subtype_t[80]; subtypeに対応する文字列(例えば,MEDIASUBTYPE_RGB32なら"RGB32")
 };
 メディアサブタイプ情報は,カメラがネイティブでサポートする形式を示したものです.ewc_device_type等の使用によりここで得られたメディアサブタイプの中から指定されたデバイスフォーマットを選択して画像入力を行うこともできます.デバイスフォーマットや画像フォーマットについては「メディアサブタイプについて」を参照してください.
引数
 devn:物理デバイス番号(0〜9)
  カメラを番号で指定します.他の関数で出てくる論理カメラ番号とは異なりますのでご注意ください.
  物理デイバス番号は見つかった順(デバイスマネージャー - イメージングデバイスに現れる順)に0,1,2…と割り当てられています.
 devicename:デバイス名
  物理デイバス番号ではなく,デイバス名でカメラを探索して指定するときは,この引数を使います.
  デバイスマネージャ - イメージングデバイスに表示される名前です.
  ここに指定された文字列を含むものがあれば対象とします.
 fmt:構造体配列へのポインタ
  構造体ewc_formatを配列にしたものの先頭アドレス(ポインタ)を渡してください.
 nmax:フォーマット取得数の上限(用意された構造体配列fmtの要素数)
  上記配列の要素数を事前にこの変数に入れておき,そのポインタを渡してください.
  得られるフォーマット数が多い場合,このnmaxにより最大取得数が制限されます.
  関数実行後,nmaxには実際に格納されたフォーマット数が格納されています.
戻り値
 0:正常終了
 1:番号devnが範囲外
 上記以外:その他のエラー
使用例
 ewc_format fmt[10];
 int n=10;
 EWC_GetFormat(0, fmt, &n);
 for(int i=0; i<n; i++)
  printf("%d x %d\n", fmt[i].width, fmt[i].height);


int EWC_GUIDtoTEXT(GUID guid, char *s, int size);
説明

 メディアサブタイプで使われるGUID値に対応する文字列を取得します.
 例えば,MEDIASUBTYPE_RGB32であれば"RGB32"という文字列が得られます.
 他の関数とは独立しており,単独でいつでも実行できます.
引数
 guid:メディアサブタイプのGUID値が入った変数
 s:文字列の格納先
 size:メモリ領域sのバイトサイズ
戻り値
 0:正常終了
 1:EWCLIBで未実装のguid値だった.このときsには16進数表記した文字列が格納されます.
使用例
 char s[30];
 EWC_GUIDtoTEXT(MEDIASUBTYPE_RGB32, s, sizeof(s));




著作権・使用許諾

EWCLIB のすべての著作権はI.N.にあります.
EWCLIB はフリーソフトウェアであり配布・転載は自由です.
EWCLIB の改造・変更は自由に行っても構いません.
EWCLIB を使用した際の著作権表示は特に必要ありません.
EWCLIB の使用目的・用途は限定しません.
EWCLIB を使用したことによって生じたいかなる損害等も,作者は一切その責任を負わないこととします.


バージョンアップ履歴

ver.1.0 2005/3/29
 "ewclib.h"の誕生.
 Qcam Pro 4000で動作確認した.

ver.1.1 2005/4/4
 Creative WebCam Pro eXのためにdisplaynameのチェックを追加した.
 最大認識数を5から8へ変更

ver.1.2 2005/4/5
 WideCharToMultiByte()の利用.
 細かな点の見直し等.

ver.1.4 2006/12/26
 Visual C++ 2005対応になった.

ver.1.5 2007/1/12
 EWC_GetValue(), EWC_SetValue(), EWC_SetDefault(), EWC_SetAuto()を追加.
 EWC_GetLastMessage(), EWC_PropertyPage()を追加.
 EWC_IsCaptured(), EWC_GetBuffer(), EWC_SetBuffer()の追加.
 ewc_time[]の追加
 EWC_Open()の仕様変更.
 サンプルプログラムを追加.

ver.1.6 2008/1/29
 IAMVideoProcAmpやIAMCameraControlが未サポートであるUSBカメラへの対応.

ver.1.7 2009/4/30
 #pragma warning(disable:4819)を外す
 #pragma warning(disable:4996)を外す
 Visual C++ 2008対応版.
 OpenCV対応.
 EWC_Cnv32to24()/EWC_Cnv24to32()追加.
 サンプル追加.

ver.1.8 2009/5/13
 COM初期化,終了方法の改良(OpenCV対策).
 OpenCV&ESPLIBと組み合わせるサンプル追加.

ver.1.9 2010/4/15
  dxtrans.hと__IDxtCompositor等へ対処を変更し,qedit.hの修正を不要にした.
  EWC_Close():メモリ解放の不徹底を修正(ewc_pSampleGrabberCB[]関係).
  EWC_GetLastMessage():Unicode設定とマルチバイト設定の両対応化.

ver.2.0 2010/5/13
  EWC_Open()/EWC_Close()仕様変更.カメラ毎に解像度等の設定が可能となった.
  EWC_Run()/EWC_Stop()/EWC_CloseAll()追加.
  ewc_time[]の廃止とewc_s[].stime/ewc_s[].ftimeの追加.

ver.2.1 2012/2/28
  EWC_Close()でメモリ解放する際,メモリリークが生じていたのを修正.

ver.2.2 2014/1/20
  EWC_Open()を一部仕様変更(デフォルト値追加,デバイス名指定,等)
  @device:pnpだけでなく@device:swも認識対象とした
  最大カメラ認識数を8台から10台へ変更
  EWC_GetDeviceName(),EWC_GetFormat()の追加

ver.2.3 2014/1/27
  デバイス出力ピンのフォーマット指定の機能を追加
  フォーマット一覧を取得するサンプルの変更
  EWC_Open()引数追加
  ewc_type,ewc_device_type(EWC_DEVICE_TYPE)追加
  EWC_GetDeviceSubtype(),EWC_GetSubtype(),EWC_GUIDtoTEXT()追加
  struct ewc_formatへsubtype_tを追加

ver.2.4 2014/4/22
  ewc_s[].count, EWC_Pause(), EWC_OneShot()の追加
  EWC_SaveProperty(), EWC_LoadProperty(), EWC_SetManual()の追加
  サンプルプログラム「各種設定の変更を行う例」の内容改訂
  サンプルプログラム「CPU使用率を下げた低速度な画像入力」の追加

ver.2.5 2018/5/29
  Visual C++ 2017対応

ver.2.6 2020/6/26
  リングバッファ機能の追加
  EWC_IsCaptured(), EWC_GetImage()の仕様変更
  ewc_s[].stimeの廃止,サンプルプログラムの修正

ver.2.7 2021/4/21
  EWC_PropertyPage()を別スレッドから起動するよう変更.
  サンプルされたデータをそのまま格納するオプションのためにewc_rawの追加.
  EWC_GetCamera()を単独で使用できるように変更.
  EWC_GetCameraName()および構造体ewc_cameraの追加.
  EWC_GUIDtoTEXT()に対応フォーマットを追加.
  EWC_CnvNV12toRGB32()EWC_CnvY16toRGB32(), EWC_CnvY800toRGB32()の各変換関数の追加.
  サンプルプログラム「対応フォーマットの一覧を表示する例」,「NV12出力のカメラを使う例」を追加.

ver.2.8 2021/5/21
  EWC_IsCaptured()およびEWC_GetImage()の引数仕様を変更し,
  取得画像に関する情報はすべてEWC_IsCaptured()で把握するように変更.
  MJPGをrawモードで取り込む目的のため,EWC_IsCaptured()で毎回のデータサイズを把握できるようにした.
  また,カメラごとにrawモードを設定できるようにするため,ewc_rawを廃止し,EWC_RawMode()を追加.
  EWC_SetBuffer()により格納先が変更されていてEWC_GetImage()を使わないプログラムの場合,EWC_IsCaptured()の戻り値が正しくない問題を
  解決するため,EWC_BufferLock(),EWC_BufferUnlock()を追加.
  リングバッファの枚数が2以上のとき1枚あたりのサイズはRGB32相当(固定)とした.
  MJPGデータをそのまま取得するサンプルプログラムを2つを追加.
  1番目のサンプルプログラムを一部修正.
  カメラが0台(未接続)の場合,EWC_GetCameraName()の戻り値が非0(エラー)となっていた問題を修正.


作者のウェブサイト
 EWCLIBの最新情報や作者の他のソフト,ライブラリがあります.
 http://insubaru.g1.xrea.com/


作者への連絡先
 EWCLIBに関する質問やバグ情報などは下記URL(ブログ)にて対応いたします.
 https://insubaru.hatenablog.com/


開発環境

OS:Windows 10 Pro version 20H2
言語:Visual Studio 2019 Professional Edition


謝辞

・このEWCLIB(初期バージョン)の作成にはMicrosoft DirectXの資料以外に,下記ページの情報が大いに役立ちました.ありがとうございました.
1.http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/directshow.html
 (京都大学 川嶋先生のHiroaki's Private Pageより)
2.http://www.katolab.ee.kagu.sut.ac.jp/programing/capture.htm
 (東京理科大学 加藤先生の研究室ホームページより)

End of help.