С# gif Изображение в MemoryStream и обратно (потерять анимацию)

У меня есть небольшая проблема, и я не нахожу никаких решений. Я хочу преобразовать GIF в байт [], а затем обратно в GIF. У меня работает нормально, но я теряю анимацию.

Когда я начинаю, это идеально анимированный GIF (я показываю его в элементе PictureBox). Но после преобразования я застреваю на первом кадре.

HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create("creativetechs.com/i/tip_images/ExampleAnimation.gif");
HttpWebResponse httpWebReponse = (HttpWebResponse)httpWebRequest.GetResponse();
Stream stream = httpWebReponse.GetResponseStream();
Image img = Image.FromStream(stream);

MemoryStream ms = new MemoryStream();
img.Save(ms,img.RawFormat);
byte [] bytes = ms.ToArray();
Image img2 = Image.FromStream(new MemoryStream(bytes));

int frames1 = img.GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);
int frames2 = img2.GetFrameCount(System.Drawing.Imaging.FrameDimension.Time);

Я тоже пробовал использовать не RawFormat а System.Drawing.Imaging.ImageFormat.Gif. Ничего не изменил. frames1 - правильное количество кадров. frames2 равно 1.

У меня есть 2 элемента PictureBox в моем графическом интерфейсе. На одном изображено img, а на другом img2. Но img2 не анимируется, а img анимируется. Что случилось?

Я также пытался использовать сериализацию, чтобы создать свой byte[].

Я сериализовал изображение и снова десериализовал его, и это тоже ничего не изменило. Как это возможно?


person Oliver Bernhardt    schedule 06.01.2012    source источник
comment
Кодер GIF GDI+ не поддерживает ни SaveAdd(), ни анимированные GIF.   -  person Hans Passant    schedule 07.01.2012
comment
Вы не думали, что это может быть проблема с GIF? Я только что попробовал ваш точный код с этим GIF, и это сработало без проблем. И frames1, и frames2 равны 17.   -  person Michael Minton    schedule 07.01.2012
comment
И почему я могу загружать и визуализировать анимированный gif из Web ResponseStream?   -  person Oliver Bernhardt    schedule 07.01.2012
comment
хорошо, я попробую эту гифку. ... Нет такого же результата   -  person Oliver Bernhardt    schedule 07.01.2012
comment
Нет необходимости писать [не решено] в заголовке вопроса, так как он будет отображаться с зеленым счетчиком ответов в списке, когда вы принимаете ответ, поэтому очевидно, когда он решен/не решен.   -  person Igby Largeman    schedule 07.01.2012


Ответы (3)


Когда вы загружаете изображение из Stream, платформа .NET определяет, что GIF-файл анимирован. Поскольку он знает, что не сможет перекодировать анимированный GIF, он пытается сохранить исходную кодировку GIF. Но это происходит после чтения потока и декодирования GIF. Поэтому, когда он пытается перемотать поток, это терпит неудачу, и в конечном итоге он не сохраняет оригинал.

Когда вы вызываете Save(), он сначала проверяет, сохранена ли исходная кодировка. Но так как эта операция не удалась, он пытается перекодировать GIF. Поскольку в .NET нет кодировщика для анимированных GIF-файлов, он кодирует только первый кадр.

Если вместо этого вы используете FileStream, это работает, так как FileStream доступен для поиска.

Вы можете заставить свой код работать, сначала загрузив ответ в MemoryStream:

// ...
Stream stream = httpWebReponse.GetResponseStream();

MemoryStream memoryStream = new MemoryStream();
stream.CopyTo(memoryStream);
memoryStream.Position = 0;
stream = memoryStream;

Image img = Image.FromStream(stream);
// ...

Если вы хотите увидеть, что произойдет, включите отладку источника ссылок .NET и обратите внимание на то, что происходит в Image.EnsureSave(). Вы также заметите, что реализация Image уже копирует Stream в MemoryStream, чтобы они могли решить проблему, используя его вместо исходного Stream.

person Rasmus Faber    schedule 17.01.2012
comment
Расмус: Не пострадает ли ваше решение от этой проблемы? support.microsoft.com/kb/814675 Кроме того, если поток был уничтожен во время существования объект Bitmap, вы не можете успешно получить доступ к изображению, основанному на потоке. Объект Bitmap не хранит ссылку на поток. Если поток удален, ссылки на растровое изображение завершатся ошибкой. Вам это сойдет с рук при работе с обычными растровыми изображениями, но если вы создаете анимированный GIF из потока, перерисовка анимированного GIF невозможна на некоторых системах. - person MindModel; 08.11.2014

GDI+ не содержит никакого кодировщика анимированного GIF (только декодер). Таким образом, ваш img.Save удалит анимацию. Но вы можете попробовать это: http://www.codeproject.com/KB/GDI-plus/NGif.aspx

person Dan Byström    schedule 06.01.2012
comment
Он отлично работает, если вы загружаете gif из файла, но не загружаете его из ответа http. - person Oliver Bernhardt; 07.01.2012

Как процитировал Расмус Фабер 17 янв. Большое спасибо. Мой пример кода, как показано ниже. Включите загрузку как LPG, так и анимации GIF без каких-либо ошибок, а также включите удаление всех ненужных файлов.

Dim t1 As String
t1 = ListBox5.SelectedItem.ToString
Dim mmp As MemoryStream
mmp = New MemoryStream()

Using str As Stream = File.OpenRead(t1)
str.CopyTo(mmp)
End Using
PictureBox8.Image = Image.FromStream(mmp)
person supwat    schedule 17.09.2020