2010-12-11 20 views
15

Necesito comprimir o al menos disminuir la calidad de algunas imágenes png que los usuarios están cargando en mi sitio. Ya lo redimensioné pero eso no hace mucho por el tamaño de la imagen.C#: buscando algoritmo de compresión PNG/biblioteca

Buscando un algoritmo o biblioteca de compresión de png/pérdida de calidad o biblioteca para .net 4.0 o inferior.


Esta es la forma en la actualidad puedo guardar/convertir mis imágenes:

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

"para .net 4.0 o menos": lo siento, solo tengo uno para .NET 5.0;) –

+0

¿Cuál es su respuesta para .NET 5 por curiosidad? – Dylan

+0

Apuesto a que solo habrá algunos basados ​​en 4.5 :) –

Respuesta

22

Desafortunadamente, .NET (y GDI +, que las librerías gráficas de .NET se construyen sobre) no es compatible con ningún parámetro de codificación para PNG. De hecho, si llama a GetEncoderParameterList en su imagen con el codificador PNG Clsid, obtendrá una excepción "No implementado".

Aún más desafortunado es que ImageFormat e ImageCodecInfo son clases selladas y no se puede simplemente agregar nuevos códecs a lo que .NET puede acceder de forma nativa. Microsoft dejó caer la pelota en este caso.

Esto significa que sus alternativas son, en orden de masoquismo decreciente: 1) implementar una función de ahorrar en su cuenta en .NET que implementa RFC 2083, 2) Implementar una función de ahorro con sede fuera portar libpng a.NET, 3) Código de llamada no administrada que se creó directamente desde libpng

libpng tiene una gran documentación y es gratuito, tanto en disponibilidad como en permisividad de licencia.

+0

Gracias por la información. –

+0

+1 para llamar al código no administrado ... generalmente solo usa un procesador basado en consola. – Tracker1

+0

¿Qué hay de FreeImage? – jjxtra

7

PNG es generalmente un esquema compresión sin pérdidas, lo que significa que la calidad de imagen no se reduce a menos que reduzca el número de píxeles (tamaño) o profundidad de color. Hay tres formas de reducir el tamaño de archivo de las imágenes PNG:

  • Reduzca el número de píxeles (reduciendo la escala de la imagen); hay una evidente pérdida de la resolución aquí
  • Usando un diferentes filtros de precompresión/desinflado parámetros del compresor (OptiPNG es mi herramienta favorita para elegir automáticamente la mejor combinación de filtros/ajustes del compresor)
  • La reducción de la profundidad de color del color verdadero de 256 (o menos) de colores que darán ahorros sustanciales de bytes, pero por lo general a un gran costo visual (especialmente para las imágenes fotográficas)

parece que .NET no tiene una forma integrada de cambiar los filtros de precompresión o parámetros del compresor de PNG, por lo que deberá usar una biblioteca externa. OptiPNG o cualquiera de las other herramientas de optimización PNG no son bibliotecas .NET nativas, por lo que tendrá que ocuparse de P/Invocar las bibliotecas o ejecutar un proceso separado para procesar cada imagen. Sin embargo, a menudo observa ahorros de alrededor del 5% o menos (aunque he visto tanto como el 40%), ya que este es, en última instancia, un proceso sin pérdidas.

Recomendaría no reducir la profundidad de color en el escenario automatizado que describe, porque los resultados pueden parecer realmente horribles (piense en los GIF vacilantes de la antigüedad). (Sin embargo, si está realizando una optimización manual, consulte Color Quantizer en Windows y ImageAlpha en Mac.)

De manera realista, la mejor manera de reducir el tamaño del archivo a expensas de la calidad es simplemente convertir a JPEG, lo que requiere sin dependencias externas, y está diseñado para ser un algoritmo de compresión con pérdida:

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

Esto no es exactamente cierto. PNG implementa un concepto de filtros de compresión que se utilizan para reducir el tamaño de la imagen sin perder la calidad. No garantiza nada, pero en algunas situaciones la mejora podría ser bastante significativa. Puede leer sobre esto aquí: http://www.libpng.org/pub/png/pngintro.html – detunized

+0

Pero estoy de acuerdo con josh3736, la manera más fácil y más confiable sería ir con JPEG. – detunized

+0

@detunized: Sí, pero los filtros de compresión pueden no implementar compresión con pérdida, que es lo que @Shawn realmente está pidiendo. De todos modos, cualquier archivo PNG subido por sus usuarios necesariamente ya habrá aplicado filtros de compresión, por lo que no es posible reducir aún más el tamaño del archivo. – josh3736

0

Desafortunadamente, el procesador de imágenes de .Net para png no realizará ninguna heurística de optimización en la salida. Su mejor opción es tener un binario optipng/pngcrush disponible en el servidor, renderizar el resultado redimensionado a un archivo temporal, y luego usar pngcrush en él a través de System.Diagnostics.Process.

En su mayor parte, si las cargas son fotografías y el formato original es JPEG, será mejor si utiliza la salida JPEG.

Cuestiones relacionadas