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

現在「猫でもわかる」を参考にSDKを学んでいるものです。
ここで[ 画像の表示 ]などをプログラムしていると疑問が出てきます。

今大学で画像処理専門の研究室に所属しているので、そこで培った技術を是非SDKで組めればと思います。

C言語のコンソールではraw画像を読み込み、処理し、出力するといったプログラムは組めるのですが、SDKにて同様な処理を実現しようと考えるとちょっとなやみます。

「猫でもわかる」では画像の表示をビットマップ画像を例にとってプログラムをしているのですが、raw画像の場合ばどのようになるのでしょう?


具体的に行いたいことは、自作したraw画像の読み込み関数を利用してraw画像をグローバルな配列へ読み込み、その配列を使用し内部で画像処理をした後、新しいウィンドウにその処理後の画像を表示するようにしたいと考えています。


「猫でもわかる」ではOPENFILENAME構造体を利用してビットマップを読み込んでいるのですが、自分もOPENFILENAME構造体を使用して既存のファイルオープン用のダイアログボックスから読み込ませたいと考えています。

すこし荒い要求ですが、こたえられる方はよろしくお願いします。

A 回答 (7件)

>BITMAPINFO pbi = (BITMAPINFO *)new char[size];


*pbiの間違いでした。

C++ではなくCを使っている場合、new は malloc と同じようなものと思って下さい。
>for (int i = 0; i < 256; i++)
これもエラーになりそうです。
    • good
    • 0
この回答へのお礼

返答が遅れ申し訳ありませんでした。

やっと今日作成することができました。
色々とてこずりましたが、輝度情報を格納した配列を意図するように表示することができてほっとしております。

時間がかかりすぎましたねw

また何かあったらよろしくお願いします。

お礼日時:2007/05/01 19:19

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を作成して直接書き換えるようにした方が無駄が無いです。
    • good
    • 0

まず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を参考にして調べてください。
    • good
    • 0
この回答へのお礼

返答が遅れ申し訳ありませんでした。

やっと今日作成することができました。
色々とてこずりましたが、輝度情報を格納した配列を意図するように表示することができてほっとしております。

時間がかかりすぎましたねw

また何かあったらよろしくお願いします。

お礼日時:2007/05/01 19:19

★多分、原因は『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 プログラミングは間際らしいです。気をつけましょう。
・以上。参考に!
    • good
    • 0
この回答へのお礼

返答が遅れ申し訳ありませんでした。

やっと今日作成することができました。
色々とてこずりましたが、輝度情報を格納した配列を意図するように表示することができてほっとしております。

時間がかかりすぎましたねw

また何かあったらよろしくお願いします。

お礼日時:2007/05/01 19:18

★CUI の main() 関数内で WinMain() のメッセージループを記述します。


・これで単純にウインドウが表示されます。
 その後、WM_CREATE メッセージ内でグローバルな配列で読み込んだ raw 画像を描画します。
 つまり、WM_CREATE メッセージ内で GetDC()、ReleaseDC() で HDC を操作すれば良い。

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

この回答への補足

返信ありがとうございました。

実験した結果をしたの回答者さんの補足に書いておきました。

解決の仕方をお願いしたいです。

よろしくお願いします。

補足日時:2007/04/24 22:50
    • good
    • 0

>そのファイルポインタを使用してどのように表示するか・・・・


>BitBlt関数を使用するならデバイスコンテキストハンドルが必要なわけだし・・・・・

デバイスコンテキストハンドルが必要ならCreateCompatibleDCを使ってください。
CreateBitmapで作ったオブジェクトをSelectObjecでそのDCと関連させます。
後はそのDCをSetDIBitsToDevice/StretchDIBits/SetDIBits等で操作します。
まずそれらのAPIを調べてください。
あとは、そのDCをWM_PAINT(BeginPaint)で受け取るHDCに
BitBltなりStretchBltなりで貼り付ければ表示できます。
(SetPixelを使って1ドットずつ塗りつぶすなんて力技もありますが
かなり遅いので現実的ではないです。)

必ずしもメモリ内で処理しなくていいのなら(ファイルにはきだしていいのなら)
変換したものを一旦BMPにファイルで出力してLoadBitmapで読ませる手もあります。

この回答への補足

作成するプログラムは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が格納されています。

補足日時:2007/04/24 22:44
    • good
    • 0

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

    • good
    • 0
この回答へのお礼

確かにそれも考えましたが、fopen関数によりfp(ファイルポインタ)を得ることになりますが、そのあとが問題になってしまいます。

そのファイルポインタを使用してどのように表示するか・・・・
BitBlt関数を使用するならデバイスコンテキストハンドルが必要なわけだし・・・・・

難しいです。

お礼日時:2007/04/24 10:03

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