2009-07-27 15 views
6

Estoy intentando admitir imágenes JPEG giratorias desde ASP.NET MVC (en incrementos de 90 grados). Estoy intentando usar System.Drawing (GDI +), sin embargo, estoy teniendo problemas.Rotar archivos JPEG en .NET con pérdida mínima de calidad

He intentado usar Image.RotateFlip que puede girar la imagen pero causa una pérdida de calidad. Incluso con una calidad de encoder de 100, todavía hay artefactos visibles en la imagen girada que no estaban en la imagen original ni se muestran cuando la giro usando otros programas (Gimp, etc.).

using (Image image = Image.FromFile("C:\\source.jpg")) { 
    ImageFormat sourceFormat = image.RawFormat; 
    image.RotateFlip(RotateFlipType.Rotate90FlipNone); 
    EncoderParameters encoderParams = null; 
    try { 
     if (sourceFormat == ImageFormat.Jpeg) { 
      encoderParams = new EncoderParameters(1); 
      encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 
     } 
     image.Save("C:\\target.jpg", GetEncoder(sourceFormat), encoderParams); 
    } finally { 
     if (encoderParams != null) 
      encoderParams.Dispose(); 
    } 
} 

He encontrado un artículo en transforming a JPEG without loss of information. Usando Encoder.Transformation parece ser una opción en .NET - sin embargo, no puede llegar a causar cualquiera de mis imágenes JPEG de prueba para girar en absoluto, si las dimensiones son un múltiplo de 16.

using (Image image = Image.FromFile("C:\\source.jpg")) { 
    ImageFormat sourceFormat = image.RawFormat; 
    EncoderParameters encoderParams = null; 
    try { 
     if (sourceFormat == ImageFormat.Jpeg) { 
      encoderParams = new EncoderParameters(1); 
      encoderParams.Param[0] = new EncoderParameter(Encoder.Transformation, 
       (long)EncoderValue.TransformRotate90); 
     } 
     image.Save("C:\\target.jpg", GetEncoder(sourceFormat), encoderParams); 
    } finally { 
     if (encoderParams != null) 
      encoderParams.Dispose(); 
    } 
} 

¿Alguien sabe ¿Cómo rotar con éxito un JPEG en .NET en incrementos de 90 grados con una pérdida de calidad mínima o nula utilizando cualquiera de los métodos anteriores u otro método? Gracias.

Además, aquí es mi implementación de GetEncoder:

private ImageCodecInfo GetEncoder(ImageFormat format) { 
    foreach (var info in ImageCodecInfo.GetImageEncoders()) 
     if (info.FormatID == format.Guid) 
      return info; 
    return null; 
} 

Editar:

He actualizado el código anterior para adaptarse mejor a mi código real. El error estaba en la línea siguiente:

if (sourceFormat == ImageFormat.Jpeg) { 

Debería haber sido:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) { 
+2

Tu código funciona para mí ... ¿estás seguro de que se devuelve un ImageCodecInfo para tus datos? –

+0

Gracias @pb, estaba obteniendo un ImageCodecInfo pero no un encoderParams porque mi código real tenía una comprobación adicional antes de configurarlo que tenía un error. –

Respuesta

1

Gracias por confirmar que mi código publicado trabajó. Esto me ayudó a aislar mi problema. Me siento estúpido ahora. Mi código real tenía un cheque de formato de imagen antes de encoderParams - pero tenía un error:

if (sourceFormat == ImageFormat.Jpeg) { 
    // set encoderParams here 

descubrí el condicional anterior era falsa por lo que no siempre se estaba estableciendo encoderParams. La solución fue simple:

if (sourceFormat.Guid == ImageFormat.Jpeg.Guid) { 
2

Con cualquier método que descomprime la imagen, lo gira y lo comprime, se obtiene una pérdida de calidad.

El formato JPEG comprime información de color en cuadrados de 2x2 píxeles obteniendo un color promedio para representar los cuatro píxeles, por lo que si el ancho y la altura de la imagen son divisibles por dos perderá menos calidad ya que la mayoría de la información la compresión es información que fue interpolada en la descompresión.

Del mismo modo, la información de brillo se comprime en cuadrados de 8x8 píxeles, por lo que si su ancho y altura son divisibles por ocho, la cuadrícula se alineará después de girar la imagen y perderá menos información real.

Para realizar una rotación sin pérdida, debe utilizar un método completamente diferente, leer el archivo JPEG y reorganizar y rotar cada cuadrado de información para que forme la imagen girada sin descomprimirla ni recomprimirla.

Cuestiones relacionadas