0

What I am trying to do here is:

  • Download an image
  • Save it to disk
  • Resize etc
  • Save it with a new name
  • Delete the old image

I have achieved everything but not the last step. I get the "file in use" error.

This is the code:

            filenameb = "img-1b.jpg";//old img
            fullpathb = Path.Combine(dir, filenameb);//old img path
            //downloading using imglink
            client.DownloadFile(imglink, fullpathb);//save old img as %dir%\img-1b.jpg
            //until here I downloaded the "old" img

            filename = "img-1.jpg";//new img
            fullpath = Path.Combine(dir, filename);//new img path
            //name and fullpath for the "new img" are set

            Image imgresize = Image.FromFile(fullpathb);//give old img path
            imgresize = FixedSize(imgresize);//resize
            imgresize.Save(fullpath, ImageFormat.Jpeg);//save new img as %dir%\img-1.jpg

            //EVERYTHING WORKS PERFECTLY UP TO HERE

            imgresize.Dispose();//dispose -has old img path
            System.IO.File.Delete(fullpathb);//delete old img

I also dispose the image in FixedSize. And this is the code of "FixedSize" if needed:

    //kind of messed up to save some space
    static Image FixedSize(Image imgPhoto)
    {
        int Width = 300;int Height = 250;
        int sourceWidth = imgPhoto.Width;int sourceHeight = imgPhoto.Height;
        int sourceX = 0;int sourceY = 0;int destX = 0;int destY = 0;
        float nPercent = 0;float nPercentW = 0;float nPercentH = 0;

        nPercentW = ((float)Width / (float)sourceWidth);
        nPercentH = ((float)Height / (float)sourceHeight);

        if (nPercentH < nPercentW){ nPercent = nPercentH;
            destX = (int)((Width - (sourceWidth * nPercent)) / 2);}
        else { nPercent = nPercentW;
            destY = (int)((Height - (sourceHeight * nPercent)) / 2); }

        int destWidth = (int)(sourceWidth * nPercent);
        int destHeight = (int)(sourceHeight * nPercent);

        Bitmap bmPhoto = new Bitmap(Width, Height, PixelFormat.Format24bppRgb);
        bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution);

        Graphics grPhoto = Graphics.FromImage(bmPhoto);
        grPhoto.Clear(Color.White);
        grPhoto.InterpolationMode = InterpolationMode.HighQualityBicubic;

        grPhoto.DrawImage(imgPhoto,
            new Rectangle(destX, destY, destWidth, destHeight),
            new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
            GraphicsUnit.Pixel);

        grPhoto.Dispose();
        return bmPhoto;
    }

I am really new to this and I can't realise what i'm doing wrong (or what i am not doing at all). Any help is appreciated!

  • 1
    Why are you using `IDisposable` improperly? Your code is completely broken if any exceptions occur. Use [`using`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement)! – Aluan Haddad Jan 16 '18 at 13:54
  • Instead of saving the downloaded image to disk, why can't you resize it in memory if resizing is all you need the original image for? – ethane Jan 16 '18 at 13:56
  • Have a look at this answer (https://stackoverflow.com/questions/6576341/open-image-from-file-then-release-lock) for the 'correct' way to access a file loaded from disk, and only delete your file at the end of it. – LordWilmore Jan 16 '18 at 13:57
  • @AluanHaddad, it would be more helpful if you pointed the OP to actual examples of a best practice. – ethane Jan 16 '18 at 13:58
  • Possible duplicate of [Open Image from file, then release lock?](https://stackoverflow.com/questions/6576341/open-image-from-file-then-release-lock) – LordWilmore Jan 16 '18 at 13:58
  • your error tells you exactly what you need to know. your file is still in use, you'll want to `close` it out. – user2366842 Jan 16 '18 at 14:10
  • The resize step never cleans up the old object. That's the problem. Assign the result from FixedSize to a new object, in a new `using` block. – Nyerguds Jan 24 '18 at 13:38
  • @LordWilmore Indeed a duplicate, but sadly, barely any of the many, many duplicates of this actually have a 100% correct answer. [I got one](https://stackoverflow.com/a/48170549/395685), but even that doesn't work in some cases, like animated gifs. Though in this case, just proper disposing will work fine. – Nyerguds Jan 24 '18 at 13:40

1 Answers1

0
Image imgresize = Image.FromFile(fullpathb)

This is going to lock the file. Instead, create an image from a MemoryStream of bytes read from the file

byte[] imageBytes = FileReadAllBytes(fullpathb);

using (var ms = new MemoryStream(imageBytes)){
    var image = Image.FromStream(ms);
}

Untested

p3tch
  • 1,414
  • 13
  • 29
  • Sadly, a disposed stream can _also_ give errors, since the image retains a reference to that stream object. The only fool-proof way is to [deep-clone the object by creating a new image object from a constructor _without_ any source parameters, and copy the original's backing byte data into it using LockBits](https://stackoverflow.com/a/48170549/395685). – Nyerguds Jan 24 '18 at 13:36