ti-enxame.com

Redimensionando uma imagem sem perder qualidade

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

103
public static

Como 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));
}
210
Kris Erickson

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

32
Randy
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;
}

de aqui

23
ozba

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

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

5
Ashlocke

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

Não reduza o tamanho do cliente, porque os navegadores não fazem um bom trabalho ao redimensionar 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

3
AaronS

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

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

Você também pode alterar os metadados de DPI da imagem (supondo que ela tenha alguns), o que manterá exatamente a mesma contagem de pixels, mas alterará o modo como os editores de imagens a visualizam 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 da imagem real, 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 o Paint como um transcodificador gratuito para imagens no Windows. Carregue a imagem no Paint, salve como no novo formato)

3
workmad3

Veja se você gosta do qualidade de redimensionamento de imagem deste módulo ASP.NET de código aberto. Há uma demonstração ao vivo, para que você possa mexer com ele mesmo. 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.

2
Nathanael Jones

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 borrar um pouco os pixels, você pode olhar para isso.

1
Victor

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>();
        }

    }
1
cagin

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 com arestas duras ou o quê? 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

1
DarenW

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

0
jimg