• ベストアンサー

SDKにて。

現在「猫でもわかる」を参考にSDKを学んでいるものです。 ここで[ 画像の表示 ]などをプログラムしていると疑問が出てきます。 今大学で画像処理専門の研究室に所属しているので、そこで培った技術を是非SDKで組めればと思います。 C言語のコンソールではraw画像を読み込み、処理し、出力するといったプログラムは組めるのですが、SDKにて同様な処理を実現しようと考えるとちょっとなやみます。 「猫でもわかる」では画像の表示をビットマップ画像を例にとってプログラムをしているのですが、raw画像の場合ばどのようになるのでしょう? 具体的に行いたいことは、自作したraw画像の読み込み関数を利用してraw画像をグローバルな配列へ読み込み、その配列を使用し内部で画像処理をした後、新しいウィンドウにその処理後の画像を表示するようにしたいと考えています。 「猫でもわかる」ではOPENFILENAME構造体を利用してビットマップを読み込んでいるのですが、自分もOPENFILENAME構造体を使用して既存のファイルオープン用のダイアログボックスから読み込ませたいと考えています。 すこし荒い要求ですが、こたえられる方はよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#30727
noname#30727
回答No.7

>BITMAPINFO pbi = (BITMAPINFO *)new char[size]; *pbiの間違いでした。 C++ではなくCを使っている場合、new は malloc と同じようなものと思って下さい。 >for (int i = 0; i < 256; i++) これもエラーになりそうです。

noconan
質問者

お礼

返答が遅れ申し訳ありませんでした。 やっと今日作成することができました。 色々とてこずりましたが、輝度情報を格納した配列を意図するように表示することができてほっとしております。 時間がかかりすぎましたねw また何かあったらよろしくお願いします。

その他の回答 (6)

noname#30727
noname#30727
回答No.6

BMPファイルは表示できるのですよね? BMPファイルにはBITMAPINFOのようなデータが含まれていますが、独自形式の場合にはそれが無いので、プログラム上で作ってやる必要があります。 8bitグレースケールが0(黒)~255(白)だとします。 int size = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256; BITMAPINFO pbi = (BITMAPINFO *)new char[size]; pbi->bmiHeader.メンバ = 適切に初期化; for (int i = 0; i < 256; i++) { pbi->bmiColors[i].rgbBlue = i; pbi->bmiColors[i].rgbGreen = i; pbi->bmiColors[i].rgbRed = i; pbi->bmiColors[i].rgbReserved = 0; } こういったものを用意してからCreateDIBitmapやCreateDIBSectionなどでビットマップを作成する事を考えて下さい。 それから、WM_PAINTでビットマップを作成するのは良くないです。 ファイルを読み込んだ直後に作成して、WM_PAINTでは描画だけにするべきです。 アニメーションさせるのが目的なら、DIBを作成して直接書き換えるようにした方が無駄が無いです。

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.5

まずCreateBitmapは成功していますか? 恐らくhBitmapにNULLが入っていると思われます。 (まず4番目の引数が256ビットというのがおかしいです。) また、CreateBitmapで作ったものをSelectObjectしても必ず表示できるとは限りません。 その形式(色数等)とデバイスコンテキストが一致していなければSelectObjectが失敗します。 (戻り値がGDI_ERRORになります。) その為、MSDNにはCreateCompatibleBitmapを使う事を推奨しており、パフォーマンスがあがると書いております。 あと、RAWフォーマットがどういう形式かはしりませんが その情報をそのままぶちこんでもデバイスコンテキストと形式が一致していなければ表示できません。 CreateCompatibleBitmapを使いSelectObjectしたmhdcを GetDIBitsで取得し、それに含まれるBITMAPINFOをみれば、デバイスコンテキストの現在の形式が分かります。 つまり、その形式に一旦変換する必要があると思います。 Windowsのデバイスコンテキストの扱う上でBitmap/DIBのフォーマットは基本なので、もしご存知なければ それを先に調べてください。(Bitmap フォーマットで検索できます。) あとアドバイスとして、WindowsAPIは失敗した場合、 GetLastErrorでその失敗理由を知る事が可能なものが多いです。 MSDNを参考にして調べてください。

noconan
質問者

お礼

返答が遅れ申し訳ありませんでした。 やっと今日作成することができました。 色々とてこずりましたが、輝度情報を格納した配列を意図するように表示することができてほっとしております。 時間がかかりすぎましたねw また何かあったらよろしくお願いします。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★多分、原因は『GetDC』、『ReleaseDC』を使っているからだと思います。 ・WM_PAINT メッセージ内では、なぜか特別に『BeginPaint』、『EndPaint』関数を  使用する決め事になっています。ですから『BeginPaint』関数で書き直せば良い。 case WM_PAINT: {  PAINTSTRUCT ps;    hBitmap = CreateBitmap( (int)XSIZE, (int)YSIZE, 8, 256, Image[ImageFileNumber].src );  hdc = BeginPaint( hwnd , &ps );  hmdc = CreateCompatibleDC( hdc );  SelectObject( hmdc, hBitmap );  BitBlt( hdc, 0, 0, XSIZE, YSIZE, hmdc, 0, 0, SRCCOPY );  DeleteDC( hmdc );  DeleteObject( hBitmap );  EndPaint( hwnd , &ps );  break; } その他: ・WM_PAINT メッセージ内では、『BeginPaint』、『EndPaint』関数をペアで使う。 ・WM_PAINT メッセージ以外は、『GetDC』、『ReleaseDC』関数をペアで使う。  または、『CreateDC』、『DeleteDC』関数をペアで使います。 ・Windows プログラミングは間際らしいです。気をつけましょう。 ・以上。参考に!

noconan
質問者

お礼

返答が遅れ申し訳ありませんでした。 やっと今日作成することができました。 色々とてこずりましたが、輝度情報を格納した配列を意図するように表示することができてほっとしております。 時間がかかりすぎましたねw また何かあったらよろしくお願いします。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.3

★CUI の main() 関数内で WinMain() のメッセージループを記述します。 ・これで単純にウインドウが表示されます。  その後、WM_CREATE メッセージ内でグローバルな配列で読み込んだ raw 画像を描画します。  つまり、WM_CREATE メッセージ内で GetDC()、ReleaseDC() で HDC を操作すれば良い。 その他: ・main()、WinMain() 関数も両方とも API 関数が呼び出せます。  そこでコマンドラインの文字列を解釈してから GetOpenFileName() 関数でファイル名を取得します。  そして、fopen()、fclose() でグローバルな配列に読み込ませます。その後にメッセージループを  構成すればウインドウが表示されます。 ・あとは WM_CREATE メッセージ内で GetDC()、ReleaseDC() で HDC を操作します。 ・メッセージループを抜けたらば、グローバルな配列の後始末などを行いプログラム終了すれば良い。 ・以上。おわり。

noconan
質問者

補足

返信ありがとうございました。 実験した結果をしたの回答者さんの補足に書いておきました。 解決の仕方をお願いしたいです。 よろしくお願いします。

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.2

>そのファイルポインタを使用してどのように表示するか・・・・ >BitBlt関数を使用するならデバイスコンテキストハンドルが必要なわけだし・・・・・ デバイスコンテキストハンドルが必要ならCreateCompatibleDCを使ってください。 CreateBitmapで作ったオブジェクトをSelectObjecでそのDCと関連させます。 後はそのDCをSetDIBitsToDevice/StretchDIBits/SetDIBits等で操作します。 まずそれらのAPIを調べてください。 あとは、そのDCをWM_PAINT(BeginPaint)で受け取るHDCに BitBltなりStretchBltなりで貼り付ければ表示できます。 (SetPixelを使って1ドットずつ塗りつぶすなんて力技もありますが かなり遅いので現実的ではないです。) 必ずしもメモリ内で処理しなくていいのなら(ファイルにはきだしていいのなら) 変換したものを一旦BMPにファイルで出力してLoadBitmapで読ませる手もあります。

noconan
質問者

補足

作成するプログラムはMDIとしているので、以下はドキュメントウィンドウのプロシージャ内に記述した物です。 case WM_PAINT:               hBitmap = CreateBitmap((int)XSIZE, (int)YSIZE, 8, 256, Image[ImageFileNumber].src);               hdc = GetDC(hwnd);               hmdc = CreateCompatibleDC(hdc);               SelectObject(hmdc, hBitmap);               BitBlt(hdc, 0, 0, XSIZE, YSIZE, hmdc, 0, 0, SRCCOPY);               DeleteDC(hmdc);               DeleteObject(hBitmap);               ReleaseDC(hwnd, hdc);               break; fread関数を使用して、rawファイルのデータをImage[ImageFileNumber].srcへ格納しました。ImageFileNumberは現在読み込んだファイルの番号です。 このプログラムを実行した結果、真っ白いドキュメントウィンドウが出力されてしまいました。 やはりSetDIBitsToDevice関数などを取り入れなければ表示できないのでしょうか? ちなみに読み込む画像は256*256の8bitのグレースケールです。 XSIZE、YSIZEともに256が格納されています。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

OPENFILENAME構造体でファイルパスを取得したら後はC言語のコンソールと同じようにfopen( FileName, "rb")で読み込めば良いのでは。

noconan
質問者

お礼

確かにそれも考えましたが、fopen関数によりfp(ファイルポインタ)を得ることになりますが、そのあとが問題になってしまいます。 そのファイルポインタを使用してどのように表示するか・・・・ BitBlt関数を使用するならデバイスコンテキストハンドルが必要なわけだし・・・・・ 難しいです。

関連するQ&A

  • SDKにてRAW画像(ヘッダ情報0)の表示

    現在RAW画像(ヘッダ情報0)の表示プログラムをSDKにて作成中です。 色々と細かな質問に対してお答えいただいた皆様に感謝します。 おかげで一応表示することができました。 しかし新たな疑問が出てきてしまいました。 詳しく説明します。 まず入力画像情報をグローバルな構造体により管理するため、 typedef struct{ unsigned char *Input_Image; int Width; int Height; HWND hwnd; char szFileName[MAX_PATH]; char szFileTitle[MAX_PATH]; LPBITMAPINFO lpBitmapInfo; HANDLE hMemBitmapInfo; HANDLE hMemInput_Image; int flag; }IMAGEINFORMATION; static IMAGEINFORMATION *Image; このように定義しました。 ちなみにこの構造体メンバの最初のメンバ*Input_Imageは入力画像が格納するポインタです。今回の問題に対しこの*Input_Imageメンバのみ注意をお願いします。 画像入力処理として Image->hMemInput_Image = GlobalAlloc(GHND, sizeof(unsigned char) * Image->Height * Image->Width); Image->Input_Image = (unsigned char *)GlobalLock(Image->hMemInput_Image); により画像情報のポインタをImage->Input_Imageに格納します。 しかし入力した情報をそのまま使用すると、表示した場合に上下さかさまに反転して表示されてしまうので、この後に画像情報の反転処理を行わなければなりません。この反転処理を行う関数をvoid ReverseBitmap(unsigned char *)として、内容を次に示します。 void ReverseBitmap(unsigned char *Input) {   int i, j, width, height;   unsigned char temp;   width = Image->Width-1;   height = Image->Height-1;   for(i=0; i<=height; i++){     for(j=0; j<=width; j++){       temp = Input[width * (height - i) + j];       Input[width * (height - i) + j] = Input[width * i + j];       Input[width * i + j] = temp;     }   } } 関数実行の記述は  ReverseBitmap(Image->Input_Image);  のように行いました。 これにより反転した配列が ReverseBitmap関数の引数に格納されていると考えたのですが、結果は反映されていませんでした。 結果として色々と試してみたのですが、どうやってもさかさまのまま表示されてしまいます。 関数への引数の渡し方、反転の仕方に問題があるようならアドバイスをお願いします。 そして、反転処理を記述した場合、2次元画像を1次元配列で操作するのは結構めんどくさいです。なのでこの上の定義をもとに、反転処理を2次元配列にて行うような方法はないでしょうか? こちらの疑問もよろしくお願いします。

  • コンソールアプリケーションからWindowsプログラムへの道順

    私は現在Visual C++ .NET 2003のスタンダードを使用して、Win32コンソールアプリケーションでプログラムを作成しています。まだまだ経験が浅いのでエラーの連続ですが、ポインタの使用や構造体の使用、クラスの使用や低水準ファイル入出力を利用して、テキストファイルの読み込み・整形・書き込みをするプログラムを作成しています。 そろそろSDKやMFCなどを学びたいと考えているのですが、書籍などでSDKを覚えてからMFCを学んだほうが良いみたいなことが書かれていました。でも、別の書籍ではいきなりMFCでも問題ないみたいなことも書いてありました。現在コンソールアプリケーションを作る私がSDKやMFCを学ぶために道順が良く分からなくなっています。 そこで現在Windowsプログラミングをされている方にお聞きしたいことがあります。質問は次のとおりです。 1、MFCを学ぶなら先にSDKを覚えてからのほうが良いですか? 2、Visual C++ .NET 2003を使用してSDKまたはMFCを学ぶのに、お勧めの書籍があったら教えてください。 3、絶版になっていない書籍を探すとVisual C++ .NET 2005を使用しているものが目立つように思えるのですが、私の所有しているバージョンを2005にしてから書籍を考えたほうが良いと思いますか? お時間がありましたら皆さんのご経験をお聞かせください。よろしくお願いいたします。

  • DirectX SDK アンインストール出来ない

    既出の質問かもしれませんが、 質問させて下さい。 OS:Windows7(64bit)で G:ドライブ Program Files(x86) ←自分で用意したフォルダ DirectX SDK (June 2010)をインストールしようとしたところ、 添付画像1のようにインストールに失敗しました。 しかし、G:ドライブ Program Files(x86)には Microsoft DirectX SDK (June 2010)フォルダが出来ており、 中身も揃っています。 そこで、そのフォルダを削除したいと思い、 コントロールパネルのプログラムと機能からアンインストールしようとしましたが、 一覧に表示されておらず、アンインストール出来ません。 どなたか、このフォルダの削除方法が分かる方おられませんか? 以下、その他、自分で試してみたこと。 ・再インストール:上記と同じくインストール失敗、しかも初回のように別ドライブを指定出来ない ・再起動:やはり一覧に表示されず ・レジストエディタ:HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥Windows¥CurrentVersion            ¥Uninstallの一覧にも表示されず。 ・アンイストールツール:Revo Uninstallerを使用、一覧に表示されず。 ・フォルダを直で削除:このプログラムは別のプログラムで使用されているため削除できませんの表示               どのアプリケーションで使用されているのか分からず。              

  • マルチスレッド化。

    今とても大きな配列を使用し、長時間処理をするプログラムを組んでいます。元々処理時間に1時間を要するプログラムを2分で処理を完了するまでに仕上げました。 しかし、探究心はおさまらずもう少し高速化に挑みたいと考えています。 過去に「猫でもわかる」のSDK第1章と2章を学び、マルチスレッドのプログラムをSDKで組んだことがあります。それを利用してマルチスレッド化を実現したいと考えています。 言語はCでVisualStudio2005を使用しています。 *疑問1   SDKの場合WinMain関数とプロシージャからの実行で_beginthread関数を記述すれば処理が開始されます。 Cでもmain関数内に記述すれば、SDKと同様に処理できるのでしょうか? *疑問2 _beginthread関数の引数に関してです。 第1引数にvoid型のスレッド関数、第2引数に0?、そして第3引数にはスレッド関数に渡すデータの引数を記述すると把握しているのですが、渡したいデータは複数あり、***型と**型、それに変数を数個とスレッド関数に渡したいデータだらけなのですが、どのように記述すればよいでしょう? *疑問3 2つのスレッドを作成しようと考えていますが、その2つのスレッドで1つの大きな配列を共有して処理したいと考えています。 そのため、スレッド間の同期が必要になるわけですが同期の種類にもクリティカルセクションやミューテックス、イベントと豊富でどれを使用すれば良いのか迷ってしまいます。厳密に同期を取り処理をするにはイベントが一番良いと考えています。 これらの疑問に答えられる方はアドバイスをよろしくお願いします。

  • ビットマップ画像の座標を小数で扱う方法について。

    ビットマップ画像の座標を小数で扱う方法について。 プログラムでビットマップ画像を扱っています。 現在、ビットマップ画像のRGBの値を2次元配列に格納しています。 そのため、例えば画像の白い部分の座標がどこかを知りたいときは、2次元配列の場所を辿り、整数値として座標を得ています。 これを整数値ではなく、少数値で扱うことは可能でしょうか? 配列で扱う以外に方法が思いつかないです;; よろしくお願いします。

  • C言語でBMP(16bit)を扱う方法

    組み込みソフトの作成を行なっており、液晶に画像を表示するソフトを 作りたいと思っております。 16bitのビットマップ画像をC言語のソースにするにはどうすればよいでしょうか? interface2011年5月号の付録(Renesas RX62N)を使用して、3.5インチQVGAのTFT液晶に 画像を表示したいと思っているのですが、自分で用意した16ビットのビットマップ画像を どうすればC言語ソースに落とせるのかがわかりません。 付録のサンプルプログラムでは、pct_data[]={65535,65535,・・・・}; と各ドットを16bitで表現した配列になっているのですが、ビットマップデータからこのような 配列の作成方法を教えて頂けると助かります。 よろしくお願いいたします。

  • ビットマップの表示について

    プログラムの初心者です。visual sudio net 2003でビットマップの表示の仕方について困っています。猫でもわかるwindows プログラム という本を参考にビットマップリソースをつくりソースファイルも参考書と同じようにしたのですが、肝心なビットマップが表示されません。ちなみにエラーは出ていません。ただ画像が表示されません。 これは使っているパソコンにも問題があるのでしょうか? パソコンはWinosw Vistaを使っています。 どうかご教授おねがいします。何か説明に足りないところがあればまた足しますのでよろしくおねがいします。

  • ディレクトリツリービューを有するWin32SDKアプリケーション

    左にエクスプローラ風のフォルダツリービューのペインを有し、ファイルをクリックすると右ペインで表示編集などの処理をする、ごく一般的な2ペインアプリケーションをMSVC++6.0 Win32SDKで作成すべく、インターネットで検索しましたが、MFCやVBの例はあるもののWin32SDKのサンプルコードを見つけることが出来ませんでした。 コモンコントロールでエクスプローラ風のフォルダツリービューのコードを自作するとなると極端な労力を要します。 そこで"Win32SDKプログラム"のフォルダツリービューの適当なサンプルコードの所在をご存知でしたらよろしくお願いします。

  • C言語 構造体配列について

    6人分の小テストの点数を記録し,平均値などを計算するプログラムを作成している. 以下の手順と条件に従ってプログラムを作成. 手順 (1) 氏名(name[100], char 型) と点数( score , int 型) をメンバにもつ構造体「struct_TEST」を(main 関数の外で)定義. (2) struct _TEST 型構造体配列 element[6] を定義. (3) キーボードから氏名(ローマ字でよい)と点数を入力する処理を6 回繰り返す. (4) 平均点を計算して画面表示. (5) 最高点を出した人の名前と点数を画面表示. (6) 平均点に満たない人の名前と点数を画面表示. 条件 (3)~(6)の処理には以下に示す関数を利用する. (3) ・・・ 氏名と点数を入力する処理をn 回繰り返す関数 void input_score( struct _TEST *a, int n ) (4) ・・・ n 個の構造体配列に対して平均を計算し,平均点を返す関数 double calc_ave( struct _TEST *a, int n ) (5) ・・・ n 個の構造体配列に対して最高点を算出し,そのユーザの配列番号を返す関数 int calc_max( struct _TEST *a, int n ) (6) ・・・ n 個の構造体配列に対して平均点に満たない人の名前と点数を画面表示する関数 void show_under_ave( struct _TEST *a, int n ) C言語の構造体が良く分かっていません。 こういった条件が多いと考えづらく分からなくなります。 考えても分かっていないので困っています。 誰かすみませんが解答を教えて下さい。

  • C++のnewで確保したメモリーの解放の確認方法

    C++で作成中のプログラムの一部で、長い文章も処理できるように、構造体とメモリーの動的確保を使用しています。 ただ、動的に確保したメモリーは自分で解放しなくてはならないのですが、プログラムが単純なうちは開放のミスを発見できますが、長くなるとバグで一部開放されない可能性も捨てきれません。 そのようなときに全て開放できたか確認する方法は無いのでしょうか? 開発環境につきましては、 OS WindowsXP HomeEdition コンパイラ BCC 言語 C++ コンソールアプリケーション struct string { char str[512]; struct string* nextstr;}; 簡単には、このような構造体を new で確保し、開放は、先頭から delete してますが、 構造体がこれより結構複雑なため、処理部が長くきちんと開放できているか自信が有りません。