2010-12-11 50 views
15

Je dois compresser ou au moins réduire la qualité de certaines images png que les utilisateurs téléchargent sur mon site. Je l'ai déjà redimensionné mais ça ne fait pas grand chose pour la taille de l'image.C#: Recherche d'algorithme/bibliothèque de compression PNG

Recherche d'un algorithme ou d'une bibliothèque de compression ou de perte de qualité png/image pour .net 4.0 ou inférieur.


Voilà comment j'enregistrons actuellement/convertir mes images:

Image mainImg = ImageHelper.ResizeImage(bmp, 600, 500, false); 
mainImg.Save(filePath, System.Drawing.Imaging.ImageFormat.Png); 
+2

"pour .net 4.0 ou sous": désolé, j'en ai seulement un pour .NET 5.0;) –

+0

Quelle est votre réponse pour .NET 5 par curiosité? – Dylan

+0

Je parie qu'il y en aura sur la seule base de la version 4.5 :) –

Répondre

22

Malheureusement, .NET (et GDI +, que les graphiques .NET bibliothèques sont construites sur) ne prend pas en charge les paramètres de codage pour PNG. En fait, si vous appelez GetEncoderParameterList sur votre image avec l'encodeur PNG Clsid, vous obtiendrez une exception "Non implémenté".

Encore plus regrettable est que ImageFormat et ImageCodecInfo sont des classes scellées et vous ne pouvez pas simplement ajouter de nouveaux codecs à ce que .NET peut accéder nativement. Microsoft a laissé tomber la balle sur celui-ci.

Cela signifie que vos alternatives sont, par ordre décroissant de masochisme: 1) Mettre en oeuvre une fonction de sauvegarde sur votre propre dans .NET qui implémente RFC 2083, 2) Mettre en place un portage fonction de sauvegarde en fonction de libpng à.NET, 3) Appelez le code non managé qui a été construit à partir de libpng directement

libpng a une grande documentation et est libre, à la fois dans la disponibilité et la permissivité de licence.

+0

Merci pour la perspicacité. –

+0

+1 pour appeler le code non géré ... utilisez généralement un processeur basé sur une console. – Tracker1

+0

Qu'en est-il de FreeImage? – jjxtra

7

PNG est généralement un système de compression sans perte, ce qui signifie que la qualité d'image ne se réduit jamais à moins que vous réduisez le nombre de pixels (taille) ou la profondeur de couleur. Il existe trois façons de réduire la taille de fichier des images PNG:

  • Réduisez le nombre de pixels (en réduisant la taille de l'image); il y a une perte évidente de la résolution ici
  • En utilisant un paramètre de compression filtres de précompression différents/dégonflage (OptiPNG est mon outil préféré choisir automatiquement la meilleure combinaison de filtres/paramètres de compression)
  • Réduire la profondeur de couleur de la vraie couleur à 256 (ou moins) les couleurs vous donneront des économies substantielles d'octets, mais habituellement à un coût visuel élevé (en particulier pour les images photographiques)

Il semble que .NET ne dispose pas d'un moyen intégré pour changer les filtres de précompression ou les paramètres du compresseur. de PNG, vous devrez donc utiliser une bibliothèque externe. OptiPNG ou l'un des outils d'optimisation PNG other ne sont pas des bibliothèques .NET natives, vous devrez donc faire appel à P/Appeler les bibliothèques ou exécuter un processus séparé pour traiter chaque image. Cependant, vous envisagez souvent des économies d'environ 5% ou moins (bien que j'en ai vu jusqu'à 40%), car il s'agit en définitive d'un processus sans perte.

Je recommanderais de ne pas réduire la profondeur de couleur dans le scénario automatisé que vous décrivez, car les résultats peuvent sembler vraiment horribles (pensez aux GIF tramés d'antan). (Cependant, si vous faites l'optimisation manuelle, regardez Color Quantizer sur Windows et ImageAlpha sur Mac.)

De manière réaliste, la meilleure façon de réduire la taille des fichiers au détriment de la qualité est de simplement convertir en JPEG, ce qui nécessite aucune dépendance externe, et est conçu pour être un algorithme de compression avec perte:

mainImg.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg); // make sure you change `filePath` to end with jpg instead of png. 
+0

Ce n'est pas tout à fait vrai. PNG implémente un concept de filtres de compression qui sont utilisés pour réduire la taille de l'image sans perdre la qualité. Cela ne garantit rien, mais dans certaines situations, l'amélioration pourrait être assez importante. Vous pouvez lire à ce sujet ici: http://www.libpng.org/pub/pngintro.html – detunized

+0

Mais je suis d'accord avec josh3736, le moyen le plus simple et le plus fiable serait d'utiliser JPEG. – detunized

+0

@detunized: Oui, mais les filtres de compression ne peuvent pas implémenter une compression avec perte, ce que demande vraiment @Shawn. Quoi qu'il en soit, tout fichier PNG importé par ses utilisateurs devra nécessairement avoir déjà des filtres de compression appliqués, il n'est donc pas possible de réduire davantage la taille du fichier. – josh3736

0

Malheureusement, le processeur d'image de .Net pour png ne fera aucune heuristique d'optimisation sur la sortie. Votre meilleur pari est d'avoir un binaire optipng/pngcrush disponible sur le serveur, de rendre la sortie redimensionnée dans un fichier temporaire, puis d'utiliser pngcrush dessus via un System.Diagnostics.Process. Dans la plupart des cas, si les images téléchargées sont des photographies et que le format d'origine est JPEG, il est préférable d'utiliser la sortie JPEG.