Isto parece ser um erro um pouco infame em toda a web. Tanto que não consegui encontrar uma resposta para o meu problema como o meu cenário não encaixa't. Uma exceção é lançada quando eu salvo a imagem para o fluxo.
Estranhamente, isto funciona perfeitamente com um png mas dá o erro acima com jpg e gif, o que é bastante confuso.
A maioria dos problemas similares por aí relaciona-se com salvar imagens em arquivos sem permissões. Ironicamente a solução é usar um fluxo de memória 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 excepção. A razão pela qual isto 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.<InvokeActionMethodWithFilters>b__7()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
InnerException:
OK coisas que eu tentei até agora.
OK, parece que eu encontrei a causa apenas por pura sorte e não há nada de errado com esse método em particular, ele'é mais uma vez mais um back up na pilha de chamadas.
Antes eu redimensiono a imagem e como parte desse método devolvo o objeto redimensionado da seguinte forma. Eu inseri duas chamadas para o método acima e uma gravação direta 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 fluxo de memória em que o objeto foi criado em tem para ser aberto no momento em que o objeto é salvo. Não tenho a certeza porque é que isto acontece. Será alguém capaz de me iluminar e como eu posso contornar isto.
Eu só volto de um fluxo porque depois de usar o código de redimensionamento semelhante a isto o arquivo de destino tem um tipo mime desconhecido (img.RawFormat.Guid) e Id como o tipo Mime para ser correto em todos os objetos de imagem, pois torna difícil escrever código de manipulação genérico de outra forma.
**EDIT***
Isto não'não apareceu na minha pesquisa inicial mas aqui's a resposta de Jon Skeet
Teve um problema muito semelhante e também tentou clonar a imagem que não't funciona. Descobri que a melhor solução era criar um novo objeto Bitmap a partir da imagem que era carregada a partir do fluxo de memória. Dessa forma, o fluxo pode ser descartado, por exemplo
using (var m = new MemoryStream())
{
var img = new Bitmap(Image.FromStream(m));
return img;
}
Espero que isto ajude.
Reparei que o seu "jpeg" caso é realmente:
default:
format = ImageFormat.Jpeg;
break;
Tens a certeza que o formato é jpeg e não outra coisa qualquer?
I' tentaria:
case "image/jpg": // or "image/jpeg" !
format = ImageFormat.Jpeg;
break;
Ou verifique o que imageToConvert.MimeType()
está realmente retornando.
**UPDATE***
Há alguma outra inicialização que você precisa fazer com o objeto MemoryStream?