Redimensionner une image sans perte de qualité [fermé]

108

Comment puis-je redimensionner une image sans affecter la qualité de l'image?

public statique
la source
Pouvez-vous nous donner plus de détails? Quelle est la taille de vos images et quelle taille avez-vous besoin qu'elles soient?
Mark Ransom
6
imageresizing.net - Cette bibliothèque produit les images de la plus haute qualité que vous puissiez obtenir avec .NET
Lilith River

Réponses:

217

Comme le dit rcar , vous ne pouvez pas sans perdre de la qualité, le mieux que vous puissiez faire en c # est:

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));
}
Kris Erickson
la source
2
Je pourrais ajouter que (si possible) l'utilisateur doit commencer avec une image Bitmap qui est, par exemple, deux fois plus grande que nécessaire, puis réduire la taille. L'image résultante doit être assez lisse.
Pretzel
2
gr.SmoothingMode = SmoothingMode.HighQuality est un meilleur code. Actuellement, HighQuality et AntiAlias ​​sont la même chose, mais peut-être que dans le futur, Microsoft inventera quelque chose de nouveau. HighQuality doit toujours être un alias pour le meilleur.
Eyal
4
La méthode «System.Drawing.Image.Save (string filename, ImageFormat format)» enregistre les JPG avec une qualité 75. L'image était floue et inacceptable par le client. Ce qui a résolu le problème de qualité était d'utiliser Save (nom de fichier de chaîne, encodeur ImageCodecInfo, EncoderParameters encoderParams) à la place et de spécifier une valeur de qualité plus proche de 100.
Riga
3
Cela laisse parfois des artefacts sur le bord de l'image ...
jjxtra
1
J'avais des artefacts à la frontière en utilisant cela. Des suggestions?
Gopichandar
32

Sauf si vous faites des graphiques vectoriels, il n'y a aucun moyen de redimensionner une image sans potentiellement perdre une certaine qualité d'image.

Excité
la source
1
sauf si vous l'étendez ...
Blair Conrad
Vous pouvez l'étendre sans perdre d'informations, mais il existe différents types de filtres que vous pouvez utiliser qui donnent des résultats différents - maintien d'ordre zéro, passe-bas, etc.
Adam Rosenfield
24
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;
}

d' ici

ozba
la source
Cela fonctionne, mais renvoie une qualité identique à la réponse de Kris Erickso. Nice to see Size used cependant ...
Sam Jones
3

Sauf si vous redimensionnez, vous ne pouvez pas le faire avec des graphiques raster.

Ce que vous pouvez faire avec un bon filtrage et un bon lissage est de redimensionner sans perdre aucune qualité notable .

Vous pouvez également modifier les métadonnées DPI de l'image (en supposant qu'elle en possède) qui conserveront exactement le même nombre de pixels, mais modifieront la façon dont les éditeurs d'images la perçoivent dans des mesures «réelles».

Et juste pour couvrir toutes les bases, si vous ne parliez vraiment que de la taille de fichier de l'image et non des dimensions réelles de l'image, je vous suggère de regarder un encodage sans perte des données d'image. Ma suggestion pour cela serait de réenregistrer l'image sous forme de fichier .png (j'ai tendance à utiliser Paint comme transcodeur gratuit pour les images dans Windows. Charger l'image dans Paint, enregistrer sous le nouveau format)

workmad3
la source
3

Vous ne pouvez pas redimensionner une image sans perdre de la qualité, simplement parce que vous réduisez le nombre de pixels.

Ne réduisez pas la taille côté client, car les navigateurs ne font pas un bon travail de redimensionnement des images.

Ce que vous pouvez faire est de modifier la taille par programme avant de le rendre ou au fur et à mesure qu'un utilisateur la télécharge.

Voici un article qui explique une façon de faire cela en c #: http://www.codeproject.com/KB/GDI-plus/imageresize.aspx

AaronS
la source
«les navigateurs ne font pas un bon travail de redimensionnement des images» - cela aurait pu être vrai en 2008, mais heureusement, nous sommes maintenant loin dans ce domaine (en grande partie à cause de la disparition progressive des anciennes versions d'IE).
Camilo Martin
2

Voyez si vous aimez la qualité de redimensionnement d'image de ce module ASP.NET open source. Il y a une démo en direct, vous pouvez donc jouer avec vous-même. Cela donne des résultats qui sont (pour moi) impossibles à distinguer de la sortie Photoshop. Il a également des tailles de fichier similaires - MS a fait du bon travail sur son encodeur JPEG.


la source
Eh bien, JPEG est un format relativement simple. Vous ne pouvez pas faire grand-chose pour battre les implémentations de référence en termes de qualité / taille de fichier car à la fin, il ne s'agit que de coefficients DCT avec une compression générique.
Camilo Martin
1

Il y a quelque chose là-bas, le redimensionnement sensible au contexte, je ne sais pas si vous pourrez l'utiliser, mais cela vaut la peine d'être examiné, c'est sûr

Une belle démo vidéo (l'agrandissement apparaît vers le milieu) http://www.youtube.com/watch?v=vIFCV2spKtg

Ici, il pourrait y avoir du code. http://www.semanticmetadata.net/2007/08/30/content-aware-image-resizing-gpl-implementation/

Était-ce exagéré? Peut-être qu'il existe des filtres simples que vous pouvez appliquer à une image agrandie pour brouiller un peu les pixels, vous pouvez vous pencher là-dessus.

Victor
la source
Je soupçonne que cela n'a rien à voir avec la question initiale, mais j'adore cette technique.
Matt Cruikshank
1

Redimensionnez-vous plus ou moins? Par un petit% ou par un facteur plus grand comme 2x, 3x? Qu'entendez-vous par qualité pour votre application? Et quel type d'images - des photographies, des dessins au trait dur ou quoi? Écrire votre propre code de broyage de pixels de bas niveau ou essayer de le faire autant que possible avec des bibliothèques existantes (.net ou autre)?

Il existe un vaste corpus de connaissances sur ce sujet. Le concept clé est l'interpolation.

Recommandations de navigation:
* http://www.all-in-one.ee/~dersch/interpolator/interpolator.html
* http://www.cambridgeincolour.com/tutorials/image-interpolation.htm
* pour 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 * ceci est spécifique à Java mais peut être éducatif - http: //today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html

DarenW
la source
1

Ici vous pouvez trouver également ajouter des codes de filigrane dans cette 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>();
        }

    }
cagin
la source