StretchBlt関数で画像を縮小して表示しようとしていますが、うまくいきません

このQ&Aのポイント
  • 画像を縮小して表示するためにStretchBlt関数を使用していますが、うまくいきません。
  • 現在、画面の縦幅の中央に表示するためのコードを試していますが、横は問題なく表示されますが、縦に拡大されてしまいます。
  • StretchBlt関数を使用しないでBitBlt関数に書き換えると正常に表示されることもわかりました。座標の取得は正しく行っています。
回答を見る
  • ベストアンサー

StretchBlt関数について

StretchBlt関数について 画像を縮小して表示しようとしていますが、上手くいきません。 beforeはint型の変数で現在「0」が入っていますので、 無視していただきたいと思います。 まず、テストでStretchBlt関数で縮小しない状態で画面縦幅の中央に表示しようと 下記コードで試みましたが、横は問題ないようですが、 縦に拡大1.5倍くらい拡大されてしまいました。 int MyBitOpen(HWND hWnd,HDC hNormalDC,DataParam *data){ HBITMAP hBitmap; BITMAP bmpInfo={0}; HDC hBitDC; RECT rc; hBitDC=CreateCompatibleDC(NULL); hBitmap=(HBITMAP)LoadImage(NULL,data->szFile[data->iFileCount], IMAGE_BITMAP,0,0,LR_LOADFROMFILE); GetObject(hBitmap,sizeof(BITMAP),&bmpInfo); SelectObject(hBitDC,hBitmap); GetClientRect(hWnd,&rc); StretchBlt(hNormalDC,before+5,(rc.bottom-bmpInfo.bmHeight)/2, (before+5)+bmpInfo.bmWidth,((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight, hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 関数から戻り BitBlt(hdc,0,0,rc.right,rc.bottom,hNormalDC,0,0,SRCCOPY); で画面出力しております。 これがうまくいかない理由もわかりませんが、 下記のように(1)StretchBltを使用せずBitBltに書き換えただけのものと (2)StretchBltを使用しても描画開始座標を(0、0)に変更したものは 拡大されず上手くいってしまいます。 (1) BitBlt(hNormalDC,before+5,(rc.bottom-bmpInfo.bmHeight)/2, (before+5)+bmpInfo.bmWidth,((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight, hBitDC,0,0,SRCCOPY); (2) StretchBlt(hNormalDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight, hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); 座標の取得は間違っていないと思うのですが・・ 本来は画面中央に縦横1/2に縮小した下記のコードでしたが まず上記がうまくいっていないので・・・ 初心者のためシンプルに書けませんでした↓ StretchBlt(hNormalDC,((before+5)+(bmpInfo.bmWidth/4)), (((rc.bottom-bmpInfo.bmHeight)/2)+(bmpInfo.bmHeight/4)), (((before+5)+bmpInfo.bmWidth)-(bmpInfo.bmWidth/4)), ((((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight)-(bmpInfo.bmHeight/4)), hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); ご教授よろしくお願いします。

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

  • ベストアンサー
回答No.1

> StretchBlt(hNormalDC,before+5,(rc.bottom-bmpInfo.bmHeight)/2, (before+5)+bmpInfo.bmWidth,((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight, hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); どう見ても拡縮後のサイズを示す (before+5)+bmpInfo.bmWidth と ((rc.bottom-bmpInfo.bmHeight)/2)+bmpInfo.bmHeight の指定が不明です。 水平方向と垂直方向のアスペクト比を変えたくないのであれば、ここは拡縮比率を一致させたサイズの記述になるはずですが、ここに描画開始位置の座標+元画像のサイズが記されているので、描画された結果はアスペクト比が狂ったものになります。 元画像の等倍のままで描画するのであれば、 StretchBlt(hNormalDC,before+5,(rc.bottom-bmpInfo.bmHeight)/2, bmpInfo.bmWidth,bmpInfo.bmHeight, hBitDC,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,SRCCOPY); で良いはずです。

scanfprintf
質問者

お礼

こんな時間にも関わらず瞬時に私の勘違いを性格にご指摘していただき、 大変感謝しています。 至らない部分が多いので、これからもOKWAVEでの質問もあるかと思いますが 見かけましたらよろしくお願いいたします。

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

転送先の高さと幅の式が変だと思いますよ StretchBltの転送先の幅と高さならば before+5 や (rc.bottom-bmINfo.bmHeight)/2は不要だと思います これらがあると 幅は+5、高さは余白の半分を加算 といったことになり、希望の大きさより大きくなります 左上の点と右下の点を指示ではなく 左上の点と幅、高さを指示という仕様ですから たとえば 100x150画像を 20,30を左上で描画する場合 StretchBlt( hDC, 20, 30, 100, 150, ... といった具合です これが 100,15を左上で描画する際も StretchBlt( hDC, 100, 15, 100, 150, ... といった具合に変化するだけですよ ・・・

scanfprintf
質問者

お礼

ありがとうございました。 確かに左上の座標と右下の座標を指定するのだと勘違いしておりました。 即解決いたしました。相談させていただいてよかったです。

関連するQ&A

  • ActiveBasic 透過画像の作り方

    ゲームを作っています。 そのときに、背景を透過した画像を作る関数を書いたのですが、どうしてもうまく処理が出来ません。 Function CreateMask(hBmp As HBITMAP) As HBITMAP Dim hDC As HDC Dim hBaseDC As HDC,hBaseBmp As HBITMAP Dim hMaskDC As HDC,hMaskBmp As HBITMAP Dim hTempDC As HDC,hTempBmp As HBITMAP Dim hCompDC As HDC,hCompBmp As HBITMAP Dim bmp As BITMAP Dim dummy[5] As HBITMAP hDC=GetDC(hMainWnd) hBaseDC=CreateCompatibleDC(hDC) hMaskDC=CreateCompatibleDC(hDC) hTempDC=CreateCompatibleDC(hDC) hCompDC=CreateCompatibleDC(hDC) GetObject(hBmp,len(bmp),bmp) hMaskBmp=CreateCompatibleBitmap(hMaskDC,bmp.bmWidth,bmp.bmHeight) hBaseBmp=CreateCompatibleBitmap(hDC,bmp.bmWidth,bmp.bmHeight) hCompBmp=CreateCompatibleBitmap(hDC,bmp.bmWidth,bmp.bmHeight) dummy[0]=SelectObject(hTempDC,hBmp) dummy[1]=SelectObject(hMaskDC,hMaskBmp) dummy[2]=SelectObject(hBaseDC,hBaseBmp) dummy[3]=SelectObject(hCompDC,hCompBmp) SetBkColor(hTempDC,GetPixel(hTempDC,0,0)) BitBlt(hMaskDC,0,0,bmp.bmWidth,bmp.bmHeight,hTempDC,0,0,NOTSRCCOPY) BitBlt(hBaseDC,0,0,bmp.bmWidth,bmp.bmHeight,hTempDC,0,0,SRCCOPY) BitBlt(hBaseDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,SRCAND) BitBlt(hMaskDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,NOTSRCCOPY) BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,SRCAND) BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hBaseDC,0,0,SRCPAINT) SelectObject(hTempDC,dummy[0]) SelectObject(hMaskDC,dummy[1]) SelectObject(hBaseDC,dummy[2]) SelectObject(hCompDC,dummy[3]) DeleteDC(hTempDC) DeleteDC(hMaskDC) DeleteDC(hBaseDC) DeleteDC(hCompDC) CreateMask=hCompBmp End Function とりあえず、いろいろと実験したところ、 背景を黒くしたもの(hBaseDC)とマスク画像(hMaskDC)はちゃんと出来ています。 おそらく問題なのは、 BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hMaskDC,0,0,SRCAND) BitBlt(hCompDC,0,0,bmp.bmWidth,bmp.bmHeight,hBaseDC,0,0,SRCPAINT) ここではないかと思っています。 これを処理すると、背景を黒くしたもの(hBaseDC)と同じものが出てきます。 これを透過するにはどうしたらいいのでしょうか? ご教授お願いします。 Win.XP AB 4.23.00

  • 透過済み画像を作りたい

    プログラムを始めたところの初心者です。 画像を透過し、ウインドウに表示させたいので、いろいろ探してみたところ、 マスクを自動で作成すると言う物があったので、参考にさせてもらいました。 さらに、その中に、『同じように透過済み画像を作れる』とあったので、いろいろ試したのですが、ダメでした・・・ よろしければ、やり方を教えていただけないでしょうか。 http://oshiete1.goo.ne.jp/qa5254128.html 上を参考にさせていただきました Dim hDC as HDC, hTemp As HDC, hDest as HDC,hOriDC As HDC Dim hBmpTemp as HBITMAP, dummy(3) as HBITMAP,hOriBmp As HBITMAP Dim bmp as BITMAP Dim hMemDC As HDC,hMemBmp As HBITMAP hDC=GetDC(NULL) hTemp=CreateCompatibleDC(hDC) hDest=CreateCompatibleDC(hDC) hOriDC=CreateCompatibleDC(hDC) hMemDC=CreateCompatibleDC(hDC) ReleaseDC(NULL,hDC) ' 元画像の情報の取得 GetObject(hBmp,Len(bmp),bmp) ' モノクロBITMAPの生成 hBmpTemp=CreateCompatibleBitmap(hDest,bmp.bmWidth,bmp.bmHeight) hOriBmp=CreateCompatibleBitmap(hOriDC,bmp.bmWidth,bmp.bmHeight) hMemBmp=hBmp dummy(0)=SelectObject(hTemp,hBmp) dummy(1)=SelectObject(hDest,hBmpTemp) dummy(2)=SelectObject(hOriDC,hOriBmp) dummy(3)=SelectObject(hMemDC,hMemBmp) SetBkColor(hTemp,GetPixel(hTemp,0,0)) ' 背景マスクの生成 BitBlt(hDest,0,0,bmp.bmWidth,bmp.bmHeight,hTemp,0,0,SRCCOPY) 'スプライト BitBlt(hOriDC,0,0,bmp.bmWidth,bmp.bmHeight,hDest,0,0,NOTSRCCOPY) BitBlt(hOriDC,0,0,bmp.bmWidth,bmp.bmHeight,hTemp,0,0,SRCAND) '透過 BitBlt(hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,hDest,0,0,SRCAND) BitBlt(hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,hOriDC,0,0,SRCPAINT) ' HBITMAPの切り離し SelectObject(hTemp,dummy(0)) SelectObject(hDest,dummy(1)) SelectObject(hOriDC,dummy(2)) SelectObject(hMemDC,dummy(2)) ' HDCの後始末 DeleteDC(hTemp) DeleteDC(hDest) DeleteDC(hOriDC) DeleteDC(hMemDC) ' 呼び出し元への返り値 MakeMaskWith=hMemBmp

  • ビットマップの描画について(Windowプログラミング)

    おせわになります。 現在WIndows上で動作するソフトを作成しています。 ほとんど作成は終わっているのですが、作成したWindowsの上にビットマップを描画する部分で不安な点があります。 (これまであまり手をつけていなかったので) ネットなどを参考に作成したのですが、サンプルコードを見ていただいておかしいところを指摘していただければ幸いです。 以下のようなコードになります。 int ShowBMP(HWND hWnd, HDC hdc) { HDC hmdc; HBITMAP hBitmap; BITMAP bmp; HINSTANCE hInst; int BMP_W, BMP_H; hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); hBitmap = LoadBitmap(hInst, "TOPBMP"); GetObject(hBitmap, sizeof(BITMAP), &bmp); BMP_W = (int)bmp.bmWidth; BMP_H = (int)bmp.bmHeight; hmdc = CreateCompatibleDC(hdc); SelectObject(hmdc, hBitmap); BitBlt(hdc, 0, 0, BMP_W, BMP_H, hmdc, 0, 0, SRCCOPY); DeleteDC(hmdc); DeleteObject(hBitmap); return 1; }

  • ビットマップ画像表示

    いつもお世話になっております。 VS2005でC++を用いてWindowsアプリケーションの作成をしています。 子ウィンドウにビットマップ画像(ファイル名:HELP.bmp)を 表示させようとプログラムを組んだのですが、 子ウィンドウを出してもビットマップ画像が表示されません。 以下のようなプログラムを追加しました。 --------------------------------- ///リソーススクリプト/////////////////////////////////  IDB_BITMAP1  BITMAP DISCARDABLE  "HELP.bmp" ///ヘッダースクリプト/////////////////////////////////  #define IDB_BITMAP1   3000 ///ソーススクリプト/////////////////////////////////// void ShowMyBMP(HWND hWnd, HDC hdc){   HDC hmdc;   HBITMAP hBitmap;   BITMAP bmp;   HINSTANCE hInst;   int BMP_W, BMP_H;   hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);   hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_BITMAP1));  //インスタンスハンドル取得   GetObject(hBitmap, sizeof(BITMAP), &bmp);  //ビットマップの情報を得る   BMP_W = (int)bmp.bmWidth;  //画像の幅   BMP_H = (int)bmp.bmHeight;  //画像の高さ   hmdc = CreateCompatibleDC(hdc);  //メモリデバイスコンテキストハンドルを取得   SelectObject(hmdc, hBitmap);   BitBlt(hdc, 0, 0, BMP_W, BMP_H, hmdc, 0, 0, SRCCOPY);   StretchBlt(hdc, 0, BMP_H, BMP_W / 2, BMP_H / 2, hmdc, 0, 0, BMP_W, BMP_H, SRCCOPY);   DeleteDC(hmdc); //デバイスコンテキストハンドルを開放   DeleteObject(hBitmap);   return; } --------------------------------- ShowMyBMP関数は子ウィンドウを表示するときに実行されます。 全て載せられないので追加した部分のみプログラムを載せましたが、 この部分だけでも、プログラムの間違い等はありませんでしょうか。 ご教授お願いいたします。

  • WinAPIで画像を更新し続けるには

    本を見ながら、WindowsSDKを使ってビットマップを描画する 所まではできたのですが、動かそうとすると上手くいきません。 ソースを簡略かして載せますと、以下のようにしています。 case WM_KEYDOWN: x++; // static MyDrawBitMap( hWnd, x, 10 ); ------------------------------------------------ void MyDrawBitMap( HWND hWnd, int x, int y ) { hdc = BeginPaint(hWnd, &ps); BitBlt( hdc, x, y, bitmap.bmWidth, bitmap.bmHeight, hMemDC, 0, 0, SRCCOPY); EndPaint(hWnd, &ps); このように書いてますが、ボタンを押しても画面に変化が出ません。 PAINTSTRUCTは再描画が必要な情報に関する構造体だとは解っていま すが、特に変更の必要の無い画像も再描画したい場合の処理はどうす れば良いのでしょうか?よろしくお願いします。

  • c言語を使いダイアログにbmpを表示したい 

    はじめまして、 私は、c言語は初心者なのでが、ダイアログボックスに、画像(bmp)が表示することができません。 ソースは、 hdc = BeginPaint(hDlg, &ps); //指定ウィンドウ内での描写準備 // ビットマップをファイルからロードする hBitmap = ::LoadBitmap( NULL, _T("test.bmp") ); // ウィンドウのデバイスコンテキストハンドルを取得する hDC = GetDC( hDlg ); // メモリデバイスコンテキストを作成する hCompatDC = CreateCompatibleDC( hDC ); // ロードしたビットマップを選択する GetObject(hBitmap, sizeof(BITMAP), &bmp); // ビットマップをウィンドウに転送する(表示する) if(hBitmap != NULL){ StretchBlt( hDC, 0, 0, 100, 100, hCompatDC, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY ); SendDlgItemMessage( hDlg, IDC_STATIC, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap); } なのですが、これはメインウィンドウでは動くのですが、ダイアログボックスでは動かずこまっています。 どうか、助言のほどよろしくお願いします。

  • 画像表示について

    画像を表示させたいのですがうまくいきません。 途中まで打ってみたのでご意見お願いします。 (リソースから読み込んで表示させる方法) 環境:MicrosoftVisualC++ SDK ******省略********* case WM_PAINT:   hdc = BeginPaint(hWnd,&ps);   //ビットマップリソースハンドルの取得   hBmp = LoadBitmap( hInst, MAKEINTRESOURCE(IDB_BITMAP1));   if(hBmp == NULL){     MessageBox(hWnd,"ファイルの読み込みに失敗しました。","エラー",MB_ICONWARNING | MB_OK);     exit(1);   }   //ビットマップの大きさの情報取得   GetObject(hBmp,(int)sizeof(BITMAP),&bmp_info);   w = bmp_info.bmWidth;   h = bmp_info.bmHeight;   hdc_mem = CreateCompatibleDC(hdc);   SelectObject(hdc_mem,hBmp);   BitBlt(hdc,0,0,w,h,hdc_mem,0,0,SRCCOPY);   DeleteDC(hdc_mem);   DeleteObject(hBmp);   EndPaint(hWnd,&ps);   break; ******リソース(img.rc)****** // // Bitmap // IDB_BITMAP1 BITMAP DISCARDABLE "bitmap1.bmp" #ifdef APSTUDIO_INVOKED

  • OnPaint() とOnDraw()の違いについて

    OnPaint内に記述した下記コードでビットマップが描画されますが、OnDraw内だと描画されません。 どうしてなのか教えてください。 お願いします。 void CAbcView::OnPaint() { HBITMAP myDIB; // ビットマップのハンドル HBITMAP oldDIB; HDC hDC; // デバイスコンテキストのハンドル HDC hCompatiDC; // メモリデバイスコンテキスト PAINTSTRUCT ps; // クライアント領域の描画に使う情報を保持 if(!m_BmpInfo) return; hDC = ::GetDC(m_hWnd);//これでもOK ::BeginPaint(m_hWnd,&ps); hCompatiDC = ::CreateCompatibleDC(hDC);//hDC); myDIB = ::CreateDIBitmap(hDC,&m_BmpInfo->bmiHeader, CBM_INIT,m_BmpImage,m_BmpInfo,DIB_RGB_COLORS); oldDIB=(HBITMAP)::SelectObject(hCompatiDC,myDIB); BitBlt(hDC,5,25,m_BmpInfo->bmiHeader.biWidth, m_BmpInfo->bmiHeader.biHeight,hCompatiDC,0,0,SRCCOPY); 略 } 環境 WIN98 VC++6.0 MFC にて

  • c++ ダブルバッファリング、以下のコードでできず

    こんばんわ。visual studio express 2013でC++を勉強している者です。 ダブルバッファリングをしたいのですが、チラつきが改善しません。 どう書けばダブルバッファリングを実現できるのか、ご教授ください。 以下は私が書いたコードの一部です。よろしくお願いします。 (要は、hdc_mem1のビットマップを、hdc_mem0(白紙のビットマップ)に読み込み、hdc_mem0のみを画面に表示しようとしています。 いずれは用意したすべての種類のビットマップをhdc_mem0に読み込み、hdc_mem0のみ画面に表示させることによってチラつきを抑えようと考えています) case WM_CREATE:  hdc = GetDC(hWnd);  hBmp0 = LoadBitmap(hInst, TEXT("MYBMP0"));  GetObject(hBmp0, (int)sizeof(BITMAP), &bmp_info0);  hdc_mem0 = CreateCompatibleDC(hdc);  SelectObject(hdc_mem0, hBmp0);  hBmp1 = LoadBitmap(hInst, TEXT("MYBMP1"));  GetObject(hBmp1, (int)sizeof(BITMAP), &bmp_info1);  hdc_mem1 = CreateCompatibleDC(hdc);  SelectObject(hdc_mem1, hBmp1);  DeleteObject(hBmp0);  DeleteObject(hBmp1);  ReleaseDC(hWnd, hdc);  break; case WM_PAINT:  hdc = BeginPaint(hWnd, &ps);  BitBlt(hdc_mem0, 0, 0, bmp_info1.bmWidth, bmp_info1.bmHeight, hdc_mem1, 0, 0, SRCCOPY);  BitBlt(hdc, 0, 0, bmp_info0.bmWidth, bmp_info0.bmHeight, hdc_mem0, 0, 0, SRCCOPY);  EndPaint(hWnd, &ps);  break; case WM_DESTROY:  DeleteDC(hdc_mem0);  DeleteDC(hdc_mem1);  PostQuitMessage(0);  break;

  • GetDIBits関数の使い方について

    いつも丁寧なご回答を頂きありがとうございます。 GetDIBits関数の使い方について質問させて頂きます。 http://msdn.microsoft.com/ja-jp/library/cc428673.aspx 上記サイトを参考にして色々と試してみてWin32APIでは正常に動作したのですが、C#で正常に動作しません。 <Win32API> LPCOLORREF pScanData = NULL; BITMAPINFOHEADER bmpinfo = {0}; pScanData = new COLORREF[ bmp.bmWidth ]; bmpinfo.biSize = sizeof(BITMAPINFOHEADER); bmpinfo.biWidth = bmp.bmWidth; bmpinfo.biHeight = bmp.bmHeight; bmpinfo.biPlanes = 1; bmpinfo.biBitCount = 32; bmpinfo.biCompression = BI_RGB; // 一行分画像データを DIB で取り出す GetDIBits( hdc, hBitmap,1, 1, pScanData, (LPBITMAPINFO)&bmpinfo, DIB_RGB_COLORS ); 特に第5、6引数に何を渡してやればいいのかがわかりません。 以上ご助言よろしくお願いいたします。

専門家に質問してみよう