PBoxのGraphicsをImageに書き込む

このQ&Aのポイント
  • PictureBoxを使用して画像に文字や図形を描画する方法を教えてください。
  • 保存用のBMPにPictureBox AAとBBを書き込んでJpeg形式で保存したいのですが、BBのImageプロパティが未定義で書き込めません。どのようにすれば実現できますか?
  • PCの画面上ではPictureBox AAの上にBBが表示され、背景のAA画像に文字や図形を重ねて描画できています。
回答を見る
  • ベストアンサー

PBoxのGraphicsをImageに書き込む

お世話になります PictureBoxを2枚使用して以下の様に現状はなっております。 PictureBox AAは背景となる画像を描画 AA->Image = bmpGazou; PictureBox BBはAAのオーバーレイとして、文字や図形をGraphicsオブジェクトに描画したり編集したりしています。 主にg->FillEllipse等で円を描画しています ※文字や図形以外は透過 やりたいこと 保存用のBMPを作成して、そこにAAとBBを書き込んで、Jpeg保存したい 保存用BMPを定義して Bitmap^ bmp = gcnew Bitmap(ixSize, iySize); Graphics^ g = Graphics::FromImage(bmp); そこにAAを書き込む g->DrawImage(AA->Image,・・・ ここまでは正常にできたのですが、 BBのImageプロパティが未定義なので、g->DrawImageではBBを書き込めませんでした。 GraphicsオブジェクトをBMPに上書き(重ね書き)したいのですが、 どの様にすればよいのか教えていただけないでしょうか。 ↓等も見てはいるのですが、前提条件のBBの使い方が違うので、やり方が判りませんでした。 http://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html ※PCの画面上はAAの上にBBが表示され、背景のAA画像に文字や図形を重ねて描画できております。

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

  • ベストアンサー
  • hitomura
  • ベストアンサー率48% (325/664)
回答No.2

あーと、自分の言いたかったことが伝わってないようですみません。保存時に保存用 BMP を生成するという手順を変えろと言うつもりは全くありません。その手順にひと手間を追加してみたらどうかということです。 たとえば、 > 主にg->FillEllipse等で円を描画しています というのであれば、その FillEllipse で使用したパラメータがあるはずです。 そのパラメータと、FillEllipse で描画したという事実を覚えておくということです。ここで保存用 BMP に描画はしませんし、そもそもこの時点では保存用 BMP は存在しないはずです。 そしていざ保存という時点で保存用 BMP を生成し AA をDrawImage したら、「そのパラメータと、FillEllipse で描画したという事実」を覚えていたので、続けて保存用 BMP に覚えていたパラメータで FillEllipse すれば、画面で見えている図と同じ絵の BMP ができるのではないか、というのが私の提案した代替手段です。 ええ、わかっています、描く円は一つだけじゃないし、そもそも描くのは円だけじゃないという事を。 ですから、複数回複数種類の描画を再現するには、 ・何らかの描画を行ったという事を表す抽象クラスを作って、それを各描画方法ごとに派生させたクラスを作る。 ・画像編集開始時に上記抽象クラスの List を生成する。 ・何らかの画像編集を行うごとにそれに対応する派生クラスを生成し、上記 List に add する。 ・画像保存時、保存用 BMP を生成し AA の画像を DrawImage した後で上記 List の順に行った描画を保存用 BMP に再現する。 ということを行えばできるはずです。 「これだけ変えたら現状の描画が変わるじゃないか」とお思いかもしれませんが、大丈夫です。最初のクラス追加は処理の流れには関係しませんし、2・3 番目は現行の処理を行っているメソッドに簡単な処理を追加するだけで、処理にかかる時間も「BB描画時にちらつき等」が出ることはまずないはずです。 確かに、目の前に描画した結果があるのに回りくどいことをしているように思うかもしれません。 しかし、上記の変更を行えば、現状では無理な画像編集の Undo/Redo もできるようになります。

usami33
質問者

お礼

たびたびスミマセン その後、色々確認したところ、元々のGraphicsオブジェクトに描画した時の座標系は PictureBoxのサイズが基準で、 今回の修正で変更した Graphics^ gCorePrint = Graphics::FromImage(AA->Image); ですと、Imageで定義されているピクセルが座標系となっているように見えます

usami33
質問者

補足

回答ありがとうございます。 実は、同時進行で、BMPへの直接描画も試みているのですが、 こちらはこちらで、別の問題が発生してしまい、 よろしければ、こちらの問題もアドバイスいただけますでしょうか。 【事象】 前記の質問の方法で作画した図形と以下の方法で作画した図形のスケールが異なってしまいます。 見た目で明らかに、下記方法の時の図形が、サイズ指定で大きくなるのではなく、 ズームしたように、荒く大きいので、Viewのサイズがおかしい様に見受けられます。 しかし、 AA,BBともに縦横(WidthとHeight)のサイズが同じで、ImageRectangleの縦横のサイズも同じ、 私の見逃しが無ければウォッチで比べたAA,BBの各クラスの値も同じだったんです。 ※当然、アドレス系の値は異なっておりましたけど、直接数値の物とフラグ系は同じ値でした ※編集中は従来の方法で、編集終了時にバックグランドのイメージを入れ込んで、 そこに図形を上書きしております。 BB->Image = AA->Image; Graphics^ g = Graphics::FromImage(BB->Image); g->FillEllipse(gcnew SolidBrush(Color::White), posx, posy, d, d); ちなみに SizeModeはStretchImageにして、pictureboxのサイズも指定できるようにしております

その他の回答 (1)

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.1

自分も軽く MSDN を確認してみたのですがわかりませんでした。 ただ、代替手段として、 > PictureBox BBはAAのオーバーレイとして、文字や図形をGraphicsオブジェクトに描画したり編集したりしています。 のときに、どのような文字や図形をどの位置に描画したかを覚えておいて、 > そこにAAを書き込む > g->DrawImage(AA->Image,・・・ のあとでその g に上記で覚えておいた描画情報にしたがって描画する、というのであなたの希望通りの処理は可能と思います。

usami33
質問者

補足

回答ありがとうございます 私も最初は g->DrawImage(AA->Image,・・・ の後に g->DrawImage(BB->Image,・・・ と記載すれば良いと考えていたのですが。 PictureBox BBのImageプロパティには何も書き込んでいない為、 ※書き込んでいるは、Graphicsオブジェクトに対しての書き込み このため、実行すると 「'System,ArgumentNullException'のハンドルされていない例外がSystem,Drawing.dllで発生しました」 となってしまいます。 AA,BBのプロパティを確認すると AAはImageが構造体となり、Bmpへのアドレスを始め各種情報が定義されていますが BBは<未定義の値>となっております。 そりゃそうですよね、BBは元々オーバーレイとして、常に書き捨て前提で、 Graphicsオブジェクトのエリアにしか描画していないのですから。 つまり BB->Graphicsに対して書き込んだ物を 保存用BMPに対して AA->Image同様に書き込みたいんです。 BB描画時にちらつき等を気にしない仕様なら、BBの描画をImageプロパティに書けばよいのは判っているのですが、 できれば、現状の描画のまま解決策を見出したいと考えております

関連するQ&A

  • 【C#】GraphicsのhDcについて

    C#でアプリケーションを作成しています。 PictureBoxに読み込んだ画像を画像処理ライブラリにGraphicsのhDcを渡し、処理をさせたいのですが、 Bitmap bmp = new Bitmap("ファイル名"); pictureBox1.Image = bmp; Graphics g = Graphics.fromImage(pictureBox1.Image); IntPtr hdc = g.GetHdc(); というふうに作った[hdc]を渡すと真っ黒な画像が表示されてしまいます。 ピクチャーボックス1のPaintイベント pictureBox1_Paint(object sender, PaintEventArgs e) { // pictureBox1.Imageには上と同じ画像を読み込み済み IntPtr hdc = e.Graphics.GetHdc(); } というふうに作った[hdc]を渡すと、正常に処理された画像が表示されます。 質問なのですが、PictureBox1.Imageから作ったGraphicsとPaintEventArgs.Graphicsはどのような差があるのでしょうか? また、PaintEventArgsを使わず同じようなGraphicsを作るにはどうしたらいいでしょうか? 至らない説明で申し訳ありませんが、ご助言をよろしくお願いします。

  • C# PictureBoxへの描画を行うとメッセージボックスが表示されません。

    いつもお世話になっております。 ふと、PictureBoxに描画をしてみようかと思い Paintイベントに以下のようにして描画を行いました。   myBitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);   Graphics g = Graphics.FromImage(myBitmap);   pictureBox1.Image = myBitmap;      ・      ・(g.FillRectangle(・・・);など)      ・ (myBitmapはBitmap型のグローバル変数です。) PictureBoxは、自由にサイズ変更可能なフォームに貼り付け、四方をanchorで固めています。 そのためサイズが変更されるたびに、描画するときBitmapのサイズも変更しないといけないので この処理を毎回通っています。 (その部分が何だか無駄な気がするのですが、他にいい方法が思いつきませんでした。) ところが、描画はうまくいったのですが、メッセージボックスを出すと そのメッセージボックスが一度Altキーを押さないと表示されません。 色々調べて、ダブルバッファリングというものがあると知りました。 そこでPaintイベントで最初にこの処理をし   Image image = new Bitmap(pictureBox1.Width, pictureBox1.Height);   g = Graphics.FromImage(image); gに描画し終わってから   e.Graphics.DrawImage(image, 0, 0); としてみると、今度はフォームを移動するのにも一瞬フリーズするようになってしまいました。 (あまり深くプログラミングをしたことがないので、理解しきれなくてやり方が悪いのかも知れません・・・) メッセージボックスが表示されないのは、PictureBoxの描画のため 他のコントロールの描画ができていなためだと推測しているのですが どう直していいかわかりません。 どなたか、わかる方がいましたらよろしくお願いします。 <補足> OS:Vista VisualStudio2008 .NET Framework3.5

  • C#で画像をクリップボードへのコピーと貼り付けについて

    GraphicsオブジェクトのDrawImageメソッドを使って画像を表示させています。 この画像をクリップボードへコピーしてほかのところに貼り付けしたいのですが、クリップボードへはClipboard.SetDataObject()を使用すればよいと思っています。 しかし、どのように使ったらいいのかよくわかりません。現在のソースは以下のようになっています。 //Bitmapオブジェクトの作成(画像ファイルを読み込む) Bitmap bmap = new Bitmap(@"C:\test2.bmp"); //元の画像からの切り取り範囲の指定 RectangleF rectSrc = new RectangleF                 (pointX,pointY,WidthX,WidthY); //貼り付け先を指定範囲の指定 RectangleF rectDst = new RectangleF(0, 0, DstX,DstY); //PictureBox1のGraphicsオブジェクトの作成 Graphics g= pictureBox1.CreateGraphics(); //画像の描画 g.DrawImage(bmap, rectDst,rectSrc,GraphicsUnit.Pixel); //クリップボードへのコピー Clipboard.SetDataObject(g); よろしくおねがいいたします。

  • VB.netでのPictuerBoxに描写した内容の保存について。

    VB.netでのPictuerBoxに描写した内容の保存について。 PictureBoxに描写した内容を保存してみると、描写した項目事態は正しく保存されているのですが、背景が真っ黒になってしまいますこれは、なぜなのでしょうか? ソースは以下の様な感じです。 Dim bmp As Bitmap Dim g As Graphics bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height) PictureBox1.Image = bmp g = Graphics.FromImage(PictureBox1.Image) g.DrawLine(Pens.AliceBlue, 0, 10, 20, 10) PictureBox1.Refresh() PictureBox1.Image.Save("test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg) どなたかわかる方よろしくお願いいたします。

  • VB.NET ピクチャーボックスのImageの一部をクリップボードにコピー

    Picturebox1.Image = New Bitmap(Picturebox1.Width, Picturebox1.Height) Dim g As Graphics = Graphics.FromImage(Picturebox1.Image) これ以降 g.DrawLine 等で描画を行っています そして、ピクチャーボックスの一部の領域(矩形)を指定して クリップボードにコピーしたいのですがどうしたらいいでしょうか よろしくお願いします 他のピクチャーボックスにその一部をコピーできるだけでもいいのですが

  • Graphics等のイメージの描画

    こんばんわ。 GraphicsクラスのdrawImageメソッドをつかっているですが 描画したあとでイメージだけを消す方法はあるのでしょうか。 APIはみてみましたがGraphicsクラスにはないようでした。 消すとしたら画面全体を消すのしかわからなく、使い勝手が悪いので困ってます。 ちなみにauのオープンアプリを作ろうとしているのでCLDCで使えるのを教えてください。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 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(...); -> ジャギが目立つ。(画像の上の方) ビットマップ(メモリ)にスムーズなテキストを描画することはできないのでしょうか? ちなみにフォントはメイリオです。

  • 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にぴったりと表示させることができるでしょうか?

  • VB.NETのグラフィック描画で困っています

    VB.NETでのグラフィックの記述方法ですが 何かをクリックすると描画させるのではなく 単にあるsubプロシージャ内でグラフィックを描画させる記述する方法として pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) Dim g As Graphics = Graphics.FromImage(PictureBox1.Image) を教えていただきました。そこで private sub xy_keisan() '座標を計算させるプロシージャ disp_x() 'x座標に目盛りを表示させるプロシージャ disp_Y() 'xの目盛り数によってY座標の位置を変えて表示させるプロシージャ end sub private sub disp_x() pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) Dim g As Graphics = Graphics.FromImage(PictureBox1.Image) g.DrawLine(****** end sub private sub disp_y() pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) Dim g As Graphics = Graphics.FromImage(PictureBox1.Image) g.DrawLine(****** end sub のような記述(引数とか細かい所は端折っています)ですとdisp_yは描画されていますが,disp_xは消えてしまいます。 pictureBox1.Image=New Bitmap(PictureBox1.width,pictureBox1.Height) が消えてしまう原因だとおもって宣言場所を変えてみましたが同じです 逆にこれが無いと描画させることが出来なくなります。 これの意味も今ひとつ判りません よろしくお願い致します

  • VB PictureBoxの描画範囲

    VisualStudio2010のVBにて、ピクチャーボックスの範囲をプログラム中で大きくして描画をさせたいのですが、ピクチャーボックスのサイズを大きくしても、大きくした範囲には描画がされません。 やり方は↓の方法です。 まず、formにボタンとピクチャーボックスを300×200で配置して、 http://homepage1.nifty.com/rucio/main/dotnet/Samples/dnSampleKeepImage.htm ↑のページで書かれてた方法でグラフィックを再描画させています。 Public Class Form1 Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim g As Graphics = AutoGraphics(PictureBox1) PictureBox1.Width = 400 g.FillRectangle(Brushes.Black, 100, 100, 10, 10) '1つ目の図形 g.FillRectangle(Brushes.Black, 350, 100, 10, 10) '2つ目の図形 g.Dispose() End Sub Public Function AutoGraphics(ByVal picSource As PictureBox) As Graphics If picSource.Image Is Nothing Then picSource.Image = New Bitmap(PictureBox1.Width, PictureBox1.Height) End If Return Graphics.FromImage(picSource.Image) End Function End Class これを実行すると、1つ目の図形は描画されていますが、拡大した範囲にある2つ目の図形は描画されていません。 ピクチャーボックスの範囲を大きくした所にも描画をさせたいと思っています。 よろしくお願いします。

専門家に質問してみよう