2009-12-11 15 views
18

Lo que sucede (solo perceptible en ciertas imágenes) es que veré un borde blanco de 1 píxel que se inserta en un píxel. Parece suceder en áreas que son claras pero no blancas (por ejemplo, el cielo). Es similar a cuando algo está sobreajustado y se puede ver un borde fantasma al lado de bordes de alto contraste.Ghost-borders ('ringing') al redimensionar en GDI +

Aquí está el código de reproducción que lo reproduce perfectamente. Estoy usando todos los ajustes de mayor calidad para escalar.

ImageCodecInfo encoder = null; 
EncoderParameters encoderParams = null; 

foreach (ImageCodecInfo codec in ImageCodecInfo.GetImageEncoders()) 
{ 
    if (codec.MimeType == "image/jpeg") 
    { 
     encoder = codec; 

     // use highest quality compression settings 
     encoderParams = new EncoderParameters(1); 
     encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L); 
     break; 
    } 
} 

using (Bitmap input = (Bitmap)Bitmap.FromFile(inputPath, true)) 
{ 
    // shrink by multiple of 2 
    Rectangle rect = new Rectangle(0, 0, input.Width/32, input.Height/32); 

    using (Bitmap output = new Bitmap(rect.Width, rect.Height)) 
    { 
     using (Graphics g = Graphics.FromImage(output)) 
     { 
      // use highest quality settings (updated per Mark Ransom's answer) 
      g.CompositingMode = CompositingMode.SourceCopy; 
      g.InterpolationMode = InterpolationMode.HighQualityBicubic; 
      g.PixelOffsetMode = PixelOffsetMode.HighQuality; 
      g.SmoothingMode = SmoothingMode.HighQuality; 

      g.DrawImage(input, rect); 
     } 

     output.Save(outputPath, encoder, encoderParams); 
    } 
} 

¿Alguna idea? Estoy completamente desconcertado. He leído un montón de preguntas/respuestas y ninguna de ellas parece afectar mi situación.


Editar:

Este es un ejemplo antes imagen: http://img14.imageshack.us/img14/4174/mg1647.jpg

Este es un ejemplo después de imagen: http://img64.imageshack.us/img64/3156/afterringing.jpg

Es más pronunciado con el original archivos (antes de que el servicio de alojamiento los "optimice"), pero puede ver en e cielo una banda más clara de un píxel en la imagen más pequeña.

+0

He leído su descripción con un poco más de cuidado, y lo que está describiendo se llama "timbre". Puede aparecer justo en el borde o a una distancia muy corta de él. Sin embargo, no puedo ver nada obvio en tu código que lo cause. Las imágenes de muestra antes/después pueden ayudar. –

+0

Sí, es como si estuviera haciendo un algoritmo de nitidez que trata de ver los valores de los píxeles más allá del borde de la imagen.Estoy tratando de encontrar un buen lugar para publicar las imágenes antes/después. – mckamey

+0

Esa muestra * después * de la imagen no la muestra del todo tan pronunciada como la veo en mi aplicación, pero aún puede decir que no es correcta. – mckamey

Respuesta

38

Finalmente encontré un artículo que habla de esto.

Libor Tinka casualmente menciona esto antes de pasar a mostrar su amplio conjunto de filtros que forma GDI superan + escalado:

Desde su consejo, que suena como que está haciendo exactamente lo sospechamos: está sacando un promedio de detalles de los píxeles circundantes más allá del borde de la imagen. Esto me parece una falla en el algoritmo, pero eso está abierto a debate. Para resolver esto, hay una clase de ImageAttributes donde puedes especificar que los píxeles más allá son simplemente imágenes reflejas de los píxeles dentro. Al establecer esta parece eliminar completamente el sonido:

using (ImageAttributes wrapMode = new ImageAttributes()) 
{ 
    wrapMode.SetWrapMode(WrapMode.TileFlipXY); 
    g.DrawImage(input, rect, 0, 0, input.Width, input.Height, GraphicsUnit.Pixel, wrapMode); 
} 

Muchas gracias a ambos Libor Tinka de la solución, y con Mark Ransom por ayudarme a que a través de este y por darme el término "timbre", que fue lo que hizo Libor La solución de Tinka incluso aparece en mis búsquedas.

+0

La causa raíz parece ser un filtro excesivamente agresivo en el redimensionamiento, junto con un enmascaramiento de píxeles inapropiado en los bordes. Los píxeles del borde de la imagen no deben contribuir al resultado en absoluto, pero obviamente lo están desde que el ajuste lo corrige. Todavía puede ver el timbre en transiciones oscuras/claras, como la línea del techo en su ejemplo. –

+0

Lo que es realmente interesante es que el timbre a lo largo de la línea del techo ahora parece ser también fijo. Puede ser un efecto secundario de agregar en todas las otras configuraciones 'HighQuality' como' CompositingMode' y 'PixelOffsetMode'. El estado actual de las imágenes redimensionadas ha mejorado mucho. – mckamey

+0

Esto funcionó para mí también - gracias – Graeme

3

Probar:

g.CompositingMode = CompositingMode.SourceCopy; 

De mi respuesta here, corregido para la sintaxis.

El cambio de tamaño crea transparencia parcial alrededor del borde. La configuración SourceCopy le dice que reemplace ese píxel parcialmente transparente con uno completamente opaco.

+0

+1 Estoy de acuerdo con Mark, en realidad me golpeó. –

+2

Creo que tiene razón en que lo está tratando como parcialmente transparente. Si agrego 'g.Clear (Color.Black);' antes de dibujarlo, el blanco aún está allí, pero ahora el píxel más oscuro se oscurece. Desafortunadamente, al configurar 'g.CompositingMode = CompositingMode.SourceCopy;' se elimina cualquier sangrado por detrás (por ejemplo, el borde oscuro) pero todavía tiene el borde blanco de 1 pixel. – mckamey

+0

No veo ningún lugar donde esté definiendo 'calidad', ¿está seguro de que está utilizando la compresión JPEG de mayor calidad? –