una - Cambiar el tamaño de las imágenes transparentes con C#
recortar imagen c sharp (5)
Si bien PNG es definitivamente mejor que GIF, ocasionalmente hay un caso de uso para tener que permanecer en formato GIF.
Con GIF o PNG de 8 bits, debe abordar el problema de la cuantificación.
La cuantificación es donde elige qué 256 (o menos) colores preservarán y representarán mejor la imagen, y luego volverá a convertir los valores RGB en índices. Cuando realiza una operación de cambio de tamaño, la paleta de colores ideal cambia, ya que está mezclando colores y cambiando balanzas.
Para pequeños cambios de tamaño, como 10-30%, puede estar bien conservando la paleta de colores original.
Sin embargo, en la mayoría de los casos necesitará volver a cuantizar.
Los dos algoritmos principales para elegir son Octree y nQuant. Octree es muy rápido y hace un muy buen trabajo, especialmente si puedes superponer un algoritmo de tramado inteligente. nQuant requiere al menos 80MB de RAM para realizar una codificación (construye un histograma completo), y típicamente es 20-30X más lenta (1-5 segundos por codificación en una imagen promedio). Sin embargo, a veces produce una mayor calidad de imagen que la de Octree ya que no tiene valores ''redondos'' para mantener un rendimiento consistente.
Al implementar el GIF transparente y el soporte animado GIF en el proyecto imageresizing.net , elegí Octree. El soporte de transparencia no es difícil una vez que tiene el control de la paleta de imágenes.
¿Alguien tiene la fórmula secreta para cambiar el tamaño de las imágenes transparentes (principalmente GIF) sin NINGUNA pérdida de calidad? ¿Qué pasa?
He intentado un montón de cosas, lo más cercano que consigo no es lo suficientemente bueno.
Echa un vistazo a mi imagen principal:
http://www.thewallcompany.dk/test/main.gif
Y luego la imagen escalada:
http://www.thewallcompany.dk/test/ScaledImage.gif
//Internal resize for indexed colored images
void IndexedRezise(int xSize, int ySize)
{
BitmapData sourceData;
BitmapData targetData;
AdjustSizes(ref xSize, ref ySize);
scaledBitmap = new Bitmap(xSize, ySize, bitmap.PixelFormat);
scaledBitmap.Palette = bitmap.Palette;
sourceData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly, bitmap.PixelFormat);
try
{
targetData = scaledBitmap.LockBits(new Rectangle(0, 0, xSize, ySize),
ImageLockMode.WriteOnly, scaledBitmap.PixelFormat);
try
{
xFactor = (Double)bitmap.Width / (Double)scaledBitmap.Width;
yFactor = (Double)bitmap.Height / (Double)scaledBitmap.Height;
sourceStride = sourceData.Stride;
sourceScan0 = sourceData.Scan0;
int targetStride = targetData.Stride;
System.IntPtr targetScan0 = targetData.Scan0;
unsafe
{
byte* p = (byte*)(void*)targetScan0;
int nOffset = targetStride - scaledBitmap.Width;
int nWidth = scaledBitmap.Width;
for (int y = 0; y < scaledBitmap.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
p[0] = GetSourceByteAt(x, y);
++p;
}
p += nOffset;
}
}
}
finally
{
scaledBitmap.UnlockBits(targetData);
}
}
finally
{
bitmap.UnlockBits(sourceData);
}
}
Estoy usando el código anterior para hacer el cambio de tamaño indexado.
¿Alguien tiene ideas de mejora?
Si no hay un requisito para preservar el tipo de archivo después de escalar, recomiendo el siguiente enfoque.
using (Image src = Image.FromFile("main.gif"))
using (Bitmap dst = new Bitmap(100, 129))
using (Graphics g = Graphics.FromImage(dst))
{
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(src, 0, 0, dst.Width, dst.Height);
dst.Save("scale.png", ImageFormat.Png);
}
El resultado tendrá muy buenos bordes anti aliased
- imagen eliminada de la cabaña de la imagen que había sido reemplazada por un anuncio
Si debe exportar la imagen en gif, está listo para dar un paseo; GDI + no funciona bien con gif. Mira esta publicación en el blog para obtener más información
Editar: Olvidé deshacerme de los mapas de bits en el ejemplo; ha sido corregido
Creo que el problema es que estás haciendo un escaneo basado en la línea de escaneo, lo que te va a llevar a hacer jaggies sin importar cuán duro lo modifiques. Una buena calidad de cambio de tamaño de la imagen requiere que haga un poco más de trabajo para determinar el color promedio de los píxeles pre-redimensionados que cubre su píxel redimensionado.
El tipo que dirige este sitio web tiene una publicación en el blog que analiza algunos algoritmos de cambio de tamaño de la imagen. Es probable que desee un algoritmo de escalamiento de imagen bicúbico.
Esta es una función básica de cambio de tamaño que he utilizado para algunas de mis aplicaciones que aprovecha GDI +
/// <summary>
/// Resize image with GDI+ so that image is nice and clear with required size.
/// </summary>
/// <param name="SourceImage">Image to resize</param>
/// <param name="NewHeight">New height to resize to.</param>
/// <param name="NewWidth">New width to resize to.</param>
/// <returns>Image object resized to new dimensions.</returns>
/// <remarks></remarks>
public static Image ImageResize(Image SourceImage, Int32 NewHeight, Int32 NewWidth)
{
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(NewWidth, NewHeight, SourceImage.PixelFormat);
if (bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format1bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format4bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format8bppIndexed | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Undefined | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.DontCare | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppArgb1555 | bitmap.PixelFormat == Drawing.Imaging.PixelFormat.Format16bppGrayScale)
{
throw new NotSupportedException("Pixel format of the image is not supported.");
}
System.Drawing.Graphics graphicsImage = System.Drawing.Graphics.FromImage(bitmap);
graphicsImage.SmoothingMode = Drawing.Drawing2D.SmoothingMode.HighQuality;
graphicsImage.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphicsImage.DrawImage(SourceImage, 0, 0, bitmap.Width, bitmap.Height);
graphicsImage.Dispose();
return bitmap;
}
No recuerdo muy bien si funcionará con GIF, pero puedes intentarlo.
Nota: No puedo tomar todo el crédito por esta función. Combiné algunas cosas de otras muestras en línea y lo hice funcionar para mis necesidades 8 ^ D
Para cualquiera que esté intentando usar la solución de Markus Olsson para cambiar el tamaño de las imágenes dinámicamente y escribirlas en el flujo de respuestas.
Esto no funcionará:
Response.ContentType = "image/png";
dst.Save( Response.OutputStream, ImageFormat.Png );
Pero esto hará:
Response.ContentType = "image/png";
using (MemoryStream stream = new MemoryStream())
{
dst.Save( stream, ImageFormat.Png );
stream.WriteTo( Response.OutputStream );
}