Como posso redimensionar uma imagem, sem afetar a qualidade da imagem?
Como posso redimensionar uma imagem, sem afetar a qualidade da imagem?
Respostas:
Como diz o rcar , 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 gráficos vetoriais, não há como redimensionar uma imagem sem potencialmente perder parte da qualidade da 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;
}
Acredito que o que você quer fazer é "redimensionar / reamostrar" suas imagens. Aqui está um bom site que dá instruções e fornece uma classe de utilitário (que também uso):
http://www.codeproject.com/KB/GDI-plus/imgresizoutperfgdiplus.aspx
A menos que você redimensione, você não pode fazer isso com gráficos raster.
O que você pode fazer com uma boa filtragem e suavização é redimensionar sem perder nenhuma qualidade perceptível .
Você também pode alterar os metadados de DPI da imagem (supondo que haja alguns), que manterão exatamente a mesma contagem de pixels, mas alterarão a forma como os editores de imagem pensam sobre isso nas medições do 'mundo real'.
E apenas 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 tendo a usar o paint como um transcodificador gratuito para imagens em janelas. Carregue a imagem no paint, salve como no novo formato)
Você não pode redimensionar uma imagem sem perder alguma qualidade, simplesmente porque você 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 conforme um usuário o carrega.
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, para que você mesmo possa mexer nela. 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 - a MS fez um bom trabalho em seu codificador JPEG.
Tem algo lá fora, redimensionamento sensível ao contexto, não sei se você vai conseguir usar, mas vale a pena dar uma olhada, com certeza
Um bom vídeo de demonstração (a ampliação 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 desfocar um pouco os pixels, você pode dar uma olhada nisso.
Você está redimensionando para maior ou menor? Por uma pequena% 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 bem definidas ou o quê? Escrever seu próprio código de moagem de pixel de baixo nível ou tentar fazer isso o máximo possível com as bibliotecas existentes (.net ou qualquer outra)?
Existe um grande conhecimento sobre este 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
* isto é específico para 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 classe:
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<int>();
}
if (w1 < newWidth)
{
ratio = newWidth / w1;
height = h1 * ratio;
return height.To<int>();
}
return height.To<int>();
}
}
Aqui está um tópico de fórum que fornece um exemplo de código de redimensionamento de imagem C #. Você pode usar um dos fichários da biblioteca GD para fazer a reamostragem em C #.