Возможно ли, что исходный поток, поддерживающий исходное изображение, был закрыт? Если поток за битовой картой был закрыт, вы начинаете получать ошибки GDI +. Я часто сталкивался с этим, когда мы добавили обработку изображений на наш сайт.
Если вы откроете объект Bitmap в отладчике Visual Studio, вы увидите исключения вместо значений свойств? Если это так, то это не проблема с операцией сохранения, но слой GDI + утратил способность обрабатывать объект, точка.
Я обнаружил, что мне нужно было отслеживать MemoryStreams, принадлежащие моим растровым изображениям, и сохранять их все вместе. Изменение размера изображения привело к созданию нового MemoryStream с новым растровым изображением.
Я закончил тем, что создал этот простой класс (обрезал некоторые дополнительные свойства, ненужные здесь):
public class UploadedImage : IDisposable
{
private Bitmap _img = null;
private Stream _baseStream = null;
/// <summary>
/// The image object. This must always belong to BaseStream, or weird things can happen.
/// </summary>
public Bitmap Img
{
[DebuggerStepThrough]
get { return _img; }
[DebuggerStepThrough]
set { _img = value; }
}
/// <summary>
/// The stream that stores the image. This must ALWAYS belong to Img, or weird things can happen.
/// </summary>
public Stream BaseStream
{
[DebuggerStepThrough]
get { return _baseStream; }
[DebuggerStepThrough]
set { _baseStream = value; }
}
[DebuggerStepThrough]
public void Dispose()
{
if (Img != null)
Img.Dispose();
if (BaseStream != null)
BaseStream.Close();
_attached = false;
}
}
Теперь я имел дело с изображениями, загруженными на наш веб-сайт, и обнаружил, что, когда Asp.Net перерабатывает поток, присоединенный к запросу, все внезапные операции с изображениями начинают исчезать. Итак, мое решение, было ли это лучшим способом сделать это или нет, было скопировать данные из потока выгрузки в мой собственный MemoryStream, загрузить из него изображение и вставить оба в этот контейнер. И где бы я ни создавал новое изображение из старого, я всегда держал поток и изображение вместе.
Надеюсь, это поможет.
РЕДАКТИРОВАТЬ: Мне также интересно посмотреть, как вы делаете изменения размера изображения. Вот фрагмент того, как я это сделал:
temp = new Bitmap(newWidth, newHeight, PIXEL_FORMAT);
temp.SetResolution(newHorizontalRes, newVerticalRes);
gr = Graphics.FromImage(temp);
//
// This copies the active frame from 'img' to the new 'temp' bitmap.
// Also resizes it and makes it super shiny. Sparkle on, mr image dude.
//
Rectangle rect = new Rectangle(0, 0, newWidth, newHeight);
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.SmoothingMode = SmoothingMode.HighSpeed;
gr.PageUnit = GraphicsUnit.Pixel;
gr.DrawImage(img, rect);
//
// Image copied onto the new bitmap. Save the bitmap to a fresh memory stream.
//
retval = new UploadedImage();
retval.BaseStream = (Stream)(new MemoryStream());
temp.Save(retval.BaseStream, ImageFormat.Jpeg);
retval.Img = temp;