アプリ版:「スタンプのみでお礼する」機能のリリースについて

OpenCvを使ったプログラムでエラーが出ます。
ダイアログで画像ファイルを選択して表示するプログラムを作ったのですが、WindowsXPでは問題なく実行できるのにWindows7の32ビット版で実行するとダイアログでファイルを選択すると以下のエラーが出ます。
(VisualC++2008の設定はどちらも同じです。OpenCvのバージョンは1.1preです。7、XP共に同じように導入しました)

↓エラーメッセージ
Null pointer (null filename)
in function cvLoadImage,.\loadsave.cpp(404)

Press"Abort"to terminate application.
Press"Retry"to debug(if the app is running under debugger).
Press"Ignore"to continue(this is not safe).

↓問題のあるコード
#include <stdio.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

int main( int argc, char **argv ) {
int key;
OPENFILENAME ofn; // ファイル名情報
WCHAR fileName_w[200]; // ファイル名格納用バッファ
IplImage *image; // 画像の格納先
char windowName[] = "Result";//読み込んだ画像をを表示するウィンドウの名前

// ウィンドウを用意します。後で用意するときは、※1のようにhwndOwnerにNULLを指定します。
cvNamedWindow(windowName);

// OPENFILENAME構造体を設定します。
ZeroMemory(&ofn, sizeof(ofn)); // 初期化
ofn.lStructSize = sizeof(ofn); // 構造体のサイズ
ofn.hwndOwner = (HWND)cvGetWindowHandle(windowName); // 親ウィンドウ
// = (HWND)NULL; // 親ウィンドウがないときはNULLを指定します。※1
ofn.lpstrFile = fileName_w; // ファイル名格納先
ofn.lpstrFile[0] = '\0'; // ファイル名の初期値はなし
ofn.nMaxFile = sizeof(fileName_w); // ファイル名の格納サイズ
ofn.lpstrFilter = L"すべて\0*.*\0Bitmap\0*.bmp\0Jpeg\0*.jpg\0"; // フィルタの設定
ofn.nFilterIndex = 1; // フィルタの初期値
ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST; // フラグの設定

// 「ファイルを開く」ダイアログを呼び出します。
if(GetOpenFileName(&ofn) == TRUE){
char fileName[200];
size_t n;

// ファイル名をWCHAR文字列からchar文字列へ変換します。
wcstombs_s(&n, fileName, sizeof(fileName), ofn.lpstrFile, _TRUNCATE);

// 画像ファイルを読み込みます。
image = cvLoadImage(fileName);

// ウィンドウに貼り付けます。
cvShowImage(windowName, image);
}

key = cvWaitKey( 0 );

cvReleaseImage( &image );
cvDestroyWindow( windowName );

return 0;
}

このプログラムはhttp://cvwww.ee.ous.ac.jp/opencv.htmlにあるサンプルを参考にしました。
どうすればエラーをなくすことができるのでしょうか?
よろしくお願いします。

A 回答 (2件)

>error_tでなくerrno_tですよね?何かエラーが出たので・・・



すみません、書き間違いでした。

>とりあえず↑を加えてnとfileNameの内容を表示させたところ、
>nは0が表示され、fileNameは何も表示されませんでした。
>これは変換された文字数が0で、変換結果のマルチバイト文字列用のバッファのアドレスに何も入っていない?つまり正しく変換されていないということでしょうか?

マニュアルに従えば、その通りということになります。
正しくファイル名が入ってないか、WCHARで入っていないか、ちょっとわかりません。

こうなってくると、OpenCVというよりは、WinAPIとWindows7かVS2008の問題かと思います。
タイトル変えてGetOpenFileNameとwcstombs_sにしぼって再質問したほうが答えがくるかもしれません。

あとは、
Win7でつかえる別のダイアログを使うとか
http://msdn.microsoft.com/ja-jp/magazine/dd86134 …
Unicode版のGetOpenFIleNameWで強制的にWCHARになるようにするとか
    • good
    • 0
この回答へのお礼

提示していただいた方法を試しつつタイトルを変えて質問しなおしてみます。
これを機にAPIも少しずつ勉強してみようと思います。
回答ありがとうございました!

お礼日時:2010/07/07 22:27

エラーメッセージからすると


> image = cvLoadImage(fileName);
のfileNameが空文字列になっているような感じです。

一つあやしいのは
> wcstombs_s(&n, fileName, sizeof(fileName), ofn.lpstrFile, _TRUNCATE);
での変換で、
http://msdn.microsoft.com/ja-jp/library/s7wzt4be …
> wcstombs_s は、マルチバイト文字に変換できないワイド文字を検出すると、0 を *pReturnValue に設定し、変換先バッファに空の文字列を設定します。さらに、errno を EILSEQ に設定し、EILSEQ を返します。

ということなので、まずは

error_t eno = wcstombs_s(&n, fileName, sizeof(fileName), ofn.lpstrFile, _TRUNCATE);
if ( ( n == 0 ) || ( eno != 0 ) ) {
エラー処理: printfやMessageBox等を使って fileName等の内容を表示
} ;

とでもして、正しく変換できているか確認してはどうでしょうか。
あとは、ロケール指定版の wcstombs_s_l でロケールを指定するのはどうでしょうか

この回答への補足

error_tでなくerrno_tですよね?何かエラーが出たので・・・

errno_t eno = wcstombs_s(&n, fileName, sizeof(fileName), ofn.lpstrFile, _TRUNCATE);
if ( ( n == 0 ) || ( eno != 0 ) ) {
printf("n:%d\n",n);
printf("fileName:%s\n",fileName);
} ;

とりあえず↑を加えてnとfileNameの内容を表示させたところ、
nは0が表示され、fileNameは何も表示されませんでした。
これは変換された文字数が0で、変換結果のマルチバイト文字列用のバッファのアドレスに何も入っていない?つまり正しく変換されていないということでしょうか?
ロケールという言葉は初めて聞いたので現在調べ中です^^;

補足日時:2010/07/06 21:45
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!