none
PictureBox Image speichern unter RRS feed

  • Frage

  • Hallo,

    ich habe derzeit eine kleinen Code gefunden und in eins meiner Programme iengebeaut. Hat auch funktioniert.
    Nun wollte ich diesen Codeauschnitt in ein anderes Programm einbauen. Jetzt bringt er mir aber einen fehler.

    System.NullReferenceException wurde nicht behandelt.
      Message="Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."
     

    Hier der Code

    Imports System.Drawing.Imaging
    Public Class Form1
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            SaveFileDialog1.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|PortableNetworkGraphik|*.png"
            SaveFileDialog1.Title = "Speicher eine Image Datei"
            SaveFileDialog1.InitialDirectory = "C:\Pictures\"
            SaveFileDialog1.FilterIndex = 4
            SaveFileDialog1.ShowDialog()
            ' Wenn der FileName "is not" and "empty" string, öffnen für Speichern.
            If SaveFileDialog1.FileName <> "" Then
                Select Case SaveFileDialog1.FilterIndex
                    Case 1
                        PictureBox1.Image.Save(SaveFileDialog1.FileName, ImageFormat.Jpeg)
                    Case 2
                        PictureBox1.Image.Save(SaveFileDialog1.FileName, ImageFormat.Bmp)
                    Case 3
                        PictureBox1.Image.Save(SaveFileDialog1.FileName, ImageFormat.Gif)
                    Case 4
                        PictureBox1.Image.Save(SaveFileDialog1.FileName, ImageFormat.Png)
                End Select
            End If
        End Sub
    End Class
    Wo und wie muss ich den als NEW deklarieren ?

    vielen dank
    Donnerstag, 24. September 2009 08:23

Antworten

  • Hallo Bernd,

    wenn in der PictureBox kein Bild geladen ist, ist Image Nothing
    und so wird der Code wird eine NullReferenceExeception auslösen.
    Solange kein Bild geladen wurde, sollte der Button1 deaktiviert sein,
    via Enabled = false bzw. eingangs geprüft werden:

    If PictureBox1.Image Is Nothing Then Return

    Da sind aber noch einige andere Probleme im gefundenen Codeschnippsel:

    Im übrigen sollte man bei ShowDialog auf DialogResult.OK prüfen
    und nicht auf den Dateinamen testen.

    Als Vorgabe für InitialDirectory wäre sinnvoller:
    Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)

    Das Festlegen des Dateityps über den FilterIndex sollte abgesichert werden,
    denn derzeit dürfte es möglich sein, eine andere Endung als das Format
    anzugeben Bild.JPG aber als Format PNG auszuwählen. Was zumindest
    verwirrend ist.

    Und zudem kann das Speichern fehlschlagen, wenn man das gleiche Image
    speichern will, weil GDI intern auf die Datei zugreift und ein Überschreiben
    dann nicht möglich ist. Ein Try Catch ist auf jeden Fall Pflicht.

    Gruß Elmar
    Donnerstag, 24. September 2009 09:23
    Beantworter
  • Hallo Bernd,

    mit dem Festelegen des Dateityps meinte, ich das der gespeicherte Inhalt zur Endung
    passen sollte. Gerade bei Grafikdateien kommt da schon mal was durcheinander.
    Da die meisten Programme sich nicht nach der Endung, sondern den Inhalten
    richten, ist das zwar nicht dramatisch, aber schon mal etwas unsauber.

    Unten das Ganze mal ein klein wenig aufgemotzt - wobei ich es nicht in allen
    Facetten getestet habe, dazu fehlte die Zeit.

    Gruß Elmar

    Option Strict On
    
    Imports System.IO
    Imports System.Drawing.Imaging
    
    Public Class SavePictureBoxForm
        ' Angelehnt an MSPaint.exe
        Const FileFilter As String = "JPG Dateien (*.jpg, *.jpeg, *.jpe, *.jfif)|*.jpg;*.jpeg;*.jpe;*.jfif|" & _
            "Bitmap Dateien (*.bmp)|*.bmp|" & _
            "Gif Dateien (*.gif)|*.gif|" & _
            "Png Dateien (*.png)|*.png"
        Const GraphicFileFilter As String = "Alle Bilddateien|*.jpg;*.jpeg;*.jpe;*.jfif;*.bmp;*.gif;*.png"
        Const AllFileFilter As String = "Alle Dateien|*.*"
        Const JpegExtensions As String = ".jpg;.jpeg;.jpe;.jfif"
    
        Public Sub New()
            InitializeComponent()
    
            OpenFileDialog1.Title = "Bild öffnen"
    
            OpenFileDialog1.Multiselect = False
            OpenFileDialog1.CheckFileExists = True
            SaveFileDialog1.SupportMultiDottedExtensions = True
            OpenFileDialog1.Filter = FileFilter & "|" & GraphicFileFilter & "|" & AllFileFilter
            OpenFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
            OpenFileDialog1.FilterIndex = 5 ' Hier Alle Bilddateien
    
            SaveFileDialog1.Title = "Bild speichern unter"
            SaveFileDialog1.SupportMultiDottedExtensions = True
            SaveFileDialog1.AddExtension = True
            SaveFileDialog1.Filter = FileFilter
            SaveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
            SaveFileDialog1.FilterIndex = 4 ' Hier PNG
    
            Me.saveAsButton.Enabled = False
            Me.PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
        End Sub
    
        Private Sub openButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles openButton.Click
            OpenFileDialog1.FileName = ""
            If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim filename As String = Me.OpenFileDialog1.FileName
                Try
                    Me.saveAsButton.Enabled = False
                    ' Altes Bild vorher freigeben 
                    If (PictureBox1.Image IsNot Nothing) Then
                        PictureBox1.Image.Dispose()
                        PictureBox1.Image = Nothing
                    End If
    
                    PictureBox1.Image = Image.FromFile(filename)
    
                    ' Neues Vorgabeverzeichnis fürs Öffnen
                    Me.OpenFileDialog1.InitialDirectory = Path.GetDirectoryName(filename)
                    ' Vorgaben fürs Speichern
                    Me.SaveFileDialog1.FileName = Path.GetFileNameWithoutExtension(filename)
                    Me.saveAsButton.Enabled = True
                Catch ex As Exception
                    Dim messageText As String = String.Format( _
                        "Die Datei '{0}' konnte nicht geladen werden:{1}{2}", _
                        filename, Environment.NewLine, ex.Message)
                    MessageBox.Show(Me, messageText, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                End Try
            End If
        End Sub
    
        Private Sub saveAsButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles saveAsButton.Click
            If PictureBox1.Image Is Nothing Then
                Return
            End If
            Me.SaveFileDialog1.FileName = Path.GetFileNameWithoutExtension(Me.SaveFileDialog1.FileName)
            If SaveFileDialog1.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                Dim fileName As String = Me.SaveFileDialog1.FileName
                ' Endung überprüfen
                Dim format As ImageFormat = GetImageFormat(Me.SaveFileDialog1.FilterIndex)
                fileName = ValidateFileName(fileName, format)
    
                Try
                    Me.PictureBox1.Image.Save(fileName, Format)
                Catch ex As Exception
                    Dim messageText As String = String.Format( _
                        "Die Datei '{0}' konnte nicht gespeichert werden:{1}{2}", _
                        fileName, Environment.NewLine, ex.Message)
                    MessageBox.Show(Me, messageText, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
    
                    Me.SaveFileDialog1.FileName = ""
                End Try
            End If
        End Sub
    
        Private Function GetImageFormat(ByVal filterIndex As Integer) As ImageFormat
            Select Case filterIndex
                Case 1
                    Return ImageFormat.Jpeg
                Case 2
                    Return ImageFormat.Bmp
                Case 3
                    Return ImageFormat.Gif
                Case 4
                    Return ImageFormat.Png
                Case Else ' Hier PNG Standard
                    Return ImageFormat.Png
            End Select
        End Function
    
        Private Function ValidateFileName(ByVal fileName As String, ByVal format As ImageFormat) As String
            Dim validExtension As String
            Select Case format.Guid
                Case ImageFormat.Jpeg.Guid
                    validExtension = ".jpg"
                Case ImageFormat.Bmp.Guid
                    validExtension = ".bmp"
                Case ImageFormat.Png.Guid
                    validExtension = ".png"
                Case ImageFormat.Gif.Guid
                    validExtension = ".gif"
                Case Else ' andere Erweiterung
                    Return fileName
            End Select
    
            Dim extension As String = Path.GetExtension(fileName)
            If extension.Equals(validExtension, StringComparison.OrdinalIgnoreCase) Then
                Return fileName
            ElseIf format.Guid = ImageFormat.Jpeg.Guid Then
                For Each jpgExtension As String In JpegExtensions.Split(";"c)
                    If extension.Equals(jpgExtension, StringComparison.OrdinalIgnoreCase) Then
                        Return fileName
                    End If
                Next
            End If
            Return Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) & validExtension)
        End Function
    End Class





    Freitag, 25. September 2009 11:40
    Beantworter
  • Hallo ChaosBernd,

    Der Code läuft einwandfrei bei mir. Er wandelt die Bilder um erfolgreich.

    Das Festlegen des Dateityps über den FilterIndex sollte abgesichert werden,
    denn derzeit dürfte es möglich sein, eine andere Endung als das Format
    anzugeben Bild.JPG aber als Format PNG auszuwählen. Was zumindest
    verwirrend ist.

    Wie ich das verstehe:

    Auf Knopf1 Du wählst dir ein Bild zum Beispiel im .png Format.

    Auf Knopf2 Du speicherst das Bild mit dem Namen Bild.jpg aber Du änderst nicht das Format (es ist noch immer .png).

    Dann entsteht eine Datei Bild.jpg die so angezeigt wird im Ordner aber die innen als .png Format ist.

    Grüße,

    Robert

    Freitag, 25. September 2009 11:52
    Moderator

Alle Antworten

  • Hallo ChaosBernd,

    Ich glaube die Fehlermeldung kommt nicht von diesem Teil des Kodes sondern von einem anderen Teil des Programms.

    Der Code versucht, auf ein Mitglied zuzugreifen, der festgelegt auf null ist.

            Try à Man versucht etwas

            Catch nre As NullReferenceException à Man fangt die Exception ab

                Console.WriteLine(nre.Message)

            End Try

    Ich glaube Du musst uns mehr Code aufdecken. Danke.

    Grüße,

    Robert

    Donnerstag, 24. September 2009 09:19
    Moderator
  • Hallo Bernd,

    wenn in der PictureBox kein Bild geladen ist, ist Image Nothing
    und so wird der Code wird eine NullReferenceExeception auslösen.
    Solange kein Bild geladen wurde, sollte der Button1 deaktiviert sein,
    via Enabled = false bzw. eingangs geprüft werden:

    If PictureBox1.Image Is Nothing Then Return

    Da sind aber noch einige andere Probleme im gefundenen Codeschnippsel:

    Im übrigen sollte man bei ShowDialog auf DialogResult.OK prüfen
    und nicht auf den Dateinamen testen.

    Als Vorgabe für InitialDirectory wäre sinnvoller:
    Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)

    Das Festlegen des Dateityps über den FilterIndex sollte abgesichert werden,
    denn derzeit dürfte es möglich sein, eine andere Endung als das Format
    anzugeben Bild.JPG aber als Format PNG auszuwählen. Was zumindest
    verwirrend ist.

    Und zudem kann das Speichern fehlschlagen, wenn man das gleiche Image
    speichern will, weil GDI intern auf die Datei zugreift und ein Überschreiben
    dann nicht möglich ist. Ein Try Catch ist auf jeden Fall Pflicht.

    Gruß Elmar
    Donnerstag, 24. September 2009 09:23
    Beantworter
  • Hallo Robert,

    mehr Code gibt es nicht. Jedoch habe ich das Image in den Eigenschaften der PictureBox festgelegt. Vieleicht liegt es daran. ?
    In dem anderen Projekt hatte ich das Image über einen ScreenShot gemacht und dann gespeichert.
    Ich glaube ich weis wo ich suvhen muss.


    Danke

    Bernd
    Donnerstag, 24. September 2009 09:42
  • Hallo Elma,


    danke für die schnelle Antwort,

    ich werde mich sofort ran machen und ändern und probieren.
    wenn ich die lösung habe setzte ich sie hier rein

    lieben dnak
    bernd
    Donnerstag, 24. September 2009 09:43
  • Hallo Elmar und Robert,

    könnte ich das jetzt so lassen ?
    Wobei ich noch eins nicht ganz verstanden habe.

    ""
    Das Festlegen des Dateityps über den FilterIndex sollte abgesichert werden,
    denn derzeit dürfte es möglich sein, eine andere Endung als das Format
    anzugeben Bild.JPG aber als Format PNG auszuwählen. Was zumindest
    verwirrend ist.
    ""

    Ich will ja die Bilder wandeln. Ist das den falsch. gibt es da eine andee methode ?

    Imports System.Drawing.Imaging
    Public Class Form1
        Dim Bild As Image
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim dateiÖffnenDialog As New OpenFileDialog
            With dateiÖffnenDialog
                .CheckFileExists = True
                .CheckPathExists = True
                '.InitialDirectory = "C:\Pictures"
                .InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
                .Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|PortableNetworkGraphik|*.png"
                .FilterIndex = 4
                Dim dialogErgebnis As DialogResult = .ShowDialog
                If dialogErgebnis = Windows.Forms.DialogResult.Cancel Then
                    Exit Sub
                Else
                    Bild = Image.FromFile(.FileName)
                End If
            End With
            PictureBox1.BackgroundImageLayout = ImageLayout.Zoom
            PictureBox1.Image = Bild
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim dateiSpeichernDialog As New SaveFileDialog
            With dateiSpeichernDialog
                .Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif|PortableNetworkGraphik|*.png"
                .Title = "Speicher eine Image Datei"
                .InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
                .FilterIndex = 4
                Dim dialogErgebnis As DialogResult = .ShowDialog
                If dialogErgebnis = Windows.Forms.DialogResult.Cancel Then
                    Exit Sub
                Else
                    Try
                        Select Case dateiSpeichernDialog.FilterIndex
                            Case 1
                                Bild.Save(dateiSpeichernDialog.FileName, ImageFormat.Jpeg)
                            Case 2
                                Bild.Save(dateiSpeichernDialog.FileName, ImageFormat.Bmp)
                            Case 3
                                Bild.Save(dateiSpeichernDialog.FileName, ImageFormat.Gif)
                            Case 4
                                Bild.Save(dateiSpeichernDialog.FileName, ImageFormat.Png)
                        End Select
                    Catch
                    End Try
                End If
            End With
        End Sub
    End Class
    nochmals danke
    Donnerstag, 24. September 2009 16:01
  • Hallo Bernd,

    mit dem Festelegen des Dateityps meinte, ich das der gespeicherte Inhalt zur Endung
    passen sollte. Gerade bei Grafikdateien kommt da schon mal was durcheinander.
    Da die meisten Programme sich nicht nach der Endung, sondern den Inhalten
    richten, ist das zwar nicht dramatisch, aber schon mal etwas unsauber.

    Unten das Ganze mal ein klein wenig aufgemotzt - wobei ich es nicht in allen
    Facetten getestet habe, dazu fehlte die Zeit.

    Gruß Elmar

    Option Strict On
    
    Imports System.IO
    Imports System.Drawing.Imaging
    
    Public Class SavePictureBoxForm
        ' Angelehnt an MSPaint.exe
        Const FileFilter As String = "JPG Dateien (*.jpg, *.jpeg, *.jpe, *.jfif)|*.jpg;*.jpeg;*.jpe;*.jfif|" & _
            "Bitmap Dateien (*.bmp)|*.bmp|" & _
            "Gif Dateien (*.gif)|*.gif|" & _
            "Png Dateien (*.png)|*.png"
        Const GraphicFileFilter As String = "Alle Bilddateien|*.jpg;*.jpeg;*.jpe;*.jfif;*.bmp;*.gif;*.png"
        Const AllFileFilter As String = "Alle Dateien|*.*"
        Const JpegExtensions As String = ".jpg;.jpeg;.jpe;.jfif"
    
        Public Sub New()
            InitializeComponent()
    
            OpenFileDialog1.Title = "Bild öffnen"
    
            OpenFileDialog1.Multiselect = False
            OpenFileDialog1.CheckFileExists = True
            SaveFileDialog1.SupportMultiDottedExtensions = True
            OpenFileDialog1.Filter = FileFilter & "|" & GraphicFileFilter & "|" & AllFileFilter
            OpenFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
            OpenFileDialog1.FilterIndex = 5 ' Hier Alle Bilddateien
    
            SaveFileDialog1.Title = "Bild speichern unter"
            SaveFileDialog1.SupportMultiDottedExtensions = True
            SaveFileDialog1.AddExtension = True
            SaveFileDialog1.Filter = FileFilter
            SaveFileDialog1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
            SaveFileDialog1.FilterIndex = 4 ' Hier PNG
    
            Me.saveAsButton.Enabled = False
            Me.PictureBox1.SizeMode = PictureBoxSizeMode.Zoom
        End Sub
    
        Private Sub openButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles openButton.Click
            OpenFileDialog1.FileName = ""
            If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim filename As String = Me.OpenFileDialog1.FileName
                Try
                    Me.saveAsButton.Enabled = False
                    ' Altes Bild vorher freigeben 
                    If (PictureBox1.Image IsNot Nothing) Then
                        PictureBox1.Image.Dispose()
                        PictureBox1.Image = Nothing
                    End If
    
                    PictureBox1.Image = Image.FromFile(filename)
    
                    ' Neues Vorgabeverzeichnis fürs Öffnen
                    Me.OpenFileDialog1.InitialDirectory = Path.GetDirectoryName(filename)
                    ' Vorgaben fürs Speichern
                    Me.SaveFileDialog1.FileName = Path.GetFileNameWithoutExtension(filename)
                    Me.saveAsButton.Enabled = True
                Catch ex As Exception
                    Dim messageText As String = String.Format( _
                        "Die Datei '{0}' konnte nicht geladen werden:{1}{2}", _
                        filename, Environment.NewLine, ex.Message)
                    MessageBox.Show(Me, messageText, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                End Try
            End If
        End Sub
    
        Private Sub saveAsButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles saveAsButton.Click
            If PictureBox1.Image Is Nothing Then
                Return
            End If
            Me.SaveFileDialog1.FileName = Path.GetFileNameWithoutExtension(Me.SaveFileDialog1.FileName)
            If SaveFileDialog1.ShowDialog(Me) = Windows.Forms.DialogResult.OK Then
                Dim fileName As String = Me.SaveFileDialog1.FileName
                ' Endung überprüfen
                Dim format As ImageFormat = GetImageFormat(Me.SaveFileDialog1.FilterIndex)
                fileName = ValidateFileName(fileName, format)
    
                Try
                    Me.PictureBox1.Image.Save(fileName, Format)
                Catch ex As Exception
                    Dim messageText As String = String.Format( _
                        "Die Datei '{0}' konnte nicht gespeichert werden:{1}{2}", _
                        fileName, Environment.NewLine, ex.Message)
                    MessageBox.Show(Me, messageText, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
    
                    Me.SaveFileDialog1.FileName = ""
                End Try
            End If
        End Sub
    
        Private Function GetImageFormat(ByVal filterIndex As Integer) As ImageFormat
            Select Case filterIndex
                Case 1
                    Return ImageFormat.Jpeg
                Case 2
                    Return ImageFormat.Bmp
                Case 3
                    Return ImageFormat.Gif
                Case 4
                    Return ImageFormat.Png
                Case Else ' Hier PNG Standard
                    Return ImageFormat.Png
            End Select
        End Function
    
        Private Function ValidateFileName(ByVal fileName As String, ByVal format As ImageFormat) As String
            Dim validExtension As String
            Select Case format.Guid
                Case ImageFormat.Jpeg.Guid
                    validExtension = ".jpg"
                Case ImageFormat.Bmp.Guid
                    validExtension = ".bmp"
                Case ImageFormat.Png.Guid
                    validExtension = ".png"
                Case ImageFormat.Gif.Guid
                    validExtension = ".gif"
                Case Else ' andere Erweiterung
                    Return fileName
            End Select
    
            Dim extension As String = Path.GetExtension(fileName)
            If extension.Equals(validExtension, StringComparison.OrdinalIgnoreCase) Then
                Return fileName
            ElseIf format.Guid = ImageFormat.Jpeg.Guid Then
                For Each jpgExtension As String In JpegExtensions.Split(";"c)
                    If extension.Equals(jpgExtension, StringComparison.OrdinalIgnoreCase) Then
                        Return fileName
                    End If
                Next
            End If
            Return Path.Combine(Path.GetDirectoryName(fileName), Path.GetFileNameWithoutExtension(fileName) & validExtension)
        End Function
    End Class





    Freitag, 25. September 2009 11:40
    Beantworter
  • Hallo ChaosBernd,

    Der Code läuft einwandfrei bei mir. Er wandelt die Bilder um erfolgreich.

    Das Festlegen des Dateityps über den FilterIndex sollte abgesichert werden,
    denn derzeit dürfte es möglich sein, eine andere Endung als das Format
    anzugeben Bild.JPG aber als Format PNG auszuwählen. Was zumindest
    verwirrend ist.

    Wie ich das verstehe:

    Auf Knopf1 Du wählst dir ein Bild zum Beispiel im .png Format.

    Auf Knopf2 Du speicherst das Bild mit dem Namen Bild.jpg aber Du änderst nicht das Format (es ist noch immer .png).

    Dann entsteht eine Datei Bild.jpg die so angezeigt wird im Ordner aber die innen als .png Format ist.

    Grüße,

    Robert

    Freitag, 25. September 2009 11:52
    Moderator
  • Hallo Ihr zwei,

    vielen lieben dank.

    Das sind halt alles sachen mit denen ich mich noch intensiver beschäftigen möchte und werde.
    Dank eurer Hilfe klappt das ja auch super.


    wie immer

    vielen dank
    benrd
    Freitag, 25. September 2009 11:57