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.
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();
}
Your stream stuff should be in using blocks, which will dispose of your goods automagically and close them too. Not terribly important, but easier to manage.
Your generic GDI+ error is likely because you are trying to perform an operation or call a method on a file for which the stream is already closed.
Check it out...
your method isn't really false, only a few things had to be changed:
// 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, System.Drawing.Imaging.ImageFormat.Jpeg); // <-- Error doesn't occur anymore
ms.Position = 0;
pic.Data = TagLib.ByteVector.FromStream(ms);
f.Tag.Pictures = new TagLib.IPicture[1] { pic };
f.save();
ms.Close();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With