- ベストアンサー
PBoxのGraphicsをImageに書き込む
- PictureBoxを使用して画像に文字や図形を描画する方法を教えてください。
- 保存用のBMPにPictureBox AAとBBを書き込んでJpeg形式で保存したいのですが、BBのImageプロパティが未定義で書き込めません。どのようにすれば実現できますか?
- PCの画面上ではPictureBox AAの上にBBが表示され、背景のAA画像に文字や図形を重ねて描画できています。
- みんなの回答 (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 もできるようになります。
その他の回答 (1)
- hitomura
- ベストアンサー率48% (325/664)
自分も軽く MSDN を確認してみたのですがわかりませんでした。 ただ、代替手段として、 > PictureBox BBはAAのオーバーレイとして、文字や図形をGraphicsオブジェクトに描画したり編集したりしています。 のときに、どのような文字や図形をどの位置に描画したかを覚えておいて、 > そこにAAを書き込む > g->DrawImage(AA->Image,・・・ のあとでその g に上記で覚えておいた描画情報にしたがって描画する、というのであなたの希望通りの処理は可能と思います。
補足
回答ありがとうございます 私も最初は 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プロパティに書けばよいのは判っているのですが、 できれば、現状の描画のまま解決策を見出したいと考えております
お礼
たびたびスミマセン その後、色々確認したところ、元々のGraphicsオブジェクトに描画した時の座標系は PictureBoxのサイズが基準で、 今回の修正で変更した Graphics^ gCorePrint = Graphics::FromImage(AA->Image); ですと、Imageで定義されているピクセルが座標系となっているように見えます
補足
回答ありがとうございます。 実は、同時進行で、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のサイズも指定できるようにしております