DOBON.NET DOBON.NETプログラミング掲示板過去ログ

bmpファイルを保存したい

環境/言語:[vb.net]
分類:[.NET]

はじめまして。
vb.net初心者です。
自分でペイントのソフトを作ってます。
せっかく書いた絵を保存したいのですが、エラーになっちゃいます。
エラーは「オブジェクト参照がオブジェクト インスタンスに設定されていません。」で、
コードは「Picbox.Image.Save("z:\zu.bmp", Imaging.ImageFormat.Bmp)」
です。
あと、消しゴム機能の時にマウスカーソルを変えたいのです。
pictureboxのCursorプロパティをhandにしたいのです。
どうコードで記述sればいいのでしょうか?。

アドバイス、よろしくお願いします
Picbox.Imageが空(Null)である可能性があります。
ピクチャボックスとボタンを貼り付けて以下のコードを実行すると
再現しますね。

'すぐ保存する。
Private Sub Button1_Click(****) Handles Button1.Click
Me.PictureBox1.Image.Save("c:\moo_s041210.bmp", Imaging.ImageFormat.Bmp)
End Sub

イメージをファイルからロードするか、
何らかのイメージを書き込んであげてください。
その後であれば保存が成功するはずです。

たとえば、白くクリアしてあげるとか。
'Dim bmp As Bitmap = New Bitmap(1024, 768) 'サイズいい加減。
'Dim grp As Graphics = Graphics.FromImage(bmp)
'grp.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height)
'Me.PictureBox1.Image = CType(bmp, Image)

どうでしょうか。

■No7983に返信(みーちゃんさんの記事)
> はじめまして。
> vb.net初心者です。
> 自分でペイントのソフトを作ってます。
> せっかく書いた絵を保存したいのですが、エラーになっちゃいます。
> エラーは「オブジェクト参照がオブジェクト インスタンスに設定されていません。」で、
> コードは「Picbox.Image.Save("z:\zu.bmp", Imaging.ImageFormat.Bmp)」
> です。
> あと、消しゴム機能の時にマウスカーソルを変えたいのです。
> pictureboxのCursorプロパティをhandにしたいのです。
> どうコードで記述sればいいのでしょうか?。
>
> アドバイス、よろしくお願いします
■No7983に返信(みーちゃんさんの記事)

DOBON.NET .NET Tips - PictureBoxのImageプロパティに関するよくある勘違い
http://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html

が全くそのままです。

マウスポインタに関してはこちら。

DOBON.NET .NET Tips - フォームのマウスポインタを待機状態にする
http://dobon.net/vb/dotnet/form/cursorcurrent.html
返信ありがとうございます。
SAVEでエラーは出なくなり、うまく保存できましたが、2点うまくいかないことがあります。
(1)ファイルを読みこみ、描画して保存するときはうまくいく。
    新規で作成して保存すると、なぜかbackcolorが黒で保存される
保存する前に強制的にPicbox.BackColor = Color.Whiteとしたがだめだった。
(2)一度保存できるが、もう一度保存しようとするとsaveで
    「GDI+ で一般的なエラーが発生しました。」とエラーになる

常識的なことも勉強不足ですみません。
アドバイスいただけると助かります(^0^)
> (1)ファイルを読みこみ、描画して保存するときはうまくいく。
>     新規で作成して保存すると、なぜかbackcolorが黒で保存される

Bitmapオブジェクトはサイズを与えて初期化するとすべて透過色となります。別の色で塗りつぶしたい時は、四角でも描画してください。背景色が本当に黒ということであれば、不明です。

> (2)一度保存できるが、もう一度保存しようとするとsaveで
>     「GDI+ で一般的なエラーが発生しました。」とエラーになる

通常はそうはならないはずです。詳細を教えてください。
何度も返信ありがとうございます。
backcolorは「うまくいく場合と黒になっちゃうことがあり、特になにをしたときというわけではなく、たまに発生します。
(2)一度保存できるが、もう一度保存しようとするとsaveで
    「GDI+ で一般的なエラーが発生しました。」とエラーになる
(2)は改善されました。
ソースを載せてもわかりずらいかと思いますが、以下のような感じで書いて見ました。

Dim pen As New System.Drawing.Pen(Color.Black, 1)
Dim pen_w As New System.Drawing.Pen(Color.White, 1)
Dim intX As Integer
Dim intY As Integer
Dim BtnDown As Boolean = False
Dim img As Image
Dim gg As Graphics

Private Sub FrmDraw_Load(ByVal sender As System.Object, ByVal e As    System.EventArgs) Handles MyBase.Load
Picbox.Image = New Bitmap(400, 240)
gg = Graphics.FromImage(Picbox.Image)
'gg.DrawLine(pen_w, 0, 0, 400, 240)

End Sub
Private Sub Picbox_MouseDown(ByVal sender As Object, ByVal e As
      system.Windows.Forms.MouseEventArgs) Handles Picbox.MouseDown
intX = e.X
intY = e.Y
BtnDown = True
End Sub
Private Sub Picbox_MouseMove(ByVal sender As Object, ByVal e As
      System.Windows.Forms.MouseEventArgs) Handles Picbox.MouseMove
gg = Graphics.FromImage(Picbox.Image)
If BtnDown = True Then
gg.DrawLine(pen, intX, intY, e.X, e.Y)
intX = e.X
  intY = e.Y
 Picbox.Invalidate()
 End If
End Sub
Private Sub Picbox_MouseUp(ByVal sender As Object, ByVal e As
       System.Windows.Forms.MouseEventArgs) Handles Picbox.MouseUp
BtnDown = False
End Sub
Private Sub ColorChange(ByVal sender As System.Object, ByVal e As
       System.EventArgs) Handles RdoBlack.CheckedChanged, _
                     RdoRed.CheckedChanged, _
                     RdoPink.CheckedChanged, _
                     RdoYell.CheckedChanged, _
                    RdoBlue.CheckedChanged, _
                     RdoGreen.CheckedChanged
    Picbox.Cursor = Cursors.Cross
pen.Color = sender.backcolor
End Sub
Private Sub BtnEnd_Click(ByVal sender As System.Object, ByVal e As
                            System.EventArgs)
Me.Close()
End Sub
Private Sub BtnClear_Click(ByVal sender As System.Object, ByVal e As
                 System.EventArgs) Handles btnClear.Click
Picbox.Image = New Bitmap(400, 240)
gg = Graphics.FromImage(Picbox.Image)
gg.Clear(Color.White)
gg.FillRectangle(Brushes.White, 0, 0, Picbox.Width, Picbox.Height)
End Sub
Private Sub NudWidth_ValueChanged(ByVal sender As System.Object, ByVal e
             As System.EventArgs) Handles NudWidth.ValueChanged
pen.Width = sender.value
End Sub
Private Sub BtnKesigomu_Click(ByVal sender As System.Object, ByVal e As
               System.EventArgs) Handles Button1.Click
Picbox.Cursor = Cursors.Hand
pen.Color = Color.White
End Sub
Private Sub MnuOpen_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MnuOpen.Click
Picbox.Image = New Bitmap(400, 240)
gg = Graphics.FromImage(Picbox.Image)
gg.DrawLine(pen_w, 0, 0, 400, 240)
Dim filename, readdata As String
OpenFileDialog1.ShowDialog()
If OpenFileDialog1.FileName() = "" Then
Exit Sub
Else
filename = OpenFileDialog1.FileName
End If
Picbox.Image = Image.FromFile(filename)
gg = Graphics.FromImage(Picbox.Image)
End Sub
Private Sub MnuWrite_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MnuWrite.Click
gg = Graphics.FromImage(Picbox.Image)
Dim fname As String
SaveFileDialog1.ShowDialog()
If SaveFileDialog1.FileName() = "" Then
MessageBox.Show("ファイル名を入力してください", "エラー",
MessageBoxButtons.OKCancel, MessageBoxIcon.Information)
Else
fname = SaveFileDialog1.FileName
End If
Picbox.Image.Save(fname, Imaging.ImageFormat.Bmp)
gg.Dispose()
Picbox.Invalidate()
End Sub
Private Sub MnuPrint_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MnuPrint.Click
PrintDialog1.Document = PrintDocument1
If PrintDialog1.ShowDialog = DialogResult.OK Then
PrintDocument1.Print()
End If
End Sub
Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal
e As System.Drawing.Printing.PrintPageEventArgs) Handles
PrintDocument1.PrintPage
e.Graphics.DrawImage(Picbox.Image, 10, 10)
End Sub
Private Sub MnuEnd_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MnuEnd.Click
Me.Close()
End Sub
> backcolorは「うまくいく場合と黒になっちゃうことがあり、特になにをしたときというわけではなく、たまに発生します。

それは、Bitmapオブジェクトを新しく作成したときですか、ファイルを読み込んだ時ですか?また、表示しているときから黒いですか?前に回答したように、はじめから背景色で塗りつぶしても黒くなりますか?
ざっと見ただけなので見落としたかもしれないですが、

そのコードでは、
フォームのLoad後、(ファイルを呼ばずに)そのまま描き始めると、
白で塗る処理やクリアする処理を通らないようなので、当然かと。
塗らない限り背景部分は何もないままですから透明です。

PngとBitmap二種類のファイルに保存するようにするとすぐに分かると思います。
WindowsBitmapファイルには背景色という概念がないので、黒くなります。
Pngファイルの方は、放置した背景部分は透明になっているはずです。


フォームのLoadで
「'gg.DrawLine(pen_w, 0, 0, 400, 240)」
がありますが、これのコメントを外した上でFill〜(塗りつぶし)に変えるか、
Clear(白)をするかの処理を通るようにしてテストしてはいかがでしょうか。
レス、遅くなりすみませんでした。
結局、一度背景が黒くなってしまうと、どうにも動かないのですが、誤動作なしに動いていれば同じコードでも黒くなりませんでした。
自動でコードが吐き出されている部分はまだ調べていませんが、ごちゃごちゃ触っているとだめでした。
あきらめて最初から書き直してみたら、以下でうまく通りました。
ありがとうございました。
またいろいろ参考にさせてくださいね。
Private fd As Boolean
Private sx, sy As Integer
Dim pen As New System.Drawing.Pen(Color.Black, 3)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
PictureBox1.Image = New Bitmap(Me.Width, Me.Height)
End Sub

Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
Dim i As Image
OpenFileDialog1.ShowDialog()
i = Image.FromFile(OpenFileDialog1.FileName)
PictureBox1.Image = i
End Sub

Private Sub MenuItem3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem3.Click
SaveFileDialog1.ShowDialog()
PictureBox1.Image.Save(SaveFileDialog1.FileName)
End Sub

Private Sub MenuItem4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem4.Click
PrintDialog1.Document = PrintDocument1
PrintDialog1.ShowDialog()
PrintDocument1.Print()
End Sub

Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem5.Click
Me.Close()
End Sub

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
fd = True
sx = e.X
sy = e.Y
End Sub

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
Dim g As Graphics
If fd = True Then
g = Graphics.FromImage(PictureBox1.Image)
g.DrawLine(pen, sx, sy, e.X, e.Y)
PictureBox1.Refresh()
sx = e.X
sy = e.Y
End If
End Sub

Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
fd = False
End Sub

Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
e.Graphics.DrawImage(PictureBox1.Image, 0, 0)
End Sub

Private Sub NumericUpDown1_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NumericUpDown1.ValueChanged
Pen.Width = sender.value
End Sub

Private Sub colorChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.CheckedChanged, RadioButton2.CheckedChanged
PictureBox1.Cursor = Cursors.Cross
pen.Color = sender.backcolor
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
PictureBox1.Image = New Bitmap(Me.Width, Me.Height)
End Sub
End Class
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板