Comment puis-je obtenir de meilleurs résultats lorsque l’on réduit une image

Je redimensionne les images en c # et j’ai comparé mes méthodes à la meilleure méthode de Photoshop cs5.

Dans PS, j’utilise bicubic plus nette, qui a l’air vraiment bien. Cependant, lorsque j’essaie de faire de même en c #, je n’obtiens pas des résultats de qualité supérieure. J’ai essayé l’interpolation bicubique ainsi que HQ bicubic, mode de lissage HQ / None / AA. Dans les modes de composition, j’ai essayé environ 50 variations différentes et chacune d’elles apparaît assez proche de l’image de droite.

Vous remarquerez la pixellisation sur son dos et autour du titre, ainsi que le nom de l’auteur qui ne sort pas trop bien.

(À gauche, PS, à droite, c #.)

entrez la description de l'image ici

Il semble que c # bicubic effectue trop de lissage, même avec un lissage réglé à néant. J’ai joué avec de nombreuses variantes du code suivant:

g.CompositingQuality = CompositingQuality.HighQuality; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.PixelOffsetMode = PixelOffsetMode.None; g.SmoothingMode = SmoothingMode.None; 

Edit: Comme demandé, voici l’image de départ (1mb). entrez la description de l'image ici

Peut-être me manque quelque chose, mais j’ai généralement utilisé le code suivant ci-dessous pour redimensionner / compresser des images JPEG. Personnellement, je pense que le résultat s’est assez bien basé sur votre image source. Le code ne traite pas quelques cas extrêmes concernant les parameters d’entrée, mais globalement, le travail est effectué (j’ai d’autres méthodes d’extension pour le rognage et la combinaison de transformations d’image si vous le souhaitez).

Image redimensionnée à 25% de la taille d’origine et avec une compression de 90%. (~ 30 Ko de fichier de sortie)

SampleImage

Méthodes d’extension de la mise à l’échelle de l’image:

 public static Image Resize(this Image image, Single scale) { if (image == null) return null; scale = Math.Max(0.0F, scale); Int32 scaledWidth = Convert.ToInt32(image.Width * scale); Int32 scaledHeight = Convert.ToInt32(image.Height * scale); return image.Resize(new Size(scaledWidth, scaledHeight)); } public static Image Resize(this Image image, Size size) { if (image == null || size.IsEmpty) return null; var resizedImage = new Bitmap(size.Width, size.Height, image.PixelFormat); resizedImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); using (var g = Graphics.FromImage(resizedImage)) { var location = new Point(0, 0); g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(image, new Rectangle(location, size), new Rectangle(location, image.Size), GraphicsUnit.Pixel); } return resizedImage; } 

Méthode d’extension de compression:

 public static Image Compress(this Image image, Int32 quality) { if (image == null) return null; quality = Math.Max(0, Math.Min(100, quality)); using (var encoderParameters = new EncoderParameters(1)) { var imageCodecInfo = ImageCodecInfo.GetImageEncoders().First(encoder => Ssortingng.Compare(encoder.MimeType, "image/jpeg", SsortingngComparison.OrdinalIgnoreCase) == 0); var memoryStream = new MemoryStream(); encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, Convert.ToInt64(quality)); image.Save(memoryStream, imageCodecInfo, encoderParameters); return Image.FromStream(memoryStream); } } 

Usage:

  using(var source = Image.FromFile(@"C:\~\Source.jpg")) using(var resized = source.Resize(0.25F)) using(var compressed = resized.Compress(90)) compressed.Save(@"C:\~\Output.jpg"); 

REMARQUE: vous ne pouvez pas supprimer le MemoryStream créé dans la méthode Compress avant que l’image ne soit supprimée. Si vous réfléchissez à l’implémentation de Dispose sur MemoryStream, il est en fait sauvegardé pour ne pas appeler explicitement dispose. La seule alternative serait d’envelopper le stream image / mémoire dans une implémentation personnalisée d’une classe qui implémente Image / IDisposable.

En regardant la quantité d’ artefacts JPEG , en particulier en haut de l’image, je pense que vous définissez la compression jpg sur élevée. Cela se traduit par un fichier plus petit (taille de fichier), mais réduit la qualité de l’image et semble append davantage de flou.

Pouvez-vous essayer de le sauvegarder dans une qualité supérieure? Je suppose que la ligne contenant CompositingQuality.HighQuality fait déjà, mais vous pouvez peut-être trouver un mode de qualité encore plus élevé. Quelles sont les différences de taille de fichier entre Photoshop et C #? Et comment l’image Photoshop a-t-elle l’air après que vous l’ayez sauvegardée et rouverte? Le simple redimensionnement dans Photoshop n’introduit aucune perte de données jpg. Vous ne remarquerez cela qu’après avoir enregistré l’image au format jpg, puis l’avoir refermée et rouverte.

Je suis tombé sur cette question.

J’ai utilisé ce code pour ne pas utiliser de compression du jpeg et il sort comme la version PS:

 ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); ImageCodecInfo ici = null; foreach (ImageCodecInfo codec in codecs) { if (codec.MimeType == "image/jpeg") ici = codec; } EncoderParameters ep = new EncoderParameters(); ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)100);