Announcement

Collapse
No announcement yet.

Bildausschnitt aus Picturebox wählen - Arbeitsspeicher

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bildausschnitt aus Picturebox wählen - Arbeitsspeicher

    Hallo zusammen,
    ich weiss das Programm braucht zu viel Arbeitsspeicher. Doch eine Exception deswegen gab es nie wenn man nicht übermässig gross vergrössern will etc.
    Jedenfalls möchte ich eine Funktion einbauen mit der aus der PictureBox ein Ausschnitt gewählt werden kann. Vielleicht habe ich etwas ganz falsch implementiert:
    Code:
     public Bitmap CropImage(Bitmap imgFromPictureBox, Rectangle rect)
            {
                Bitmap bild=imgFromPictureBox.Clone(rect, imgFromPictureBox.PixelFormat);
               
                return bild;
    
            }
    und der Aufruf:
    Code:
    private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    selectstartpoint = new Point(e.X, e.Y);
                    
                    
    
                }
            }
    
            private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    selectendpoint = new Point(e.X, e.Y);
                    Rectangle selectedrect = new Rectangle(selectstartpoint.X, selectstartpoint.Y, selectendpoint.X, selectendpoint.Y);
                    
                    pictureBox1.Image = (Image)b.CropImage((Bitmap)pictureBox1.Image, selectedrect);
                    
                }
    Was ist hier falsch?

    Vielen Dank

  • #2
    Hallo,

    im Code ist nur eine Kleinigkeit nicht korrekt, nämlich dass nach dem "Croppen" das Originalbild nicht freigegeben wird. Dies ist aber ein kleiner Fehler und sollte nicht zu diesem Verhalten (RAM-Killer) führen.

    Das Problem liegt wahrscheinlich darin dass die PictureBox auf SizeMode=Zoom gesetzt wird. Und genau hier liegt das Problem. Diese Eigenschaft ist nur dazu gedacht ein Bild einmalig auf die Größe anzupassen, sonst tritt obiger Fehler auf.

    Unter http://www.codeproject.com/KB/graphi...ingImages.aspx gibts einen Artikel der zeigt wie es geht.

    mfG Gü
    Zuletzt editiert von gfoidl; 10.11.2008, 23:58. Reason: Link aktualisiert
    "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

    Comment


    • #3
      Vielen Dank!
      Ich habe es genau nach dem Artikel gemacht; nur das Problem ist nicht verschwunden. Es lässt sich nicht der kleinste Ausschnitt ohne OutOfMemoryException auswählen... Schuldig wird die bmp.clone(rect.....) - Methode markiert (nicht die Zuweisung an die PictureBox).
      Die Bilder lassen sich ja auch um ein vielfaches vergrössern ohne Problem, dass nun das zuwenig Speicher hat, kann ja kaum sein.

      Comment


      • #4
        Hi,

        ist der SizeMode der PicturBox auf Normal gestellt? Sonst gehts mit Sicherheit nicht.

        Am Code kann es auch nicht liegen denn alle verwendeten Resourcen werden freigegeben. Hab ich mehrmals getestet und auf einem Rechner mit 2GB RAM kann ich das Bild solange Croppen bis mir fad wird

        Es sei denn du ursprüngliche Bild sprengt schon fast den RAM.

        mfG Gü
        "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

        Comment


        • #5
          Nebenher glaube ich das die Definition von selectedrect Rectangle falsch ist.
          Die Parameter 3 und 4 des Constructors bestimmen nicht eine Ecke des Rectangles sondern Höhe und Breite.

          Aus

          Code:
          Rectangle selectedrect = new Rectangle(selectstartpoint.X, selectstartpoint.Y, selectendpoint.X, selectendpoint.Y);
          wird also

          Code:
          Rectangle selectedrect = new Rectangle(selectstartpoint.X, selectstartpoint.Y, Math.Abs(selectendpoint.X - selectstartpoint.X), Math.Abs(selectendpoint.Y - selectstartpoint.Y));

          Comment


          • #6
            Ja ich habe folgenden Code:
            Code:
             private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
                    {
                        if (e.Button == MouseButtons.Left && _selecting && _selection.Size != new Size())
                        {
                            pictureBox1.SizeMode = PictureBoxSizeMode.CenterImage;
                            Image img = crop(pictureBox1.Image, _selection);
                            pictureBox1.Image = Fit2PictureBox(img, pictureBox1);
                            _selecting = false;
                            
                            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
                        }
                        else { _selecting = false; }
                    }
            Der Fehler erschien genau so wenn ich pictureBox1.SizeMode auskommentierte. Kann also nicht daran liegen.

            Die aufgerufenen Methoden:
            Code:
            public static Image crop(Image ImageFromPictureBox, Rectangle selection)
                    {
            
                        Bitmap bmp = ImageFromPictureBox as Bitmap;
                        
                        Bitmap cropBmp = bmp.Clone(selection, bmp.PixelFormat);
                        ImageFromPictureBox.Dispose();
                        return cropBmp;
                    }
            
                    public static Image Fit2PictureBox(Image image, PictureBox picBox)
                    {
                        Bitmap bmp = null;
                        Graphics g;
                        double scaleY = (double)image.Width / picBox.Width;
                        double scaleX = (double)image.Height / picBox.Height;
                        double scale = scaleY < scaleX ? scaleX : scaleY;
                        bmp = new Bitmap((int)((double)image.Width / scale), (int)((double)image.Height / scale));
                        bmp.SetResolution(image.HorizontalResolution, image.VerticalResolution);
                        g = Graphics.FromImage(bmp);
                        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        g.DrawImage(image, new Rectangle(0, 0, bmp.Width, bmp.Height), new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);
                        g.Dispose();
                        image.Dispose();
                        return bmp;
                    }
            Das mit dem Rect selectedrect kann keine Rolle mehr spielen, da ich nun einen ganz anderen Code habe. Aber danke

            Comment


            • #7
              Der Fehler erschien genau so wenn ich pictureBox1.SizeMode auskommentierte. Kann also nicht daran liegen.
              Hsst du den SizeMode auch im Designer bei der PictureBox geändert? Oder nur im Code auskommentiert?

              Comment


              • #8
                im Code auf normal umgestellt; im Designer habe ich Zoom gelassen; möchte ja dass die Bilder auch richtig dargestellt werden wenn sie nicht zugeschnitten werden. Oder geht das nicht; muss ich sie von da an bei jedem Anzeigen, öffnen durch diese fit2PictureBox - Funktion lassen?

                Comment


                • #9
                  ist der SizeMode der PicturBox auf Normal gestellt? Sonst gehts mit Sicherheit nicht.
                  im Designer habe ich Zoom gelassen
                  Daran liegt das Problem -> auch auf Normal stellen.

                  Im Code wird das Bild unter Beibehaltung des Seitenverhältnisses an die Größe der PictureBox angepasst - Zoom macht auch nichts anderes, außer dass es RAM frisst.

                  mfG Gü
                  "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                  Comment


                  • #10
                    Genau, das Ausschnitt wählen funktioniert problemlos wenn ich den SizeMode fix auf Normal stelle anstelle CenterImage (habe nicht Zoom sondern CenterImage drin). Das Prolem nun: Das Programm hat einen TrackBar als Zoom und das funktioniert nicht mehr, durch die fit2PictureBox-Methode Ohne sie wird das Bild in der linken oberen Ecke abgeschnitten dargestellt. Und damit wird das Bild beim Ziehen des TrackBars ganz leicht in der Breite verzerrt, mehr nicht. Der Code sieht so aus:
                    Code:
                    private void trackBar1_MouseUp(object sender, MouseEventArgs e)
                            {
                                try
                                {
                                    
                                    pictureBox1.Image = b.GetBitmapZoom(trackBar1.Value);
                                }
                                catch (Exception ex)
                                {
                                    MessageBox.Show(("Ein Fehler ist aufgetreten: " + ex.Message.ToString()), "Fehler!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    
                                }
                    
                            }
                    und die Klasse mit den Funktionen:
                    Code:
                    using System;
                    using System.Collections.Generic;
                    using System.ComponentModel;
                    using System.Data;
                    using System.Drawing;
                    using System.Text;
                    using System.Windows.Forms;
                    
                    namespace Bildbearbeitungsprogramm
                    {///<summary>
                     ///Dieses Interface definiert die grundlegensten Methoden der Version 1.6 (Okt. 2008)
                     ///</summary>
                        public interface IBildbearbeitung
                        {
                            Bitmap GetBitmap();
                            void addFile(string Filename);
                            Bitmap GetBitmapZoom(int percent);
                            Bitmap Bildverkleinern(int height, int width);
                            Size Bildgroesse();
                            Bitmap Bilddrehen();
                            
                    
                    
                        }
                        ///<summary>
                        ///In dieser Klasse wird die gesamte Funktionalität des Programmes bereitgestellt
                        ///   </summary>
                        public class Bildbearbeitung : IBildbearbeitung
                        {
                            Bitmap bild; //enthält das Bild; dieses wird bearbeitet, keine Kopie des Originales behalten.
                            public Bildbearbeitung(string Filename)
                            {
                                string Dateiname = Filename;
                                bild = new Bitmap(Dateiname, true);
                    
                    
                            }
                            public Bildbearbeitung(Bitmap BildBitmap)
                            {
                                bild = BildBitmap;
                            }
                            public Bildbearbeitung() { }
                            ///<summary>
                            ///Datei hinzufügen (öffnen)
                            ///</summary>
                            public void addFile(string Filename)
                            {
                                string Dateiname = Filename;
                                bild = new Bitmap(Dateiname, true);
                            }
                            /// <summary>
                            /// Das Bild wird als Bitmap zurückgeliefert (wenn bearbeitet dann die bearbeitete Version)
                            /// </summary>
                            /// <returns>Bitmap-Objekt (ggf. gedreht, ggf. bearbeitet)</returns>
                            public Bitmap GetBitmap()
                            {
                                return bild;
                            }
                            /// <summary>
                            /// Liefert das Bitmap verkleinert/vergrössert zurück; falls es gedreht wurde dann in der Bearbeiteten Version; int-Wert=Faktor. Die Originalversion bleibt bestehen! Für Zoom-Ansicht
                            /// </summary>
                            /// <param name="percent"></param>
                            /// <returns>verkleinertes/vergrössertes Bitmap-Obj</returns>
                            public Bitmap GetBitmapZoom(int percent)
                            {
                                int pSize = percent;
                                /*Bitmap bild2 = (Bitmap)bild.GetThumbnailImage((bild.Width * 100) / percent, (bild.Height * 100) / percent, null, IntPtr.Zero);
                                return bild2;
                                  */
                                Bitmap pImage = bild;
                                int x, y;
                    
                                if (pImage.Width > pImage.Height)
                                {
                                    x = pSize;
                                    y = Convert.ToInt32(((float)pImage.Height / (float)pImage.Width * pSize));
                                }
                                else
                                {
                                    y = pSize;
                                    x = Convert.ToInt32(((float)pImage.Width / (float)pImage.Height * pSize));
                                }
                                Image ret = new Bitmap(x, y);
                                Graphics g = Graphics.FromImage(ret);
                                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                                g.DrawImage(pImage, 0, 0, x, y);
                                g.Dispose();
                                
                                return ret as Bitmap;
                            }
                            /// <summary>
                            /// Verkleinert/vergrössert das Bild nach Höhe/Breite DEFINITIV (keine Kopie wird behalten)
                            /// </summary>
                            /// <param name="height"></param>
                            /// <param name="width"></param>
                            /// <returns>Bearbeitetes Bitmap-Obj</returns>
                            public Bitmap Bildverkleinern(int height, int width)
                            {
                                int x, y;
                                
                                
                                    x = width;
                                    y = height;
                                
                                
                                Image ret = new Bitmap(x, y);
                                Graphics g = Graphics.FromImage(ret);
                                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                                g.DrawImage(bild, 0, 0, x, y);
                                
                                g.Dispose();
                                bild = ret as Bitmap;
                                return bild;
                            }  
                                
                    
                    
                    
                            
                            /// <summary>
                            /// Dreht das Bild (Original) um 90 Grad und liefert es zurück
                            /// </summary>
                            /// <returns>Gedrehtes Bitmap-Obj</returns>
                            public Bitmap Bilddrehen()
                            {
                    
                    
                                bild.RotateFlip(RotateFlipType.Rotate90FlipNone);
                                return bild;
                            }
                    
                            /// <summary>
                            /// Liefert Bildgrösse zurück
                            /// </summary>
                            /// <returns>Size-Objekt</returns>
                            public Size Bildgroesse()
                            {   
                                return bild.Size;
                            }
                           
                        }
                    
                        
                    }

                    Comment


                    • #11
                      Fürs zoomen kann in der Fit2Bitmap-Methode der Wert für Scale als Argument übergeben werden -> d.h. ändere diese Methode

                      Oder hab ich falsch verstanden?

                      mfG Gü
                      "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                      Comment


                      • #12
                        Code:
                        public static Image Fit2PictureBox(Image image, PictureBox picBox)
                        da ist kein Argument für scale...

                        Was ich bräuchte wäre eigentlich die Methode für CenterImage, durch die ich das Bild vor Anzeige durchlaufen lassen kann.

                        Comment


                        • #13
                          da ist kein Argument für scale...
                          -> d.h. ändere diese Methode
                          Um das Bild zu zentrieren brauchst du nur die Position (Location) zu berechnen und zu setzten.

                          mfG Gü
                          "Any fool can write code that a computer can understand. Good programmers write code that humans can understand". - Martin Fowler

                          Comment


                          • #14
                            Hab es hinbekommen.
                            Was fehlt noch bei einem Bildbearbeitungsprogramm? Ausser Möglichkeiten zum heller/dunkler machen, ev. auch Teilbereiche wäre natürlich sinnvoll wenn man die PictureBox scrollen könnte.
                            Ausserdem wäre eine Funktion zum scannen nicht schlecht!
                            Es handelt sich um das Programm http://www.freeware.de/download/net-...amm_36713.html welches ich laufend erweitere; wenn jemand eine Idee bekommen möchte.
                            Zuletzt editiert von C.M.Obrecht; 12.11.2008, 01:39. Reason: Link korrekt dargestellt

                            Comment

                            Working...
                            X