Redimensionando uma imagem sem perder qualidade

Preciso resize uma imagem, mas a qualidade da imagem não pode ser afetada por isso.

Como o rcar diz, você não pode, sem perder alguma qualidade, o melhor que você pode fazer em c # é:

Bitmap newImage = new Bitmap(newWidth, newHeight); using (Graphics gr = Graphics.FromImage(newImage)) { gr.SmoothingMode = SmoothingMode.HighQuality; gr.InterpolationMode = InterpolationMode.HighQualityBicubic; gr.PixelOffsetMode = PixelOffsetMode.HighQuality; gr.DrawImage(srcImage, new Rectangle(0, 0, newWidth, newHeight)); } 

A menos que você esteja fazendo charts vetoriais, não há como resize uma imagem sem perder potencialmente alguma qualidade de imagem.

 private static Image resizeImage(Image imgToResize, Size size) { int sourceWidth = imgToResize.Width; int sourceHeight = imgToResize.Height; float nPercent = 0; float nPercentW = 0; float nPercentH = 0; nPercentW = ((float)size.Width / (float)sourceWidth); nPercentH = ((float)size.Height / (float)sourceHeight); if (nPercentH < nPercentW) nPercent = nPercentH; else nPercent = nPercentW; int destWidth = (int)(sourceWidth * nPercent); int destHeight = (int)(sourceHeight * nPercent); Bitmap b = new Bitmap(destWidth, destHeight); Graphics g = Graphics.FromImage((Image)b); g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(imgToResize, 0, 0, destWidth, destHeight); g.Dispose(); return (Image)b; } 

daqui

Eu acredito que o que você está procurando fazer é “Resize / Resample” suas imagens. Aqui está um bom site que fornece instruções e fornece uma class de utilitário (que eu também uso):

http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx

A menos que você redimensione, você não pode fazer isso com charts raster.

O que você pode fazer com boa filtragem e suavização é resize sem perder nenhuma qualidade perceptível .

Você também pode alterar os metadados de DPI da imagem (supondo que ela tenha algum), que manterá exatamente a mesma contagem de pixels, mas alterará o modo como os editores de imagem a imaginam em medições do “mundo real”.

E só para cobrir todas as bases, se você realmente quis dizer apenas o tamanho do arquivo da imagem e não as dimensões reais da imagem, sugiro que você olhe para uma codificação sem perdas dos dados da imagem. Minha sugestão para isso seria salvar novamente a imagem como um arquivo .png (eu costumo usar tinta como um transcodificador gratuito para imagens no Windows. Carregue a imagem na pintura, salve como no novo formato)

Você não pode resize uma imagem sem perder alguma qualidade, simplesmente porque está reduzindo o número de pixels.

Não reduza o tamanho do lado do cliente, porque os navegadores não fazem um bom trabalho de redimensionamento de imagens.

O que você pode fazer é alterar programaticamente o tamanho antes de renderizá-lo ou como um usuário faz o upload.

Aqui está um artigo que explica uma maneira de fazer isso em c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx

Veja se você gosta da qualidade de redimensionamento de imagem deste módulo ASP.NET de código aberto. Há uma demonstração ao vivo, então você pode mexer com isso sozinho. Ele produz resultados que são (para mim) impossíveis de distinguir da saída do Photoshop. Ele também tem tamanhos de arquivo semelhantes – o MS fez um bom trabalho em seu codificador JPEG.

Há algo lá fora, redimensionamento consciente do contexto, não sei se você será capaz de usá-lo, mas vale a pena olhar, com certeza

Uma boa demonstração em vídeo (Aumento aparece no meio) http://www.youtube.com/watch?v=vIFCV2spKtg

Aqui pode haver algum código. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/

Isso foi um exagero? Talvez existam alguns filtros fáceis que você pode aplicar a uma imagem ampliada para embaçar os pixels um pouco, você poderia olhar para isso.

Você está redimensionando maior ou menor? Por um pequeno% ou por um fator maior como 2x, 3x? O que você quer dizer com qualidade para sua aplicação? E que tipo de imagens – fotografias, desenhos de linhas rígidas ou o que? Escrevendo seu próprio código de moagem de pixel de baixo nível ou tentando fazê-lo tanto quanto possível com bibliotecas existentes (.net ou qualquer outro)?

Existe um grande conhecimento sobre esse assunto. O conceito chave é a interpolação.

Recomendações de navegação:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* para C #: https://secure.codeproject.com/KB/GDI-plus/imageprocessing4.aspx?display=PrintAll&fid=3657&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26&select=629945 * isso é específico do java, mas pode ser educacional – http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

Aqui você também pode adicionar códigos de marca d’água nesta class:

 public class ImageProcessor { public Bitmap Resize(Bitmap image, int newWidth, int newHeight, string message) { try { Bitmap newImage = new Bitmap(newWidth, Calculations(image.Width, image.Height, newWidth)); using (Graphics gr = Graphics.FromImage(newImage)) { gr.SmoothingMode = SmoothingMode.AntiAlias; gr.InterpolationMode = InterpolationMode.HighQualityBicubic; gr.PixelOffsetMode = PixelOffsetMode.HighQuality; gr.DrawImage(image, new Rectangle(0, 0, newImage.Width, newImage.Height)); var myBrush = new SolidBrush(Color.FromArgb(70, 205, 205, 205)); double diagonal = Math.Sqrt(newImage.Width * newImage.Width + newImage.Height * newImage.Height); Rectangle containerBox = new Rectangle(); containerBox.X = (int)(diagonal / 10); float messageLength = (float)(diagonal / message.Length * 1); containerBox.Y = -(int)(messageLength / 1.6); Font stringFont = new Font("verdana", messageLength); StringFormat sf = new StringFormat(); float slope = (float)(Math.Atan2(newImage.Height, newImage.Width) * 180 / Math.PI); gr.RotateTransform(slope); gr.DrawString(message, stringFont, myBrush, containerBox, sf); return newImage; } } catch (Exception exc) { throw exc; } } public int Calculations(decimal w1, decimal h1, int newWidth) { decimal height = 0; decimal ratio = 0; if (newWidth < w1) { ratio = w1 / newWidth; height = h1 / ratio; return height.To(); } if (w1 < newWidth) { ratio = newWidth / w1; height = h1 * ratio; return height.To(); } return height.To(); } } 

Aqui está um tópico do fórum que fornece uma amostra de código de redimensionamento de imagem C #. Você poderia usar um dos fichários da biblioteca GD para fazer a reamostragem em C #.