Ocorreu um erro genérico no GDI +, imagem JPEG para MemoryStream

Este parece ser um erro infame em toda a web. Tanto que não consegui encontrar uma resposta para o meu problema, pois o meu cenário não se encheckbox. Uma exceção é lançada quando salvo a imagem no stream.

Estranhamente, isso funciona perfeitamente com um png, mas dá o erro acima com jpg e gif, o que é bastante confuso.

Problema mais semelhante lá fora dizem respeito a salvar imagens em arquivos sem permissions. Ironicamente, a solução é usar um stream de memory como eu estou fazendo ….

public static byte[] ConvertImageToByteArray(Image imageToConvert) { using (var ms = new MemoryStream()) { ImageFormat format; switch (imageToConvert.MimeType()) { case "image/png": format = ImageFormat.Png; break; case "image/gif": format = ImageFormat.Gif; break; default: format = ImageFormat.Jpeg; break; } imageToConvert.Save(ms, format); return ms.ToArray(); } } 

Mais detalhes para a exceção. A razão pela qual isso causa tantos problemas é a falta de explicação 🙁

 System.Runtime.InteropServices.ExternalException was unhandled by user code Message="A generic error occurred in GDI+." Source="System.Drawing" ErrorCode=-2147467259 StackTrace: at System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) at System.Drawing.Image.Save(Stream stream, ImageFormat format) at Caldoo.Infrastructure.PhotoEditor.ConvertImageToByteArray(Image imageToConvert) in C:\Users\Ian\SVN\Caldoo\Caldoo.Coordinator\PhotoEditor.cs:line 139 at Caldoo.Web.Controllers.PictureController.Croppable() in C:\Users\Ian\SVN\Caldoo\Caldoo.Web\Controllers\PictureController.cs:line 132 at lambda_method(ExecutionScope , ControllerBase , Object[] ) at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) at System.Web.Mvc.ControllerActionInvoker.c__DisplayClassa.b__7() at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) InnerException: 

OK coisas que eu tentei até agora.

  1. Clonando a imagem e trabalhando nisso.
  2. Recuperando o codificador para esse MIME passando isso com a configuração de qualidade jpeg.

OK, eu pareço ter encontrado a causa apenas por pura sorte e não há nada de errado com esse método específico, é ainda mais backup da pilha de chamadas.

Anteriormente, redimensiono a imagem e, como parte desse método, retorno o object redimensionado da seguinte forma. Eu inseri duas chamadas para o método acima e salve diretamente em um arquivo.

 // At this point the new bitmap has no MimeType // Need to output to memory stream using (var m = new MemoryStream()) { dst.Save(m, format); var img = Image.FromStream(m); //TEST img.Save("C:\\test.jpg"); var bytes = PhotoEditor.ConvertImageToByteArray(img); return img; } 

Parece que o stream de memory em que o object foi criado deve estar aberto no momento em que o object é salvo. Não sei por que isso acontece. Alguém é capaz de me esclarecer e como eu posso contornar isso.

Eu só retorno de um stream porque depois de usar o código de redimensionamento semelhante a este, o arquivo de destino tem um tipo mime desconhecido (img.RawFormat.Guid) e Id como o tipo Mime para estar correto em todos os objects de imagem, pois torna difícil escrever genérico manuseando o código de outra forma.

EDITAR

Isso não surgiu na minha pesquisa inicial, mas aqui está a resposta de Jon Skeet

Se você está recebendo esse erro, então posso dizer que seu aplicativo não tem permissão de gravação em algum diretório.

Por exemplo, se você está tentando salvar a imagem do stream de memory para o sistema de arquivos, você pode obter esse erro.

Por favor, se você estiver usando o XP, certifique-se de adicionar permissão de gravação para a conta aspnet nessa pasta.

Se você estiver usando o Windows Server (2003, 2008) ou o Vista, certifique-se de adicionar permissão de gravação para a conta do serviço de rede.

Espero que ajude alguém.

Eu adicionarei essa causa do erro também na esperança de que isso ajude algum futuro viajante da Internet. 🙂

GDI + limita a altura máxima de uma imagem para 65500

Fazemos alguns redimensionamentos básicos de imagem, mas no redimensionamento tentamos manter a proporção. Nós temos um cara de QA que é um pouco bom demais neste trabalho; ele decidiu testar isso com uma foto de um pixel de largura que tinha 480 pixels de altura. Quando a imagem foi dimensionada para atender às nossas dimensões, a altura estava ao norte de 68.000 pixels e nosso aplicativo explodiu com A generic error occurred in GDI+ .

Você pode verificar isso sozinho com o teste:

  int width = 480; var height = UInt16.MaxValue - 36; //succeeds at 65499, 65500 try { while(true) { var image = new Bitmap(width, height); using(MemoryStream ms = new MemoryStream()) { //error will throw from here image.Save(ms, ImageFormat.Jpeg); } height += 1; } } catch(Exception ex) { //explodes at 65501 with "A generic error occurred in GDI+." } 

É uma pena que não exista um ArgumentException amigável .net lançado no construtor do Bitmap .

Este artigo explica em detalhes o que exatamente acontece: dependencies de construtor de bitmap e imagem

Em suma, para uma vida inteira de uma Image construída a partir de um stream , o stream não deve ser destruído.

Então, ao invés de

 using (var strm = new ... ) { myImage = Image.FromStream(strm); } 

tente isso

 Stream imageStream; ... imageStream = new ...; myImage = Image.FromStream(strm); 

e feche o imageStream no fechamento do formulário ou na página da web.

Você também obterá essa exceção se tentar salvar em um caminho inválido ou se houver um problema de permissão.

Se você não tiver 100% de certeza de que o caminho do arquivo está disponível e as permissions estão corretas, tente gravar um em um arquivo de texto. Isso leva apenas alguns segundos para descartar o que seria uma correção muito simples.

 var img = System.Drawing.Image.FromStream(incomingStream); // img.Save(path); System.IO.File.WriteAllText(path, "Testing valid path & permissions."); 

E não esqueça de limpar seu arquivo.

Salvar imagem na variável de bitmap

 using (var ms = new MemoryStream()) { Bitmap bmp = new Bitmap(imageToConvert); bmp.Save(ms, format); return ms.ToArray(); } 

Descobri que, se uma das pastas pai em que eu estava salvando o arquivo tivesse um espaço à direita, o GDI + lançaria a exceção genérica.

Em outras palavras, se eu tentasse salvar em “C: \ Documents and Settings \ meuusuario \ Local Settings \ Temp \ ABC DEF M1 Trends Values ​​\ Images \ picture.png”, ele lançava a exceção genérica.

Meu nome de pasta estava sendo gerado a partir de um nome de arquivo que por acaso tinha um espaço à direita, então foi fácil .Trim () e seguir em frente.

Esta é uma expansão / qualificação da resposta de Fred, que afirmou: “GDI limita a altura de uma imagem para 65534”. Nós nos deparamos com essa questão com um de nossos aplicativos .NET e, depois de ver o post, nossa equipe de terceirização levantou as mãos para o ar e disse que não conseguiria resolver o problema sem grandes alterações.

Com base nos meus testes, é possível criar / manipular imagens com uma altura maior que 65534, mas o problema surge ao salvar em um stream ou arquivo em CERTO DE FORMATOS . No código a seguir, a chamada do método t.Save () lança ao nosso amigo a exceção genérica quando a altura do pixel é 65501 para mim. Por razões de curiosidade, repeti o teste para largura e o mesmo limite aplicado à gravação.

  for (int i = 65498; i < = 100000; i++) { using (Bitmap t = new Bitmap(800, i)) using (Graphics gBmp = Graphics.FromImage(t)) { Color green = Color.FromArgb(0x40, 0, 0xff, 0); using (Brush greenBrush = new SolidBrush(green)) { // draw a green rectangle to the bitmap in memory gBmp.FillRectangle(greenBrush, 0, 0, 799, i); if (File.Exists("c:\\temp\\i.jpg")) { File.Delete("c:\\temp\\i.jpg"); } t.Save("c:\\temp\\i.jpg", ImageFormat.Jpeg); } } GC.Collect(); } 

O mesmo erro também ocorre se você gravar em um stream de memory.

Para contornar isso, você pode repetir o código acima e replace ImageFormat.Tiff ou ImageFormat.Bmp por ImageFormat.Jpeg.

Isso vai até alturas / larguras de 100.000 para mim - eu não testei os limites. Acontece que o Tiff era uma opção viável para nós.

ESTEJA AVISADO

Os arquivos / streams TIFF de memory consomem mais memory do que suas contrapartes JPG.

Eu também recebi esse erro ao salvar JPEGs, mas apenas para certas imagens.

Meu código final:

  try { img.SaveJpeg(tmpFile, quality); // This is always successful for say image1.jpg, but always throws the GDI+ exception for image2.jpg } catch (Exception ex) { // Try HU's method: Convert it to a Bitmap first img = new Bitmap(img); img.SaveJpeg(tmpFile, quality); // This is always successful } 

Eu não criei as imagens, então não posso dizer qual é a diferença.
Eu apreciaria se alguém pudesse explicar isso.

Esta é a minha function SaveJpeg apenas FYI:

 private static void SaveJpeg(this Image img, string filename, int quality) { EncoderParameter qualityParam = new EncoderParameter(Encoder.Quality, (long)quality); ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg"); EncoderParameters encoderParams = new EncoderParameters(1); encoderParams.Param[0] = qualityParam; img.Save(filename, jpegCodec, encoderParams); } 

Apenas no caso de alguém estar fazendo coisas tão estúpidas quanto eu. 1. verifique se o caminho existe. 2. verifique se você tem permissions para escrever. 3. Verifique se o seu caminho está correto, no meu caso eu estava faltando o nome do arquivo no TargetPath 🙁

deveria ter dito, seu caminho é mais do que “Um erro genérico ocorreu em GDI +”

se o seu código é o seguinte, então este erro também ocorre

 private Image GetImage(byte[] byteArray) { using (var stream = new MemoryStream(byteArray)) { return Image.FromStream(stream); } } 

O correto é

 private Image GetImage(byte[] byteArray) { var stream = new MemoryStream(byteArray)) return Image.FromStream(stream); } 

Isso pode ser porque estamos retornando do bloco de uso

Teve um problema muito semelhante e também tentou clonar a imagem que não funciona. Descobri que a melhor solução foi criar um novo object Bitmap a partir da imagem que foi carregada do stream de memory. Dessa forma, o stream pode ser descartado, por exemplo

 using (var m = new MemoryStream()) { var img = new Bitmap(Image.FromStream(m)); return img; } 

Espero que isto ajude.

Resolvido – eu tive esse problema exato. A correção, para mim, era aumentar a cota de disco para IUSR no servidor IIS. Neste caso, temos um aplicativo de catálogo com imagens de itens e tal. A cota de upload para o “Usuário Anônimo da Web” foi definida como 100 MB, que é o padrão para os servidores IIS dessa empresa de hospedagem. Eu subi para 400MB e consegui fazer upload de imagens sem erro.

Isso pode não ser o seu problema, mas se for, é uma solução fácil.

Erro ocorrido por causa da permissão. Verifique se a pasta tem TODA A PERMISSÃO.

 public Image Base64ToImage(string base64String) { // Convert Base64 String to byte[] byte[] imageBytes = Convert.FromBase64String(base64String); MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length); // Convert byte[] to Image ms.Write(imageBytes, 0, imageBytes.Length); Image image = Image.FromStream(ms, true); return image; } img.Save("YOUR PATH TO SAVE IMAGE") 

No meu caso, o problema estava no caminho que eu estava salvando (a raiz C:\ ). Mudando para D:\111\ fez a exceção ir embora.

Outra causa para este erro – o caminho que você indica no método Save da instância do Bitmap não existe ou você não forneceu um caminho completo / válido.

Só tive esse erro porque eu estava passando em um nome de arquivo e não um caminho completo!

Acontece!

Minha vez!

 using (System.Drawing.Image img = Bitmap.FromFile(fileName)) { ... do some manipulation of img ... img.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg); } 

Peguei no .Save … porque o using () está mantendo o arquivo aberto, então não consigo sobrescrevê-lo. Talvez isso ajude alguém no futuro.

O mesmo problema que eu estava enfrentando. Mas no meu caso, eu estava tentando salvar o arquivo na unidade C e não estava acessível. Então eu tentei salvar na unidade D que estava totalmente acessível e consegui.

Então, primeiro verifique suas pastas em que você está tentando salvar. Você deve ter todos os direitos (ler e escrever) para essa pasta específica.

Eu noto que o seu caso “jpeg” é na verdade:

  default: format = ImageFormat.Jpeg; break; 

Tem certeza de que o formato é jpeg e não outra coisa?

Eu tentaria:

  case "image/jpg": // or "image/jpeg" ! format = ImageFormat.Jpeg; break; 

Ou verifique o que imageToConvert.MimeType() está realmente retornando.

ATUALIZAR

Existe alguma outra boot que você precisa fazer para o object MemoryStream?

Apenas para lançar outra solução possível na pilha, mencionarei o caso que encontrei com essa mensagem de erro. O método Bitmap.Save usaria essa exceção ao salvar um bitmap que eu havia transformado e estava exibindo. Eu descobri que não lançaria a exceção se a instrução tivesse um ponto de interrupção, nem se o Bitmap.Save fosse precedido por Thread.Sleep(500) então eu suponho que haja algum tipo de contenção de resources acontecendo.

Basta copiar a imagem para um novo object Bitmap para evitar que essa exceção apareça:

 new Bitmap(oldbitmap).Save(filename); 

Se você estiver tentando salvar uma imagem em um local remoto, não deixe de adicionar a conta de usuário NETWORK_SERVICE nas configurações de segurança e conceder a ele permissions de leitura e gravação. Caso contrário, não vai funcionar.

 byte[] bts = (byte[])page1.EnhMetaFileBits; using (var ms = new MemoryStream(bts)) { var image = System.Drawing.Image.FromStream(ms); System.Drawing.Image img = image.GetThumbnailImage(200, 260, null, IntPtr.Zero); img.Save(NewPath, System.Drawing.Imaging.ImageFormat.Png); } 

Eu também recebo este erro porque estou tentando salvar imagens com o mesmo nome de imagens salvas anteriormente.

Certifique-se de não salvar imagens com nome duplicado.

Use para isso por exemplo uma function ‘Aleatória’ ( Como funciona o gerador de números randoms do C #? ) Ou por exemplo, gerar um Guid ( http://betterexplained.com/articles/the-quick-guide-to-guids/ )

  • Eu tive esse problema em um servidor de teste, mas não no servidor ao vivo.
  • Eu estava escrevendo a imagem para um stream, então não era um problema de permissão.
  • Eu estava implantando diretamente alguns dos arquivos .dll para o servidor de teste.
  • A implantação de toda a solução resolveu o problema, portanto, provavelmente foi uma incompatibilidade de compilation estranha

tivemos o mesmo problema ao gerar um PDF no servidor de produção.

Recicle o pool de aplicativos para corrigir o problema.

Espero que isso ajude para alguém.

Para mim eu estava usando o Image.Save(Stream, ImageCodecInfo, EncoderParameters) e, aparentemente, isso estava causando o infame A generic error occurred in GDI+ erro A generic error occurred in GDI+ .

Eu estava tentando usar EncoderParameter para salvar os jpegs em 100% de qualidade. Isso funcionava perfeitamente na “minha máquina” (doh!) E não na produção.

Quando usei o Image.Save(Stream, ImageFormat) , o erro desapareceu! Então, como um idiota, continuei a usar o último, embora ele os salve na qualidade padrão, que eu presumo que seja de apenas 50%.

Espero que esta informação ajude alguém.

Eu também encontrei o problema. O problema foi devido ao stream de carregamento sendo descartado. Mas eu não dispensei, estava dentro do framework .Net. Tudo que eu tive que fazer foi usar:

 image_instance = Image.FromFile(file_name); 

ao invés de

 image_instance.Load(file_name); 

image_instance é do tipo System.Windows.Forms.PictureBox! PictureBox’s Load () descarta o stream que a imagem foi carregada, e eu não sabia disso.

Com base na resposta do @savindra, se você executar o RHM em seu aplicativo e tentar executá-lo como administrador , ele deverá resolver seu problema.

O meu parecia ser um problema de permissão.