[VB.NET] Afbeelding draaien en opslaan

Pagina: 1
Acties:
  • 142 views sinds 30-01-2008
  • Reageer

  • Tsjilp
  • Registratie: November 2002
  • Niet online
Ik ben bezig met een tooltje waarmee foto's geupload kunnen worden.
Deze heb ik al eens eerder geschreven, maar omdat deze vol fouten zit en niet echt schaalbaar is ben ik hem aan het herschrijven. Ik zit echter vast op het opslaan van een jpg.

Ik heb een picturebox met een afbeelding, wanneer er op een button geklikt wordt moet deze 90 graden gedraaid worden. De code die ik daarvoor gebruik is:
code:
1
2
3
4
5
6
    Private Sub butRotate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles butRotate.Click
        Dim img_rotate As Bitmap = Image.FromFile(img)
        PictureBox1.Image = Nothing
        img_rotate.RotateFlip(RotateFlipType.Rotate90FlipNone)
        img_rotate.Save(img, Imaging.ImageFormat.Jpeg)
    End Sub

Hij loopt echter vast op de regel "img_rotate.Save(img, Imaging.ImageFormat.Jpeg)" met de volgende foutmelding:
"An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in system.drawing.dll

Additional information: A generic error occurred in GDI+."
Lekker veelzeggend dus...
Ik heb de foutmelding al in google en in de search geramd, maar helaas geen succes, wanneer ik hem onder een andere bestandsnaam opsla gaat het wel goed. Blijkbaar kan hij dus het bestaande bestand overschrijven.
Vervolgens heb ik geprobeerd om de afbeelding op te slaan onder een andere bestandsnaam en deze te kopieren naar het origineel, dus:
code:
1
2
3
img_rotate.Save("C:\test.jpg", Imaging.ImageFormat.Jpeg)
img_rotate = Nothing
FileCopy("C:\test.jpg", img)

maar dan krijg ik deze melding:

"An unhandled exception of type 'System.IO.IOException' occurred in microsoft.visualbasic.dll

Additional information: The process cannot access the file "D:\Mijn afbeeldingen\vakantiefoto's 2005\IMAG0006.JPG" because it is being used by another process."

wat ik erg vreemd vind want elk object wordt op Nothing gezet alvorens het bestand te overschrijven.

Raar... Is zo gek nog niet


  • user109731
  • Registratie: Maart 2004
  • Niet online
Het bestand is gewoon in gebruik... Je heb 'm niet geopend in Explorer ofzo?
Ik zou zelf even met zo'n soort programma kijken welk proces 'm vasthoud. Dan weet je direct zeker of het aan jouw programma ligt of aan iets anders.

  • Tsjilp
  • Registratie: November 2002
  • Niet online
Nee, ik heb hem nergens open staan. Verder wordt het bestand op 3 plaatsen gebruikt:
in het parentform
in de picturebox
en in de variabele img_rotate,
deze zet ik alle 3 op 'nothing' alvorens het bestand op te staan. De files worden ingeladen via een openfiledialog (die overigens ook weer op nothing gezet wordt na gebruik)

Dat programmatje geeft de file niet weer, dus kan ik ook niet uitzoeken welk process het gebruikt.

Raar... Is zo gek nog niet


  • __fred__
  • Registratie: November 2001
  • Laatst online: 20-02 11:54
VB.NET is geen VB

een variabele op nothing zetten wil dus niet zeggen dat er geheugen wordt vrijgemaakt en eventuele bestanden worden gesloten. De garbage-collector besluit zelfstandig wanneer geheugen wordt vrijgemaakt, je hebt geen controle over wanneer een object wordt opgeruimd. Als je afsluitende handelingen wilt verrichten moet je dus zelf expliciet een .close() of dispose() voor dat object aanroepen.

Het netst hiervoor is om Using te gebruiken.

code:
1
2
3
Using { resourcelist | resourceexpression }
    [ statements ]
End Using

  • Tsjilp
  • Registratie: November 2002
  • Niet online
Volgens MSDN is using alleen voor C#, en moet je bij VB gebruik maken van TRY - FINALLY, heb nu
(Werk met VB.NET 2003)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        Dim img_rotate As Image = Image.FromFile(im)
        Try
            img_rotate.RotateFlip(RotateFlipType.Rotate90FlipNone)
            img_rotate.Save("C:\test.jpg", Imaging.ImageFormat.Jpeg)
        Finally
            PictureBox1.Image.Dispose()
            _parent.Image.Dispose()
            img_rotate.Dispose()
        End Try
        Try
            FileCopy("C:\test.jpg", im)
        Finally
            FileSystem.Kill("C:\test.jpg")
            FileSystem.Reset()
        End Try

        PictureBox1.Image = Image.FromFile(im)
        _parent.Image = Image.FromFile(im).GetThumbnailImage(200, 150, Nothing, IntPtr.Zero)

Nu doet hij het 1 keer, de tweede keer geeft hij aan dat 'im' in gebruik is:

An unhandled exception of type 'System.IO.IOException' occurred in microsoft.visualbasic.dll

Additional information: The process cannot access the file "D:\Mijn afbeeldingen\vakantiefoto's 2005\IMAG0006.JPG" because it is being used by another process.

Nu heb ik het idee dat ik zo'n beetje alles afsluit aan het eind van de functie. Zelfs als ik GC.Collect() aanroep blijf ik deze foutmelding krijgen.


---
SOLVED! Finally!
2x GC.Collect() aanroepen did the trick:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Try
            img_rotate.RotateFlip(RotateFlipType.Rotate90FlipNone)
            img_rotate.Save("C:\test.jpg", Imaging.ImageFormat.Jpeg)
        Finally
            PictureBox1.Image.Dispose()
            _parent.Image.Dispose()
            img_rotate.Dispose()
        End Try
        GC.Collect()
        Try
            FileCopy("C:\test.jpg", im)
        Finally
            FileSystem.Kill("C:\test.jpg")
            FileSystem.Reset()
        End Try
        GC.Collect()
        PictureBox1.Image = Image.FromFile(im)
        _parent.Image = Image.FromFile(im).GetThumbnailImage(200, 150, Nothing, IntPtr.Zero)

[ Voor 25% gewijzigd door Tsjilp op 28-05-2006 20:44 . Reden: Problem solved ]

Raar... Is zo gek nog niet


  • __fred__
  • Registratie: November 2001
  • Laatst online: 20-02 11:54
Ik denk eerder dat het te maken heeft dat gc.collect lang genoeg duurt voordat je files gesloten worden. Als je heel snel achter elkaar files opent en sluit wil er wel eens wat blijven hangen in een virusscanner of zo. Ik kan het me bijna niet voorstellen dat die GC.collect het verschil maakt.

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

GC.WaitForPendingFinalizers()

ASSUME makes an ASS out of U and ME


  • Tsjilp
  • Registratie: November 2002
  • Niet online
__fred__ schreef op maandag 29 mei 2006 @ 18:57:
Ik denk eerder dat het te maken heeft dat gc.collect lang genoeg duurt voordat je files gesloten worden. Als je heel snel achter elkaar files opent en sluit wil er wel eens wat blijven hangen in een virusscanner of zo. Ik kan het me bijna niet voorstellen dat die GC.collect het verschil maakt.
Blijkbaar toch wel :P

Raar... Is zo gek nog niet

Pagina: 1