C++のダイアログで画像処理をするには?

解決


さすらいの戦士  2003-06-17 02:02:26  No: 3779

capSetCallbackOnFrame( hWndCap, FrameCallback );というコマンド使い時
、FrameCallbackという関数はダイアログのどこへ作ればいいですか?
例ですけど、関数の中身としては、
 LRESULT PASCAL FrameCallback( HWND hWnd, LPVIDEOHDR lpVHdr )
  {
    //  ボードからメモリにデータをコピーする
    int i, j;
    BYTE *pBuff;
    memcpy( m_lpData, lpVHdr->lpData, lpVHdr->dwBufferLength );
    pBuff = m_lpData;
    for( j=0; j<HEIGHT; j++ ){
      for( i=0; i<WIDTH; i++ ){
        image_b[ i ][ j ] = *  pBuff;  pBuff++;
        image_g[ i ][ j ] = *( pBuff+1 );  pBuff++;
        image_r[ i ][ j ] = *( pBuff+2 );  pBuff++;
      }
    }
    return TRUE;
  }
であります。誰か教えてください。お願いしますm(_ _)m


にしの  2003-06-17 07:29:56  No: 3780

ダイアログとはTDialogでしょうか。
TDialogのメンバ関数とすると、
LRESULT PASCAL FrameCallback( HWND hWnd, LPVIDEOHDR lpVHdr );
ではなくなります。

単純に、C言語のようにクラス外で定義してやればよいと思います。

capSetCallbackOnFrameを呼ぶ箇所より後ろに関数を定義する場合は、ヘッダファイルに関数定義を書くなど、呼ぶ前に関数定義をしておく必要があります。
# もちろん、呼ぶ前に関数を定義した場合も、読みやすさなどを考えてヘッダに書くべきです


さすらいの戦士  2003-06-17 09:02:31  No: 3781

返事ありがとうございます。にしのさん。
すみません、TDialogです。
capSetCallbackOnFrame(親のハンドル名,宛て先関数のアドレス)の関数を使う時、宣言の前の親のハンドル名は知ってますけど、そのあと宛て先関数の
アドレスは自分で作った関数名を入れればいいですが、その関数をヘッダファイルで作るでしょうか?
もし、ヘッダファイルで関数で定義とすると、どのヘッダファイルに定義すればいいですか?
また、ヘッダファイルの中のpublicで定義するでしょうか?

すみません、まだ理解が浅くて、、、よろしくお願いします。
出来れば例を持って教えていただければ幸いです^^;


にしの  2003-06-17 17:30:16  No: 3782

関数の定義にpublic宣言はありません。
C言語はどの程度理解されていますか?

今回の問題とは少し違いますが、一般的には、次のようになります。

//test.h
#ifndef TEST_H
#define TEST_H

int hextoint(char*); // 関数宣言

#endif
---- ここまでがtest.h

//test.c
#include<stdio.h>
#include<stdlib.h>
#include "test.h"

int main(int argc, char**argv)
{
  int n;

  n = hextoint("20");
  printf("%d", n);
}

int hextoint(char *hex)
{
  int ret = 0; // 戻り値
  // hexに入っている文字列を16進数と見なして、intに変換する処理
  //(省略)
  return ret;
}
---- test.cここまで

これを、test.hヘッダ無しにすると、warningが発生します。
# 暗黙の関数宣言

C/C++では、関数を使用する前に関数の宣言をしていないと、ワーニングになり、暗黙の関数宣言として、intを返す関数になります。

とりあえず、わからないのであれば、おそらくコールバック関数は使用するAPIに対して1つでしょうから、APIを使用する関数の前に、コールバック関数を置き、それを呼べばよろしいかと思います。

例えば次の通り。

****.cpp // APIを使用する箇所を含むファイル

・・・(省略)・・・
//コールバック関数を定義
LRESULT PASCAL MyFrameCallback( HWND hWnd, LPVIDEOHDR lpVHdr )
{
  //省略
}
void TMyDialog::Hogehoge(...)
{
  // APIを使用する関数
・・・
  // 省略
・・・
  //関数を使用する
  capSetCallbackOnFrame( hWndCap, MyFrameCallback );

}

たいして難しくないです。
クラスのメンバ関数にしないだけです。
クラスのメンバ関数は、クラスのインスタンスがなければ呼べません(staticな関数は呼べますが)。


さすらいの戦士  2003-06-17 23:42:20  No: 3783

にしのさん、親切に教えてもらえてありがとうございます。
C++についてはある程度わかるですが、クラス関係には少々まだ理解してない部分がありまして、
apiをクラスとの関連付けは最初あまりわかりませんでしたが、
にしのさんのおかげでようやくその構造をわかってきました。
あと、たびたびですみませんですけど、
今は自分でC++のDialogを使って簡単な自作キャプチャソフトを作ってるですけど、
BOOL CCapturewinDlg::OnInitDialog()

    最初から付いてたコード
    CWnd* pWnd = GetDlgItem ( IDC_CAPWIN );
  hWndCap = capCreateCaptureWindow(
            "Captrue Window",  
            WS_CHILD | WS_VISIBLE,
            0, 0,                 
            320, 240,             
            pWnd->m_hWnd,         
            NULL);               
  capDriverConnect( hWndCap, 0 ); 

  capPreviewRate( hWndCap, 1 );   
  capPreview( hWndCap, TRUE );    

という内容追加しまして、USBによりカメラの表示までできましたけれど、
実際にcapSetCallbackOnFrame( , );とその宛先の関数の処理内容はどこで
宣言すればよろしいですか??
実際にいろんなHPを参考しましたけど、どうやらcapSetCallbackOnFrame( , );は上のソースコードの
capDriverConnect( hWndCap, 0 ); 
のあとに追加するみたいです。
そして、そのあとに
LRESULT PASCAL MyFrameCallback( HWND hWnd,LPVIDEOHDR lpVHdr )
{
  //画像処理の内容
}
を追加する。

またお手数ですが、よろしくお願いします。


にしの  2003-06-18 00:08:04  No: 3784

次のような感じになります。

//先に関数を宣言。他で使わないのであれば、ヘッダに追加する必要はありません
LRESULT PASCAL MyFrameCallback( HWND hWnd,LPVIDEOHDR lpVHdr )
{
  //画像処理の内容
}
//APIを使用する箇所
BOOL CCapturewinDlg::OnInitDialog()
{
  //最初から付いてたコード
  CWnd* pWnd = GetDlgItem ( IDC_CAPWIN );
  hWndCap = capCreateCaptureWindow(
    "Captrue Window",  
    WS_CHILD | WS_VISIBLE,
    0, 0,                 
    320, 240,             
    pWnd->m_hWnd,         
    NULL);               
  capDriverConnect( hWndCap, 0 ); 

  //ここに追加
capSetCallbackOnFrame(hWndCap, MyFrameCallback);
//もしかしたら capSetCallbackOnFrame(hWndCap, &MyFrameCallback); かもしれません
//ちょっとCから離れているので構文忘れました

  capPreviewRate( hWndCap, 1 );   
  capPreview( hWndCap, TRUE );    
}


さすらいの戦士  2003-06-18 01:28:31  No: 3785

にしのさん、ありがとうございます。何とかコンパイルが通りまして、できました。
しかし、実行しましたらmemcpy.asmというファイルがなくてコンパイルが通って、実行エラーが起こりました。
その後そのファイルをDLしてきて実行してみたら、同じくエラーが出てきました。
その原因はなぜでしょうか??
もしかしてmemcpyというライブラリが必要ということでしょうか??
以下がその処理内容ですけど、、、よろしくお願いします。
LRESULT PASCAL FrameCallback( HWND hWnd, LPVIDEOHDR lpVHdr )
  {
    // ボードからメモリにデータをコピーする
    int i, j;
    BYTE *pBuff;
    memcpy( m_lpData, lpVHdr->lpData, lpVHdr->dwBufferLength );
    pBuff = m_lpData;
    for( j=0; j<HEIGHT; j++ ){
      for( i=0; i<WIDTH; i++ ){
        image_b[ i ][ j ] = *  pBuff; pBuff++;
        image_g[ i ][ j ] = *( pBuff+1 ); pBuff++;
        image_r[ i ][ j ] = *( pBuff+2 ); pBuff++;
      }
    }
    return TRUE;
  }

あ、一つのUSBカメラで取り込んだ動画を同時に同じ複数の画面で表示させることはできますか?
capDriverConnect( hWndCap, 0 ); で一度一つのドライバしか取り込めないと思うので、もしするとしたらどういう風作ればいいですか?


にしの  2003-06-18 01:48:10  No: 3786

memcpyは、標準Cの関数です。
#include <string.h>
をつけましたか?

最後の質問は、専門分野ではないのでちょっとわかりません。
# 今環境がない、というのもありますが

capCreateCaptureWindowで複数ウィンドウを作って、capDriverConnectで接続させればよいのでは?
capDriverConnectの仕様を知らないので、もしかしたら1つのドライバに1つのウィンドウしか接続できないのかもしれません。


さすらいの戦士  2003-06-19 00:36:19  No: 3787

ありがとうどざいます。
include<string.h>、もしくinclude<memory.h>を加えても同じくエラーが出ます、、、
実行だけでしたら強制終了で終わってしまうです。
デバックでしましたら、
「ハンドルされていない例外がcapture win.exe(MSVCRTD.dll)にあります,0xC0000005:Access Violation
として表示され、そのあとにmemcpy.asmのパスを入れてくださいで聞かれます。
なぜかそうなるでしょうか???


にしの  2003-06-19 00:47:25  No: 3788

どうしてもエラーになるのでしたら、CopyMemoryを使用されてはどうでしょう。
APIですので、存在するはずです。
定義は、
procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
なので、そのまま置き換えられると思います。


さすらいの戦士  2003-06-20 03:10:39  No: 3789

にしのさん、ありがとうございます。
原因はわからなかったですけど、何とかできるようになりました。
いろいろアドバイスしてくれてありがとうございました。


さすらいの戦士  2003-06-20 03:11:05  No: 3790

解決ですーーー^0^


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加