0

I am trying to create a C# app which loads a powerpoint and makes each slide a JPG that is stored in a list of BitmapImages. The user should be able to load another powerpoint, which, on load, deletes each of the other JPGs in the folder. Currently, I am unable to delete the JPGs, as they are "being used by another process" which happens to be this app. How can I work around this?

foreach (ISlide slide in presentation.Slides)
{
             System.IO.Stream imageStream = slide.ConvertToImage(Syncfusion.Drawing.ImageFormat.Jpeg);
             System.Drawing.Image convertedImage = System.Drawing.Image.FromStream(imageStream);

             if (!System.IO.File.Exists(picsPath + "\\Slide_" + slide.SlideNumber + ".jpg"))
                  convertedImage.Save(picsPath + "\\Slide_" + slide.SlideNumber + ".jpg");
             else
             {
                        try
                        {
                  System.IO.File.Delete(picsPath + "\\Slide_" + slide.SlideNumber + ".jpg");               
                  convertedImage.Save(picsPath + "\\Slide_" + slide.SlideNumber + ".jpg");
             }
                  catch (Exception df){Console.WriteLine(df.StackTrace);}
             }
             bitmap = new BitmapImage();
             bitmap.BeginInit();
             bitmap.UriSource = new Uri(picsPath + "\\Slide_" + slide.SlideNumber + ".jpg");
             bitmap.CacheOption = BitmapCacheOption.OnLoad;
             bitmap.EndInit();
             VisualAidPPT.Add(bitmap);
             convertedImage = null;
}
jjo
  • 154
  • 2
  • 14
  • THat is because jpg file is being locked by the previous operation you performed on it. Use .Dispose() to release file handler – Clint Dec 18 '19 at 18:22
  • You can use `handle.exe` from sysinternals which gives you the process that uses the specified file. You can parse its output and kill that process then you can delete your file. – Eldar Dec 18 '19 at 18:27
  • Why are you using `System.Drawing.Image.FromStream` (which is WinForms) instead of directly loading a BitmapImage by assigning the `imageStream` to its `StreamSource` property? There doesn't seem to be any need to save the JPEG files at all. – Clemens Dec 18 '19 at 18:43
  • Thank you all for your help. Now, when I display a new ppt, the first few slides are still displayed from the last ppt that was loaded, but the last few are from the new updated one. Checking the files in the folder, all of them are the new updated ones. Would anyone know why this may be? – jjo Dec 18 '19 at 19:29
  • @Clemens I have used the StreamSource property, but an exception is thrown when I don't have the UriSource set to the location of the file – jjo Dec 18 '19 at 21:09
  • You don't need to set UriSource when you set StreamSource (and you don't need a file!). But you may have to set `imageStream.Position = 0;` before. Which exception is thrown? We can't read your mind. – Clemens Dec 18 '19 at 21:12
  • @Clemens I get a System.NotSupportedException: The component cannot be found – jjo Dec 18 '19 at 21:16

1 Answers1

1

You don't need to write any image file at all.

Just directly use the Stream returned by slide.ConvertToImage to load a BitmapImage:

foreach (var slide in presentation.Slides)
{
    var bitmap = new BitmapImage();

    using (var imageStream = slide.ConvertToImage(Syncfusion.Drawing.ImageFormat.Jpeg))
    {
        imageStream.Position = 0;

        bitmap.BeginInit();
        bitmap.StreamSource = imageStream;
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.EndInit();
    }

    VisualAidPPT.Add(bitmap);
}

EDIT: In case the above does not work, you may still decode a System.Drawing.Image and save that to a MemoryStream:

foreach (var slide in presentation.Slides)
{
    var bitmap = new BitmapImage();

    using (var imageStream = slide.ConvertToImage(Syncfusion.Drawing.ImageFormat.Jpeg))
    using (var image = System.Drawing.Image.FromStream(imageStream))
    using (var memoryStream = new MemoryStream())
    {
        image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
        memoryStream.Position = 0;

        bitmap.BeginInit();
        bitmap.StreamSource = memoryStream;
        bitmap.CacheOption = BitmapCacheOption.OnLoad;
        bitmap.EndInit();
    }

    VisualAidPPT.Add(bitmap);
}
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • I am getting an exception System.NotSupportedException: No imaging component suitable to complete this operation was found – jjo Dec 18 '19 at 21:28
  • Did you set `Position = 0`? – Clemens Dec 18 '19 at 21:31
  • See the edited answer. It copies the image stream to a MemoryStream before loading the BitmapImage. – Clemens Dec 18 '19 at 21:37
  • Still get the same exception; the component cannot be found – jjo Dec 18 '19 at 21:40
  • Can you try a different format than `Syncfusion.Drawing.ImageFormat.Jpeg`? E.g. PNG? – Clemens Dec 18 '19 at 21:41
  • Still the same using Syncfusion.Drawing.ImageFormat.Png – jjo Dec 18 '19 at 21:43
  • That's odd. If you can create a System.Drawing.Image from the stream, save that to a file and load a BitmapImage from the file, you should of course also be able to create a BitmapImage directly from the stream. Anything else doesn't make sense... – Clemens Dec 18 '19 at 21:47
  • Yes it's very strange. The exception is thrown at bitmap.EndInit() – jjo Dec 18 '19 at 21:57
  • Yes, that's exactly what happens when the stream does not contain a complete JPEG frame – Clemens Dec 18 '19 at 21:59
  • Just for a test, try to keep the image stream open as shown in the second code part above. – Clemens Dec 18 '19 at 22:04
  • Still the same exception after removing cacheoption – jjo Dec 18 '19 at 22:07
  • I've made another edit, now with using `System.Drawing.Image`. If that still doesn't work, I don't know what else to try. – Clemens Dec 18 '19 at 22:18
  • Now i get a System.FileFormatException: The image cannot be decoded. The image header might be corrupted. – jjo Dec 18 '19 at 22:23
  • That's from `System.Drawing.Image.FromStream`? How did that work in your original code? – Clemens Dec 18 '19 at 22:29
  • It worked when I made the file format System.Drawing.Imaging.ImageFormat.Bmp, thank you for all of your help, I'll accept your answer – jjo Dec 18 '19 at 22:29