Después de varios días de seguimiento extraño GDI+ errores, me he tropezado con esta pequeña joya en MSDN:

Clases dentro del Sistema.Dibujo de espacio de nombres no son compatibles para su uso dentro de un Windows o ASP.NET servicio. Intentar utilizar estas clases desde dentro de uno de estos tipos de aplicaciones que se pueden producir problemas inesperados, tales como la disminución de rendimiento del servicio y excepciones en tiempo de ejecución.

No sé si «ASP.NET servicio» significa «aplicación web» en este contexto, pero «la disminución de rendimiento del servicio» ciertamente parece cubrir el surtido aleatorio de «Un error genérico que se produjo en GDI+» y «Out of memory» los errores que mi aplicación está lanzando intermitentes, no reproducibles errores en la lectura y escritura de imágenes JPEG que – en muchos casos – en realidad fueron creados por el Sistema.De dibujo.La imagen en el primer lugar.

Así – si GDI+ no puede leer y escribir archivos JPEG de forma fiable en una aplicación Web, ¿a qué debo estar utilizando en su lugar?

Quiero que los usuarios puedan subir imágenes (JPEG sea necesario, a otros formatos agradable), volver a muestrear ellos de forma fiable, y mostrar mensajes de error útil si algo va mal. Alguna idea? Son el Sistema.Los medios de comunicación los espacios de nombres de WPF que vale la pena considerar?

EDICIÓN: Sí, sé que GDI+ obras «la mayoría del tiempo». Que no es lo suficientemente bueno, porque cuando falla, lo hace de una manera que es imposible aislar o recuperarse de gracia. No, no estoy interesado en los ejemplos de código GDI+ que funciona para usted: estoy buscando bibliotecas alternativas a utilizar para el procesamiento de imágenes.

  • Yo tengo uno de esos momentos en que GDI+ siempre falla independientemente sin embargo, muchos tratan de capturas/usando pongo. Consulte stackoverflow.com/questions/3125242/…
  • ¿Tienes un link actualizado o se trataba de un no-problema y la pregunta fue eliminado?
  • no sé por qué vínculo fue moderado. todavía no he encontrado ninguna solución para mi no fuente del sistema de GDI+ fallar. Es el mismo sobre .net 4. Me di por vencido y comenzó a utilizar el sistema de fuentes
  • Gracias por el apoyo de cita y enlace. Ahora también han «Para que se admita un método alternativo, vea Imágenes de Windows Componentes». msdn.microsoft.com/library/windows/desktop/…
  • También hay SkiaSharp.

7 Comentarios

  1. 10

    Hay un excelente post en el blog incluyendo el código de C# sobre el uso de la ImageMagick en la biblioteca de gráficos a través de la Interoperabilidad más en TopTen De Software De Blog. Este post trata específicamente con la ejecución de ASP.net en linux bajo mono; sin embargo, el código de C# debe ser perfectamente copiar-pegar-poder, la única cosa que usted necesitará cambiar es el de la Interoperabilidad de los atributos si se ejecuta bajo windows referencia a una ventana binario (DLL).

    ImageMagick® es una suite de software para crear, editar, componer, o convertir
    imágenes de mapa de bits. Puede leer y escribir imágenes en una variedad de formatos
    (más de 100), incluyendo DPX, EXR, GIF, JPEG, JPEG-2000, PDF, PhotoCD,
    PNG, Postscript, SVG, y TIFF. Usar ImageMagick para redimensionar, voltear,
    espejo, rotar, deformar, distorsionar y transformar las imágenes, ajustar la imagen
    los colores, aplicar diversos efectos especiales, o dibujar texto, líneas, polígonos,
    elipses y curvas de Bézier.

    También hay un ImageMagick .Red de desarrollo de proyecto en codeplex que envuelve todo. Pero no muestran un desarrollo activo desde 2009, por lo que puede estar a la zaga de la actual ImageMagick versión de la biblioteca. Para un pequeño trivial cambio de tamaño de rutina, probablemente me pegan con la interoperabilidad. Usted sólo necesita ver su aplicación cuidadosamente para su propia pérdida de memoria o inéditas de los recursos (la biblioteca en sí está bien probado y avalado por la comunidad).

    La biblioteca es libre y de código abierto. La licencia Apache 2 parece ser compatible tanto con el personal y con fines comerciales. Ver ImageMagick Página De Licencia.

    La biblioteca es totalmente multiplataforma e implementa muchas de las más poderosas de la imagen de la manipulación y la transformación de las rutinas que no se encuentran en GDI+ (o que no se aplican en virtud de mono) y tiene una buena reputación como una alternativa para ASP.net procesamiento de la imagen.

    Actualización: Parece que hay una versión actualizada del mismo .NETA envoltura aquí: http://magick.codeplex.com/

    • Esto se ve muy dulce, en realidad… voy a darle una oportunidad y dejar que usted sabe cómo subo 🙂 Gracias.
    • he usado la consola de contra-parte de imagemagick en una aplicación de poco tráfico sin ningún tipo de problemas, de modo que usted puede ser que también desee comprobar de que fuera demasiado
    • OK, algunos de los primeros hacks parece indicar que es bastante sencillo de gancho en la MagickWand de la API de .NET – así que la recompensa va a este, aunque en varias otras respuestas parecen prometedores así.
  2. 9

    Sí, el uso de WPF System.Windows.Media clases. Siendo totalmente gestionado que no sufren los mismos problemas que el GDI cosas.

    Aquí un extracto de algunos MVC código que uso para representar degradados, para dar una idea de cómo llegar desde una WPF Visual a un PNG:

    using System;
    using System.IO;
    using System.Web.Mvc;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    namespace MyMvcWebApp.Controllers
    {
    public class ImageGenController : Controller
    {
    //GET: ~/ImageGen/Gradient?color1=red&color2=pink
    [OutputCache(CacheProfile = "Image")]
    public ActionResult Gradient(Color color1, Color color2, int width = 1, int height = 30, double angle = 90)
    {
    var visual = new DrawingVisual();
    using (DrawingContext dc = visual.RenderOpen())
    {
    Brush brush = new LinearGradientBrush(color1, color2, angle);
    dc.DrawRectangle(brush, null, new Rect(0, 0, width, height));
    }
    return new FileStreamResult(renderPng(visual, width, height), "image/png");
    }
    static Stream renderPng(Visual visual, int width, int height)
    {
    var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Default);
    rtb.Render(visual);
    var frame = BitmapFrame.Create(rtb);
    var encoder = new PngBitmapEncoder();
    encoder.Frames.Add(frame);
    var stream = new MemoryStream();
    encoder.Save(stream);
    stream.Position = 0;
    return stream;
    }
    }
    }
    • No son totalmente administrados, son contenedores para el programa WIC, que es también incompatible (a pesar de lo que la documentación dice). La mayor parte de los mismos problemas y los nuevos.
    • WPF/WIC es también incompatible bajo ASP.NET.
  3. 9

    Usted puede encontrar un muy buen artículo de un Empleado de Microsoft aquí: Cambio de tamaño de imágenes desde el servidor usando WPF/WIC en lugar de GDI+ que propone el uso de WPF en lugar de GDI+. Es más acerca de thumbnailing pero en general los mismos problemas.

    De todos modos, al final dice esto:

    Me puse en contacto WPF equipo a tener la última palabra sobre si este es
    apoyado. Por desgracia, no lo es, y la documentación que se
    actualizado en consecuencia. Me disculpo sobre cualquier confusión que esto puede tener
    causado. Estamos buscando la manera de hacer que la historia sea más aceptable en
    el futuro.

    Para WPF también es compatible en aplicaciones web, y aún es, creo yo :-S

    • Sí, no es compatible. He tenido un error con un simple cambio de tamaño JPEG.
  4. 4

    ImageSharp

    ImageSharp es una fuente abierta de la cruz-plataforma 2D, biblioteca de gráficos. Está escrito en C# en la parte superior de la nueva .NETO Estándar, con ninguna dependencia en cualquier sistema operativo específico de la API.

    Es actualmente todavía en pre-lanzamiento en MyGet (tendrás que añadir el paquete fuente en el VS de opciones o un NuGet.archivo de configuración), pero ya estamos utilizando con algunos resultados muy positivos.

  5. 1

    La mayoría de los problemas que he leído sobre corresponden a recursos que no se desechen adecuadamente.

    He utilizado variantes de este código una y otra vez sin problemas de aplicaciones web:

    public void GenerateThumbNail(HttpPostedFile fil, string sPhysicalPath, 
    string sOrgFileName,string sThumbNailFileName,
    System.Drawing.Imaging.ImageFormat oFormat, int rez)
    {
    try
    {
    System.Drawing.Image oImg = System.Drawing.Image.FromStream(fil.InputStream);
    decimal pixtosubstract = 0;
    decimal percentage;
    //default
    Size ThumbNailSizeToUse = new Size();
    if (ThumbNailSize.Width < oImg.Size.Width || ThumbNailSize.Height < oImg.Size.Height)
    {
    if (oImg.Size.Width > oImg.Size.Height)
    {
    percentage = (((decimal)oImg.Size.Width - (decimal)ThumbNailSize.Width) / (decimal)oImg.Size.Width);
    pixtosubstract = percentage * oImg.Size.Height;
    ThumbNailSizeToUse.Width = ThumbNailSize.Width;
    ThumbNailSizeToUse.Height = oImg.Size.Height - (int)pixtosubstract;
    }
    else
    {
    percentage = (((decimal)oImg.Size.Height - (decimal)ThumbNailSize.Height) / (decimal)oImg.Size.Height);
    pixtosubstract = percentage * (decimal)oImg.Size.Width;
    ThumbNailSizeToUse.Height = ThumbNailSize.Height;
    ThumbNailSizeToUse.Width = oImg.Size.Width - (int)pixtosubstract;
    }
    }
    else
    {
    ThumbNailSizeToUse.Width = oImg.Size.Width;
    ThumbNailSizeToUse.Height = oImg.Size.Height;
    }
    Bitmap bmp = new Bitmap(ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
    bmp.SetResolution(rez, rez);
    System.Drawing.Image oThumbNail = bmp;
    bmp = null;
    Graphics oGraphic = Graphics.FromImage(oThumbNail);
    oGraphic.CompositingQuality = CompositingQuality.HighQuality;
    oGraphic.SmoothingMode = SmoothingMode.HighQuality;
    oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
    Rectangle oRectangle = new Rectangle(0, 0, ThumbNailSizeToUse.Width, ThumbNailSizeToUse.Height);
    oGraphic.DrawImage(oImg, oRectangle);
    oThumbNail.Save(sPhysicalPath  + sThumbNailFileName, oFormat);
    oImg.Dispose();
    }
    catch (Exception ex)
    {
    Response.Write(ex.Message);
    }
    }
    • ¿significa esto que el Sistema.Los métodos de dibujo que está llamando se apoyó en un ASP.NET aplicación?
    • Las llamadas a la API utilizadas en esta función han sido utilizadas en varias aplicaciones web, y no he tenido problemas hasta la fecha. Yo no puedo decir con certeza acerca de que sea compatible.
    • Yo creo que la advertencia de que el OP encontrado se aplicaría a estos métodos. Y con .NET 4.0 próximamente, «siempre trabajó» se convierte en menos convincente.
  6. 0

    He tenido buen comportamiento de la biblioteca Cairo (http://www.cairographics.org) en un ASP.Net webserver medio ambiente. De hecho, me trasladó a el cairo desde WPF debido a WPF pobres del uso de la memoria modelo basado en la web cosas.

    De WPF en realidad tiende a ejecutar el proceso de trabajo de la memoria. Ninguno de los objetos de WPF implementar IDisposable, y muchos de ellos de referencia de la memoria no administrada que sólo se libera a través de un finalizador. El gran uso de WPF (especialmente si el servidor es significativamente CPU-impuestos a) se ejecutará finalmente fuera de la memoria, porque el finalizador de cola obtiene saturado. Cuando yo era perfiles de mi aplicación, por ejemplo, la finalización de la cola tenía más de 50,000 objetos, muchos de ellos sosteniendo las referencias a la memoria no administrada. El Cairo se ha comportado mucho mejor para mí, y su uso de la memoria patrón ha sido mucho más predecibles que los de WPF es.

    Si usted está interesado en el uso de el cairo, agarra una de las librerías de GTK+’s sitio web. Tienen un x86, así como una x64 conjunto de archivos binarios.

    El único inconveniente es que el cairo no puede leer/escribir JPG de forma nativa; sin embargo, usted puede fácilmente adaptarse WPF cosas para leer/escribir en JPG y hacer el remuestreo/escala/dibujo/cualquier otra cosa que el uso de el Cairo.

Dejar respuesta

Please enter your comment!
Please enter your name here