Una respuesta correcta puede ser reconstruido a partir de algunas de las otras respuestas, pero ninguno de ellos está completo y algunos presentan algunas ideas muy malas (como dibujar la imagen dos veces).
Hay tres razones por las que estamos viendo artefactos:
- El valor predeterminado
Graphics.PixelOffsetMode
configuración hace que los valores de los píxeles a muestrear de forma incorrecta, lo que resulta en una ligera distorsión de la imagen, sobre todo en los bordes.
InterpolationMode.HighQualityBicubic
muestras píxeles más allá del borde de la imagen, que son transparentes de forma predeterminada. Esos píxeles transparentes se mezclan con los píxeles del borde por la muestra, lo que da como resultado bordes semitransparentes.
- Cuando guarda una imagen semitransparente en un formato que no admite transparencias (por ejemplo, JPEG), los valores transparentes se reemplazan por negro.
Todo eso se suma a los bordes semi-negros (es decir, grises).
La forma correcta para eliminar esos artefactos es utilizar PixelOffsetMode.Half
y utilizar un objeto ImageAttributes
para especificar suelo de baldosas de borde de modo que el HighQualityBicubic
muestreador tiene algo distinto de los píxeles transparentes a muestra.
Hay algunos otros problemas con el código que envió, así:
El Bitmap
constructor que se utiliza es inicializar el nuevo Bitmap
cambiando el tamaño de la imagen original, por lo que está haciendo la operación de cambio de tamaño dos veces. Debe usar una sobrecarga de constructor con solo las dimensiones deseadas para crear un lienzo en blanco.
Recuerde que la clase Bitmap
representa una copia no administrada de la imagen en la memoria. Debe eliminarse para que se le pueda decir a GDI + que libere esa memoria cuando haya terminado con ella. Supongo que está haciendo eso en el código que recibe el retorno Image
, pero lo señalo en caso de que alguien más tome prestado este código.
La configuración CompositingQuality.HighQuality
utilizada en su código no tendrá ningún efecto visual si obtiene las otras configuraciones correctas y perjudicará el rendimiento bastante significativamente en combinación con el valor predeterminado de CompositingMode.SourceOver
. Puede omitir la configuración CompositingQuality
y establecer CompositingMode.SourceCopy
para obtener los mismos resultados con un mejor rendimiento.
La configuración SmoothingMode
utilizada en el código no tiene ningún impacto en DrawImage()
, por lo que se puede quitar.
Puede leer más acerca de la configuración Graphics
clase y su impacto en la calidad de imagen y rendimiento aquí: http://photosauce.net/blog/post/image-scaling-with-gdi-part-3-drawimage-and-the-settings-that-affect-it
El código revisado debería ser algo como esto:
public static Image Scale(Image sourceImage, int destWidth, int destHeight)
{
var toReturn = new Bitmap(destWidth, destHeight);
using (var graphics = Graphics.FromImage(toReturn))
using (var attributes = new ImageAttributes())
{
toReturn.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
attributes.SetWrapMode(WrapMode.TileFlipXY);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.Half;
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.DrawImage(sourceImage, Rectangle.FromLTRB(0, 0, destWidth, destHeight), 0, 0, sourceImage.Width, sourceImage.Height, GraphicsUnit.Pixel, attributes);
}
return toReturn;
}
¿Cómo se ve el código HTML como si eso fuera enviado al navegador para estas imágenes? – DOK
¿Cuál es el tipo original de la imagen? –
publique su imagen de entrada –