Criar uma nova imagem no sistema de arquivos de System.Drawing.Image?
-
22-07-2019 - |
Pergunta
Ok, me desculpe, esta é provavelmente uma questão de noob, mas eu estou meio preso.
Então, o que estou fazendo (no meu aplicativo asp.net) está carregando uma imagem do sistema de arquivos:
System.Drawing.Image tempImage;
tempImage = System.Drawing.Image.FromFile(HttpContext.Server.MapPath(originalPath));
Então eu fazer alguma redimensionamento:
tempImage = my awesomeResizingFunction(tempImage, newSize);
e pretende guardá-lo para o sistema de arquivos em outro local usando o seguinte:
string newPath = "/myAwesomePath/newImageName.jpg";
tempImage.Save(newPath);
eo que eu vejo é este erro:
"A generic error occurred in GDI+."
Eu sei que a imagem é "ok" porque eu posso escrevê-lo para o navegador e ver a imagem redimensionada, eu só recebo o erro ao tentar salvá-lo. Eu estou meio novo e preso, estou fazendo isso totalmente errado? (Bem, eu acho que é óbvio, mas você sabe o que quero dizer ...)
Solução
plz tente este código ... Eu tenho usado o mesmo código para redimensionar imagem e poupança. se tiver qualquer problema, então plz me avise.
System.Drawing.Bitmap bmpOut = new System.Drawing.Bitmap(NewWidth, NewHeight);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmpOut);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.FillRectangle(System.Drawing.Brushes.White, 0, 0, NewWidth, NewHeight);
g.DrawImage(new System.Drawing.Bitmap(fupProduct.PostedFile.InputStream), 0, 0, NewWidth, NewHeight);
MemoryStream stream = new MemoryStream();
switch (fupProduct.FileName.Substring(fupProduct.FileName.IndexOf('.') + 1).ToLower())
{
case "jpg":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case "jpeg":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
break;
case "tiff":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Tiff);
break;
case "png":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
break;
case "gif":
bmpOut.Save(stream, System.Drawing.Imaging.ImageFormat.Gif);
break;
}
String saveImagePath = Server.MapPath("../") + "Images/Thumbnail/" + fupProduct.FileName.Substring(fupProduct.FileName.IndexOf('.'));
bmpOut.Save(saveImagePath);
onde fupProduct é o controle fileupload ID
Outras dicas
Você tem certeza que o OriginalPath e ponto newpath a diferentes arquivos? Quando você usa Image.FromFile, os restos de arquivo bloqueado até que você chamar Dispose sobre a imagem, que pode levar a exceção que você mencionou. Você poderia carregar a imagem como aquela vez:
Image tempImage = null;
using (FileStream fs = new FileStream(originalPath, FileMode.Open, FileAccess.Read))
{
tempImage = Image.FromStream(fs);
}
...
Esta abordagem garante que o arquivo é fechado no final do bloco usando
É possível o fluxo original apoiando a imagem original foi fechado? Se o fluxo atrás de um Bitmap foi fechado, você começar a receber erros GDI +. Corri para este muito quando adicionamos processamento de imagem para o nosso site.
Se você abrir o objeto Bitmap no depurador Visual Studio, você vê exceções em vez dos valores das propriedades? Se assim for, não é um problema com a operação de salvamento, mas a camada GDI + perdeu a capacidade de processar o objeto, período.
O que descobri foi que eu precisava para manter o controle dos MemoryStreams pertencentes aos meus mapas de bits e mantê-los todos juntos. Redimensionar uma imagem resultou em uma nova MemoryStream uma nova imagem de bitmap.
I acabou criando esta classe simples (aparadas algumas propriedades extras desnecessários aqui):
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;
}
}
Agora, eu estava lidando com imagens enviadas ao nosso site, eo que eu encontrei foi que, quando Asp.Net reciclados o fluxo anexado ao pedido, todas as operações de imagem súbitas começou pirando. Então, a minha solução, se esta era a melhor maneira de fazê-lo ou não, era para copiar os dados do fluxo de upload para o meu próprio MemoryStream, carregar a imagem daquele, e ficar tanto neste recipiente. E onde quer que eu criei uma nova imagem a partir de um velho, eu sempre mantive o fluxo ea imagem juntos.
Espero que isso ajude.
EDIT: Eu também estou interessado em ver como você está fazendo o redimensionamento da imagem. Este é um trecho de como eu fiz nosso:
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;