GDI+の使用方法について

このQ&Aのポイント
  • VC++2010でWin32アプリケーションを作成中の方に質問です。GDI+の使用方法について教えてください。
  • Bitmapのクローンを作成する際、PixelFormatを指定する方法がわかりません。どのように定義すれば良いでしょうか?
  • また、System.Drawing名前空間の参照方法についても教えていただけますか?
回答を見る
  • ベストアンサー

GDI+の使用方法について

現在VC++2010でWin32アプリケーションを作成していて、 最近GDI+の使用を試みているのですが・・・・ Bitmapのクローンを作成する場合に、PixelFormatを指定するとことですが、 PixelFormatはどのように定義するのでしょうか? Gdiplus::Rect *rect=new Gdiplus::Rect(0,0,OrgRect.right,OrgRect.bottom); PixelFormat pf; Bitmap1=Bitmap2->Clone(rect,pf.); とすると構文のエラーになってしまいます。 PixelFormatはDontcareにしたいのですが、PixelFormatはINT型になってしまっているらしく pf.Dontcareなどもできません。 そもそも、MSDNを確認していると、名前空間:System.Drawingとありますが、 名前空間にusing System.Drawing;と記述すると「Systemが定義されていません」 となっています。ファイルの参照?というものが必要なのでしょうか? Bitmap1からBitmap2へコピーする場合(クローンを作成する場合)は 実際どのように書けばいいのでしょうか? 質問内容がゴチャゴチャして申し訳ございません。 初歩的な質問で大変恐縮ですが、ご教示願います。

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

  • ベストアンサー
  • FAY
  • ベストアンサー率49% (95/193)
回答No.2

VC++で組む場合は.NET Frameworkで組むのとはちょっと違うんですよ。 ごっちゃにすると混乱します。 > PixelFormatはDontcareにしたいのですが、PixelFormatはINT型になってしまっているらしく PixelFormat pf = PixelFormatDontCare; です。 SDKのヘッダファイルを漁るとGdiPlusPixelFormats.hの中で#defineされてたりします。 BitmapのCloneはGdiPlusBitmapに定義されている通り inline Bitmap* Bitmap::Clone(IN const Rect& rect, IN PixelFormat format); なので (中略) // namespace使ってればGdiplus::は不要 Rect rect( 0, 0, nImageWidth, nImageHeight); PixelFormat format = PixelFormatDontCare; pBitmap1 = Bitmap2.Clone(rect, format); (以下略) かな。

scanfprintf
質問者

お礼

おそくなり申し訳ございません。 仰っていただいたとおり、.NET Frameworkと混同しておりました。 (そのような気はしていたのですが・・・) PixelFormatDontCareと書けばいいですね、これでなんとかCloneは 使えそうです。日本語のヘルプもしくは、参考サイトなどが あればいいですが・・・ 的確なご回答ありがとうございます。

その他の回答 (1)

  • sygh
  • ベストアンサー率76% (42/55)
回答No.1

サンプルを示します。Rectオーバーロード版も同様です。 なお、ネイティブC++(Win32)用のGDI+は、.NETのSystem.Drawing以下のライブラリとよく似ているけれど違います。 MSDNのヘルプも英語しかありません。 http://msdn.microsoft.com/en-us/library/ms536305.aspx #include <Windows.h> #include <GdiPlus.h> #include <memory> #include <cstdio> #include <clocale> #include <conio.h> #pragma comment(lib, "gdiplus") // 簡単のため。できるかぎり完全名を使用することを推奨。 using namespace Gdiplus; class MyEncoders { UINT m_encoderNum; ImageCodecInfo* m_pEncodersArray; public: MyEncoders() : m_encoderNum() , m_pEncodersArray() { UINT size = 0; GetImageEncodersSize(&m_encoderNum, &size); m_pEncodersArray = reinterpret_cast<ImageCodecInfo*>(malloc(size)); GetImageEncoders(m_encoderNum, size, m_pEncodersArray); } ~MyEncoders() { free(m_pEncodersArray); } const ImageCodecInfo* GetEncoderByMimeType(LPCWSTR pName) const { for (UINT i = 0; i < m_encoderNum; ++i) { if (wcscmp(m_pEncodersArray[i].MimeType, pName) == 0) { return &m_pEncodersArray[i]; } } return NULL; } }; // スマート ポインタ型。 typedef std::tr1::shared_ptr<Bitmap> TBitmapPtr; void PrintBitmapInfo(LPCWSTR pBmpFilePath, Bitmap& bmp) { wprintf(L"FilePath = [%s], Width = %u, Height = %u, PixelFormat = 0x%x (%u bpp)\n", pBmpFilePath, bmp.GetWidth(), bmp.GetHeight(), bmp.GetPixelFormat(), GetPixelFormatSize(bmp.GetPixelFormat())); } void main() { _wsetlocale(LC_ALL, L""); ULONG_PTR gdipToken = 0; GdiplusStartupInput startupInput; GdiplusStartup(&gdipToken, &startupInput, NULL); { MyEncoders encoders; LPCWSTR pSrcBmpFilePath = L"test.jpg"; LPCWSTR pDstBmpFilePath = L"test.png"; Bitmap src(pSrcBmpFilePath); if (src.GetLastStatus() == Ok) { PrintBitmapInfo(pSrcBmpFilePath, src); TBitmapPtr pBmp(src.Clone(0, 0, src.GetWidth(), src.GetHeight(), src.GetPixelFormat())); if (pBmp->Save(pDstBmpFilePath, &encoders.GetEncoderByMimeType(L"image/png")->Clsid) == Ok) { PrintBitmapInfo(pDstBmpFilePath, *pBmp); } else { wprintf(L"Failed to save the image! [%s]\n", pDstBmpFilePath); } } } GdiplusShutdown(gdipToken); puts("Press any..."); _getch(); }

scanfprintf
質問者

お礼

お礼が遅くなり大変申し訳ございません。 詳細なコードまで記載いただきありがとうございます。 やはり英語のヘルプしかないんですね。 書籍を用意するしかないですかね・・・・・ 大変参考になりました。

関連するQ&A

  • GDI+で高速な描画

    GDI+を利用してお絵かきツールのようなものを作成しようと思っています。 しかしdrawImage()での画面への描画が非常に遅いようで、描いてみると線がカクカクしてしまいます。 アンチエイリアスやアルファブレンドが必要なのでGDI+を利用したいのですが、どうにか高速に描画させる方法はないでしょうか? 下記は現在のソースの一部です。 static Bitmap *offscreenBitmap //描画処理はこっちに static Graphics *offscreen; static Graphics *onscreen; //画面表示用 static RECT rect; //クライアント領域 static POINTS posPts,pts; //一つ前と現在のマウス座標 static BOOL bLButtonDown; Pen nomalPen(Color(100,0,0,0), 1); //描画用ペン switch(msg){  case WM_CREATE:   GetClientRect(hWnd,&rect);   offscreenBitmap = new Bitmap(rect.right, rect.bottom); //ビットマップ生成   offscreen = new Graphics(offscreenBitmap);   offscreen->SetCompositingMode(Gdiplus::CompositingModeSourceOver);   offscreen->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);//アンチエイリアス有効化   offscreen->Clear(Color(255,255,255)); //初期化   onscreen = new Graphics(hWnd); //ウインドウ表示用   onscreen->SetCompositingMode(CompositingModeSourceCopy);   break;  case WM_LBTTONDOWN:   bLButtonDown = TRUE;   posPts=MAKEPOINTS(lp)   break;  case WM_MOVE:   pts=MAKEPOINTS(lp)   if(bLButtonDown){    offscreen->DrawLine(&nomalPen, posPts.x, posPts.y, pts.x, pts.y);//線描画    posPts.x=pts.x;    posPts.y=pts.y;   }   InvalidateRect(hWnd,&rect,0);//ウインドウを更新   break;  case WM_PAINT:   onscreen->DrawImage(offscreenBitmap,0,0);//画面に書き出し   break; }

  • GDI+のDrawStringを使って文字を滑らかに描画したいのですが。。。

    GDI+のDrawStringを使って文字を滑らかに描画したいのですが。。。 環境は、VC++のWin32プロジェクトです。 WindowのデバイスコンテキストからGraphicsオブジェクトを生成し、DrawStringとすると滑らかに描画されます。 しかし、BitmapオブジェクトからGraphicsオブジェクトを生成し、DrawStringを行うとビットマップフォントのようです。 Graphics g(hdc); g.DrawString(......); -> この場合はなめらか(画像の下の方) しかし、 Bitmap bmp(w, h, PixelFormat32bppARGB); Graphics g (&bmp); g.SetSmootingMode(SmoothingModeHighQuality); g.DrawString(...); -> ジャギが目立つ。(画像の上の方) ビットマップ(メモリ)にスムーズなテキストを描画することはできないのでしょうか? ちなみにフォントはメイリオです。

  • GDI+で画像表示後に画面がちらつく

    GDI+を使いクライアント領域に画像を表示後に、ウィンドウサイズを変更すると変更中に画面が激しくちらつきます。本に書いてあったバックバッファを使った方法も試したのですが変わりませんでした。 どうすればちらつかないようにできますか? --- 実行環境 --- Microsoft Visual C++ 2010 Express WIN32 ユニコードビルド C++ #include <windows.h> #include <GdiPlus.h> #pragma comment(lib,"gdiplus.lib") LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); TCHAR szClassName[] = TEXT("test"); Gdiplus::Bitmap *img1=NULL; Gdiplus::Bitmap *backbuf=NULL; int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; BOOL bRet; Gdiplus::GdiplusStartupInput gdisi; ULONG_PTR gditoken; if(Gdiplus::GdiplusStartup(&gditoken,&gdisi,NULL)!= Gdiplus::Ok) return 0; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if (bRet == -1) { break; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } delete img1,backbuf; Gdiplus::GdiplusShutdown(gditoken); return (int)msg.wParam; } ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = (LPCTSTR)szClassName; wc.hIconSm = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); return (RegisterClassEx(&wc)); } BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, TEXT("GDI+で画像表示"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInst, NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { PAINTSTRUCT ps; HDC hdc; static int imgwidth; static int imgheight; switch (msg) { case WM_CREATE:{ img1=new Gdiplus::Bitmap(TEXT("test.jpg")); if(img1->GetLastStatus() != Gdiplus::Ok){ MessageBox(hWnd,TEXT("ファイルがありません"),NULL,MB_OK); } imgwidth=img1->GetWidth(); imgheight=img1->GetHeight(); backbuf=new Gdiplus::Bitmap(imgwidth,imgheight,PixelFormat32bppARGB); Gdiplus::Graphics g(backbuf); g.DrawImage(img1,0,0,imgwidth,imgheight); break;} case WM_PAINT:{ hdc=BeginPaint(hWnd,&ps); Gdiplus::Graphics g(hdc); g.DrawImage(backbuf,0,0,imgwidth,imgheight); EndPaint(hWnd,&ps); break;} case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

  • GDIによるメモリ上からの画像データ読み込みに関して

    開発環境はVC++/CLIです。 アンマネージ型のCOMオブジェクトの扱いで困っております。 JPEGやPNGなどの画像データを保存したunsigned char型配列から、Gdiplus::Bitmap型を作ろうとしています。 unsigned int imagesize; // 画像のバイト数が格納されている array<unsigned char>^ image = gcnew array<unsigned char>(imagesize); //画像のデータが格納されている 事前にこのようなデータを用意し、以下のように記述しました。 HGLOBAL hResourceBuffer = GlobalAlloc(GMEM_MOVEABLE , imagesize); void* pResourceBuffer = GlobalLock(hResourceBuffer); CopyMemory(pResourceBuffer, &image, imagesize); IStream* pIStream = NULL; CreateStreamOnHGlobal(hResourceBuffer, TRUE, &pIStream) data->bmp = new Gdiplus::Bitmap(pIStream); pIStream->Release(); GlobalUnlock(hResourceBuffer); GlobalFree(hResourceBuffer); しかしながら、上記のコードだと、CopyMemory時に「保護されたメモリに書き込もうとした」といったエラーが発生します。 Webで色々検索しましたが、全て似たような記述で動作していました。 何が問題なのでしょうか? 尚、上記と同様の画像データ配列を使って、System::Drawing::Bitmap型に格納したとき、画像が正常に表示されることを確認しております。 画像のバイト数に於いても取得したデータに間違いはなく、やはりメモリ関連の問題だと思うのですが…。 MemoryStream^ memst = gcnew MemoryStream(image); Bitmap^ bmp = gcnew Bitmap(memst); memst->Close(); Graphics^ im = pictureBox1->CreateGraphics(); im->DrawImage(bmp, 0, 0, 100, 100); delete bmp;

  • C# でパネルのマウスイベントが取得できない

    OpenNI(キネクトセンサー)のサンプルプログラムは、C#のパネルにbitmapを描画し続けるのですが、 描画中、そのパネルのマウスイベントが生じない(無視されている?)ようです。マウスの位置から 補助線を引いたりしたいのですが、描画中にマウスイベントが取得できる方法をご存知の方、お願いします。以下サンプルソースそのままです。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Text; using System.Windows.Forms; using OpenNI; using System.Threading; using System.Drawing.Imaging; namespace SimpleViewer.net { private unsafe void ReaderThread() { DepthMetaData depthMD = new DepthMetaData(); while (this.shouldRun) { try { this.context.WaitOneUpdateAll(this.depth); } catch (Exception) { } this.depth.GetMetaData(depthMD); lock (this) { Rectangle rect = new Rectangle(0, 0, this.bitmap.Width, this.bitmap.Height); BitmapData data = this.bitmap.LockBits(rect, ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb); ushort* pDepth = (ushort*)this.depth.DepthMapPtr.ToPointer(); // set pixels for (int y = 0; y < depthMD.YRes; ++y) { byte* pDest = (byte*)data.Scan0.ToPointer() + y * data.Stride; for (int x = 0; x < depthMD.XRes; ++x, ++pDepth, pDest += 3) { byte pixel = (byte)this.histogram[*pDepth]; pDest[0] = 0; pDest[1] = pixel; pDest[2] = pixel; } } this.bitmap.UnlockBits(data); } this.Invalidate(); } } private readonly string SAMPLE_XML_FILE = @"../../../Data/SamplesConfig.xml"; private Context context; private ScriptNode scriptNode; private DepthGenerator depth; private Thread readerThread; private bool shouldRun; private Bitmap bitmap; private int[] histogram; } }

  • Bitmapのディスク容量

     以下、VBの記法で書きます。Windows10,.NETのGDI+を使用しています。  PixelFormat が Format32bppArgb のBitmapを作成し、描画処理が終わった後、Bitmap.Save(パス名)で保存します。  Bitmapは1250×1250(pixel)なので、そのディスク容量は、   1250×1250×4(byte)=6104 KB=6 MB くらいと思ってました。ところが保存してみると、60 KBくらい・・・。  読みだして表示するとちゃんと保存されてるので、これはこれであり難い事なのですが、どうして?、という質問です(^^;)。  PixelFormat が Format32bppArgb の場合は初期化時に、各pixelの(A,R,G,B) は (A,R,G,B)=(0,0,0,0)であり、例えばPictureBox の BackColor との兼ね合いで、(R,G,B)=(0,0,0)(黒)はDefaultで透過色になってるので、ディスク保存時には、pixel位置を表すIndex付きでpixel情報が圧縮されて保存されるのかしら?、などと想像したわけです。  たんに気になるので、どうなってるか知りたいだけです。ネットで検索してもBitmapの大きさは、画素数×4 byte という記事しか出てこないので・・・(^^;)。  関連する検索キーワードでも良いので、教えてもらえませんか。

  • MFCでのBITMAP作成について

    VC++2005MFCで開発しています。 カメラからの画像入力の部分を作成しているのですがchar配列からのカラーbitmapの作成の仕方が分かる方いませんでしょうか? 直接ファイルに書き込む方法ですとフォーマット通りに書き込めば良いとは思うのですが、画面表示をしたいのでCBitmap又はHBitmapで取得したいです。 調べていると、モノクロだとSepBitmapBitsでできそうです。 しかし、msdnを見るとカラーの場合はSetDIBitsを使用しろとあるのですが、SetDIBitsの項を見ると何か思っている用法と違いそうです。 また、VC++.NETですとDrawing::Bitmap(( width, height, stride, format, scan0);でフォーマットを指定して作成できそうなのですが、それに相応するようなものはないかと探しているのですが見つかりません。 すいませんがご教授お願いします。

  • 色の変更

    また分からないことが出来ましたので、よろしくお願いいたします。 今、openFileDialogで画像を読取、その画像の黒色を白色に変更してpicutreBoxに表示するプログラムを作成しています。 [C#] Bitmap img = new Bitmap(openFileDialog.FileName); Graphics g = Graphics.FromImage(img); System.Drawing.Imaging.ColorMap[] cms = new System.Drawing.Imaging.ColorMap[] {new System.Drawing.Imaging.ColorMap(), new System.Drawing.Imaging.ColorMap()}; cms[0].OldColor = Color.Black; cms[0].NewColor = Color.White; System.Drawing.Imaging.ImageAttributes ia = new System.Drawing.Imaging.ImageAttributes(); ia.SetRemapTable(cms); g.DrawImage(img, new Rectangle(img.Width + 10, 0, img.Width, img.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel,ia); g.Dispose(); PictureBox1.Image = img; という風に作成したのですが、色が変更されませんでした。 どこが違うのか分かられる方がいらっしゃいましたら、よろしくお願いいたします。

  • VB.NETでのPictureBoxによる画像保存について

    またお世話になります。 VB.NETでプログラムでPictureBoxに絵を描かせているのですが、そこまでは表示させることができました。このできた画像をBitmapなりjpegなりに保存させて、ほかの画像ビューワ等でも見れる形にしたいのですがうまくいきません。 ちなみに今はこのように書いて、 Dim gra1 As Graphics = PictureBox1.CreateGraphics FileOpen(2, myfile2, OpenMode.Output) (絵を描かせるプログラム) PictureBox1.Image.Save(myfile2, System.Drawing.Imaging.ImageFormat.Bmp) FileClose(2) としてまわしたところ、 System.Runtime.InteropServices.ExternalException' のハンドルされていない例外が system.drawing.dll で発生しました。 追加情報 : GDI+ で一般的なエラーが発生しました。 といわれました。 どなたかご教授いただけたらお願いしますm(__)m

  • Open CVについて

    現在,OpenCVとVC++2008のC++/CLIでwindows formアプリケーションを作成しています。 フォーム上のpictureBoxにUSBカメラから取得した画像を,録画しながら,pictureBoxに表示させています。しかし,取り込んだ画像が,pictureBoxに収まり切っていないようです。(添付画像のようなに枠内の画像に対して,肌色部分しか,pictureBoxに表示されていない状態) コードは http://hisoap.jugem.jp/?eid=156 を参考に,以下のように記述しています。 CvCapture *capture srcImage = cvQueryFrame(capture); Bitmap^ bmpPicBox = gcnew Bitmap(pictureBox->Width, pictureBox->Height); pictureBox->Image = bmpPicBox; Graphics^g = Graphics::FromImage(pictureBox->Image); Bitmap^ bmp = gcnew Bitmap(pictureBox->Width, pictureBox->Height, srcImage->widthStep,System::Drawing::Imaging::PixelFormat::Format24bppRgb, IntPtr(srcImage->imageData)); g->DrawImage(bmp, 0, 0, srcImage->width , srcImage->height); どのようにすれば,画像をpictureBoxにぴったりと表示させることができるでしょうか?