C# – Loading Album art with TagLib sharp and then saving it to same/different file in C# causes memory error

cmp3taglib

My application lists all MP3's in a directory and when the user selects a file it loads the tag info, including album art. The art is loaded into a variable to be used when the user saves the data. The art is also loaded into a picture frame for the user to see.

// Global to all methods
System.Drawing.Image currentImage = null;

// In method onclick of the listbox showing all mp3's
TagLib.File f = new TagLib.Mpeg.AudioFile(file);
if (f.Tag.Pictures.Length > 0)
{
      TagLib.IPicture pic = f.Tag.Pictures[0];
      MemoryStream ms = new MemoryStream(pic.Data.Data);
      if (ms != null && ms.Length > 4096)
      {
           currentImage = System.Drawing.Image.FromStream(ms);
           // Load thumbnail into PictureBox
           AlbumArt.Image = currentImage.GetThumbnailImage(100,100, null, System.IntPtr.Zero);
      }
      ms.Close();
}

// Method to save album art
TagLib.Picture pic = new TagLib.Picture();
pic.Type = TagLib.PictureType.FrontCover;
pic.MimeType = System.Net.Mime.MediaTypeNames.Image.Jpeg;
pic.Description = "Cover";
MemoryStream ms = new MemoryStream();
currentImage.Save(ms, ImageFormat.Jpeg); // <-- Error occurs on this line
ms.Position = 0;
pic.Data = TagLib.ByteVector.FromStream(ms);
f.Tag.Pictures = new TagLib.IPicture[1] { pic };
f.save();
ms.Close();

If I load the image and try to save it right away I get this "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." If I try to save currentImage as a ImageFormat.Bmp I get this "A generic error occurred in GDI+."

My save method works correctly if I load an image from a url like this:

WebRequest req = WebRequest.Create(urlToImg);
WebResponse response = req.GetResponse();
Stream stream = response.GetResponseStream();
currentImage = Image.FromStream(stream);
stream.Close();

So I'm guessing there is an issue with the way that I am loading the image into currentImage when the user selects an MP3 from the listbox.

I have found a lot of examples of loading and saving images to mp3's but no one seems to be having this issue when they try to save the are immediately after loading it.

Best Answer

Thanks for the help Jim but I couldn't really get it working using the 'using' blocks so I'm guessing the stream was still closing somewhere. I found another way to do what I was looking for by storing/saving a byte[] instead of an Image. And then just saving it using:

using (MemoryStream ms = new MemoryStream(currentImageBytes))
{
    pic.Data = TagLib.ByteVector.FromStream(ms);
    f.Tag.Pictures = new TagLib.IPicture[1] { pic };
    if (save)
        f.Save();
}
Related Topic