Laden...

Bitmap laden und unter gleichem pfad speichern?

Erstellt von demondriver235 vor 17 Jahren Letzter Beitrag vor 17 Jahren 7.107 Views
D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren
Bitmap laden und unter gleichem pfad speichern?

hallo ich habe gesehen das dieses thema schon einige male diskutiert wurde

aber habe in keinem der theads eine wirkliche lösung gefunden.

und die msdn sagt ja auch

"Es ist nicht zulässig, das Bild in derselben Datei zu speichern, aus der es erstellt wurde. Dadurch wird eine Ausnahme ausgelöst."

gibt es wirlich keine möglichkeit eine bmp zu überschreiben?
oder ein workaround?

habe schon alles probiert was in den vorherigen theads vorgeschlagen wurde: von bmp.dispose() oder bmp=null oder gc.Collect()
oder streams oder file.delete();

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo demondriver235,

was auf jeden Fall gehen sollte ist, das Bitmap-Objekt zu klonen, des Original zu entsorgen (Dispose) und dann den Klone zu speichern.

herbivore

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

ich habe clone zwar noch nicht probiert aber dispose killt das object nich wirklich
das auf das file auch nach dispose, = null und gc.collect noch ein process zugreift??

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo demondriver235,

Dispose des Bitmap-Objekts sollte die zugehörige Datei schließen.

herbivore

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

davon bin ich eigendlich aus ausgegangen

ich habe deshalb um zu prüfen ob die datei freigegeben ist nach dispose

file.delete(file) probiert dann krieg ich einen IO error da die datei von einem anderen prozess verwendet wird??-

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo demondriver235,

zeig mal den Code, mit dem du das BitmapObjekt erzeugst.

herbivore

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren


     public static string[] CollectImgFilesInFolder(string folder)
        {
            //Fill array with files
            string[] imgFileArray = Directory.GetFiles(folder, "*.bmp");

            //Check out how to resize
            foreach (string file in imgFileArray)
            {
                
                //Load the bmp
                Bitmap bmp = new Bitmap(file);

                //get the original size
                int originalHeight = bmp.Height;
                int originalWidth = bmp.Width;

                //
                //if the height is bigger then the width
                //
                if (originalHeight > originalWidth)
                {
                    //calculate new width
                    int newWidth = originalWidth / (originalHeight / 150);

                    //Create new size
                    Size newSize = new Size(newWidth, 150);

                    //Set new size on new bitmap
                    Bitmap newBmp = new Bitmap(bmp, newSize);

                    bmp.Dispose();

                    //Del the old one 
                    File.Delete(file);
                    
                    //save bmp
                    newBmp.Save(file);
                }
//....


"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo demondriver235,

und das geht nicht? Bist du sicher die Datei nicht anderweitig geöffnet zu haben?

Bau mal bitte testweise ein Thread.Sleep zwischen Dispose und Delete ein.

herbivore

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

ich hab thread.sleep(0) gemacht, das sollte reichen oder?

dabei fliegt er auch wieder auf die fresse, gleicher fehler ...used by another process

das bild liegt zwar auf einem button der in einem panel liegt aber selbst da mach ich vorher ein panel.controls.clear bevor der code von ober ausgeführt wird und sonst mach e ich nichts mit der datei

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo demondriver235,

liegt auf dem Panel dasselbe Bitmap-Objekt? Oder eins, dass unabhängig mit new Bitmap(file) erzeugt wurde? Wenn ja, reicht Clear da nicht, sondern es muss auch ein Dispose her.

herbivore

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

leider nicht die bmp's liegen wirklich nur auf den buttons hab trotzem panel.dispose mal eingebaut gleiches problem !?

übrigens: wenn ich das file.delete(file) weglasse
bekomme ich A generic error occurred in GDI+. was eigendlich wohl auch ein IO error
sein dürfte oder?

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo demondriver235,

ich meinte Bitmap.Dispose.

Ich denke, dein Code oben müsste für sich alleine funktionieren.

herbivore

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

meinst du button.image.dispose()?

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Das Problem ist mir auch etwas rätselhaft.
Jedoch habe ich bim Durchsehen deines Codes folgendes gefunden:


//calculate new width
int newWidth = originalWidth / (originalHeight / 150);

Diese doppelte Division ist ... zumindest ungünstig.

Besser ist folgendes:


//calculate new width
int newWidth = (originalWidth * 150 ) / originalHeight;

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

@ borg da hast du zwar recht aber das ganze funktioniert ja bei ich einen anderen pfad zum speichern angebe als den von dem ich geladen habe

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

???
Deine Antwort ist mir jetzt ehrlich gesagt etwas rätselhaft.
Was hat denn der Pfad mit der Berechnung zu tun?

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

nichts, deshalb sag ich ja das du im bezug auf die berechnung recht hast aber das mein problem nicht löst

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ok, dann habe ich das nur falsch verstanden.

Dein Code an sich funktioniert auf jeden Fall. Hat bei mir ganz brav ein Verzeichnis mit Bildern konvertiert.

Daher kann es nur an dem Button liegen. Eventuell reicht schon ein Button.Dispose?

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

bei dir läuft das ? oh man ich weiss echt nicht mehr was ich machen soll

ich hab die buttons zur laufzeit erstellt



  //Create a button object for each labFile
            for (int i = 0; i < labFileArray.Length; i++)
            {
                Button btn = new Button();
                //Set the properties
                btn.Location = new System.Drawing.Point(200, 40 + i * 200);
                btn.Name = "button" + i.ToString(); ;
                btn.Size = new System.Drawing.Size(150, 150);
                btn.Text = labFileArray[i].ToString();
                btn.UseVisualStyleBackColor = true;
                btn.BackColor = Color.White;
                //Add an Eventhandler 
                btn.Click += new System.EventHandler(btn_Click);

                //If an img file for the label exists put it on the button
                for (int j = 0; j < imgFileArray.Length; j++)
                {
                    //a little string formating for filename comparison
                    string labelFileName =                 labFileArray[i].ToString().ToUpper().Replace(".LAB", "");
                    string imageFileName = imgFileArray[j].ToString().ToUpper().Replace(".BMP", "");

                        //Set the image if found
                        if (labelFileName == imageFileName)
                        {
                            btn.Image = System.Drawing.Image.FromFile(imageFileName + ".BMP");
                        }
                }
                //Finally add each button to the flowLayoutPanel
                this.flowLayoutPanelLabels.Controls.Add(btn);


deswegen kann ich nur die controls im panel disposen

siehe:



 int buttonCount = this.flowLayoutPanelLabels.Controls.Count;
            for (int i = 0; i < buttonCount; i++)
            {
                this.flowLayoutPanelLabels.Controls[i].Dispose();   
            }


aber das müsste doch ausreichen?

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Eigentlich sollte das schon reichen. Auch wenn du die for-Schleife durch eine foreach-Schleife ersetzen kannst.

Wann wird denn die "Dispose-Schleife" aufgerufen?
Ist sichergestellt, dass sie vor dem Konvertieren aufgerufen wird?

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

das ist sichergestellt

aber die schleife muss so heissen (im post hatte ich das buttonCount-- vergessen)



  int buttonCount = this.flowLayoutPanelLabels.Controls.Count;
            for (int i = 0; i <= buttonCount; i++)
            {
                this.flowLayoutPanelLabels.Controls[i].Dispose();
                buttonCount--;
            }


ich hab wirklich keine ahnung warum das nicht funzt!!!

aber schon mal vielen dank, das ihr euch damit auseinandersetzt!!

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Stimmt, mein Fehler.
Schon mal mit einem simplen
this.flowLayoutPanelLabels.Controls.Dispose() probiert?

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

jo! ...ich glaub ich hab mittlerweile schon alles disposed!

auch glaub ich mach mal feierabend, mir n bier auf und probier morgen weiter

euch ein schönes wochenende! falls ich die lösung finde poste ich die

falls ihr noch ne idee habt, bin für alles dankbar

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Hast du die Schleife mal debuggt?
Ich glaube nämlich nicht, dass durch Controls[n].Dispose() auch das Control aus der Collection gelöscht wird.
Da du aber ButtonCount dekrementierst, würdest du in diesem Fall nicht alle Controls erreichen.
Ansonsten alles ohne ButtonCount und am Ende einfach Controls.Clear()

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

das steht bei mir im code unter der schleife.

//Clear the panel
this.flowLayoutPanelLabels.Controls.Clear();

und die anzahl buttons muss ich ja dekrementieren
weil ich ja mit control_ dispose das control entferne und somit auch die anzahl der controls im panel verringer

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Eben das bezwifele ich ja.

Controls speichert Referenzen auf Objekte vom Typ Control.
Controls[n] liefert dir jetzt die Referenz auf ein Control.
Controls[n].Dispose() würde also die Dispose()-Methode des referenzierten Controls aufrufen, jedoch nichts an der Speicherung der Referenz in Controls ändern.

Hast du dieses Verhalten mal untersucht oder liege ich jetzt falsch?

B
1.529 Beiträge seit 2006
vor 17 Jahren

Habe noch mal in der MSDN nachgelesen. Das Verhalten, dass du beschreibst trifft auf Controls.Remove() zu.
Bei Clear() steht:

Calling the Clear method does not remove control handles from memory. You must explicitly call the Dispose method to avoid memory leaks.

Daher gehe ich davon aus, dass das auch auf Remove() und RemoveAt() zutrifft.

Somit würde ich mal diese Schleife probieren:


while (this.flowLayoutPanelLabels.Controls.Count > 0)
{
      this.flowLayoutPanelLabels.Controls[0].Dispose();
      this.flowLayoutPanelLabels.Controls.RemoveAt( 0 );
}

D
demondriver235 Themenstarter:in
496 Beiträge seit 2005
vor 17 Jahren

ich glaub ich werde verrückt

hab gerade im prinzip das gleich gemacht wie du (ok deins ist eleganter, aber war ja auch nur test)

!!!!!!!und es funzt


int buttonCount = this.flowLayoutPanelLabels.Controls.Count;
            for (int i = 0; i < buttonCount; i++)
            {
                this.flowLayoutPanelLabels.Controls[i].Dispose();
                buttonCount = this.flowLayoutPanelLabels.Controls.Count;
                i = 0;
            }
            this.flowLayoutPanelLabels.Controls[0].Dispose();
            //for debugging to check control count ==0
            int buttonCount2 = this.flowLayoutPanelLabels.Controls.Count;

du hattest recht und ich hab nicht alle controls erwischt
daran hats gelegen!

du bist mein kumpel, vielen dank , have a nice weekend

"Programming is similar to sex. If you make a mistake, you have to support it for the rest of your life."

B
1.529 Beiträge seit 2006
vor 17 Jahren

Oder alternativ so:


foreach( Control LöschMich in this.flowLayoutPanelLabels.Controls)
{
      LöschMich.Dispose();
}
this.flowLayoutPanelLabels.Controls.Clear();

Sollte prinzipiell keinen Unterschied machen, ausser dass diese Version möglicherweise etwas schneller ist.

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ok, kam zu spät.

Freut mich trotzdem, dass es jetzt hinhaut.
Dir auch schönes WE.

T
506 Beiträge seit 2005
vor 17 Jahren

Hallo

ich habe ein ähnliches Problem, und bringe die Datei einfach nicht zu löschen.

bei Load wird eine PictureBox so mit einem Bild gefüllt:


                    Bitmap bild = new Bitmap(speicherpfad + fileName);
                    //SC: Artikelbild der PictrureBox zuweisen
                    this.PictureBild.Image = bild;

und wenn ich das per button event wieder löschen möchte bringt er mir den fehler... used by another prozess.

ich wollte es so löschen.


                    //SC: Bild löschen
                    PictureBild.Dispose();                 
                    File.Delete(speicherpfad + fileName);

kann mir da jemand helfen?

grüsse

B
1.529 Beiträge seit 2006
vor 17 Jahren

Probier mal so:

// zuweisen
this.PictureBild.Image = new Bitmap(speicherpfad + fileName);
// löschen
this.PictureBild.Image.Dispose();
this.PictureBild.Dispose();
File.Delete(speicherpfad + fileName);

Funktioniert es jetzt?

T
506 Beiträge seit 2005
vor 17 Jahren

Hej Borg

es geht leider nicht. kommt genau die gleiche Meldung, dass es noch woanders verwendet wird.

grüsse

edit://

es geht jetzt, musste noch in einer andern Form ein Dispose machen.