views:

251

answers:

2

How can I show an image base64 encoded using WebBrowser control in C#?

I used the following code:

<img src="data:image/gif;base64,/9j/4AAQSkZJRgABAgAAZABkAA7AAR
R894ADkFkb2JlAGTAAAAAAfbAIQABAMDAwMDBAMDBAYEAwQGBwUEBAUHCAYGBw
...
uhWkvoJfQO2z/rf4VpL6CX0Dts/63+FaS+gl9A7bP+tthWkvoJfQODCde4qfcg
RiNWK3UyUeX9CXpHU43diOK915X5fG/reux5hUAUBftZ" />

but no image is displayed. One solution would be to save images locally and using absolute path, but this is not desirable.

Any idea?

Thanks.

A: 

What is data uri string length, according to data Protocol in IE8 Data URIs cannot be larger than 32,768 characters.

Edit: The resource data must be properly encoded; otherwise, an error occurs and the resource is not loaded. The "#" and "%" characters must be encoded, as well as control characters, non-US ASCII characters, and multibyte characters.

volody
A: 

I tried doing this for a project and IE (which the WebBrowser control will eventually use) became the limiting factor - it can only hold 32Kb-sized images. I wound up having to create an HTTP handler (.ashx) that returned the image based on a database key.

edit: example - note the database handling routines are proprietary and you'd have to put in your own. The rest of the handler will show how to rescale images (if desired) and send back as a response to the browser:

public class GenerateImage : IHttpHandler
{
    /// <summary>
    /// Shortcut to the database controller.  Instantiated immediately
    /// since the ProcessRequest method uses it.
    /// </summary>
    private static readonly IDataModelDatabaseController controller =
        DataModelDatabaseControllerFactory.Controller;

    /// <summary>
    /// Enables processing of HTTP Web requests by a custom HttpHandler
    /// that implements the <see cref="T:System.Web.IHttpHandler"/>
    /// interface.
    /// </summary>
    /// <param name="context">An <see cref="T:System.Web.HttpContext"/>
    /// object that provides references to the intrinsic server objects
    /// (for example, Request, Response, Session, and Server) used to
    /// service HTTP requests.</param>
    public void ProcessRequest(HttpContext context)
    {
        if (controller == null)
        {
            return;
        }

        IDataModelDescriptor desc = controller.GetDataModelDescriptor(
            new Guid(context.Request.QueryString["dataModel"]));
        IDataModelField imageField =
            desc.Fields[context.Request.QueryString["imageField"]];
        IDatabaseSelectQuery query = controller.CreateQuery();
        string[] keys = context.Request.QueryString["key"].Split(',');
        string showThumb = context.Request.QueryString["showThumbnail"];
        bool showThumbnail = showThumb != null;

        query.AssignBaseTable(desc);
        query.AddColumn(imageField, false);
        for (int i = 0; i < desc.KeyFields.Count; i++)
        {
            query.AddCompareValue(
                desc.KeyFields[i],
                keys[i],
                DatabaseOperator.Equal);
        }

        context.Response.CacheControl = "no-cache";
        context.Response.ContentType = "image/jpeg";
        context.Response.Expires = -1;

        byte[] originalImage = (byte[])controller.ExecuteScalar(query);

        if (showThumbnail)
        {
            int scalePixels;

            if (!int.TryParse(showThumb, out scalePixels))
            {
                scalePixels = 100;
            }

            using (Stream stream = new MemoryStream(originalImage))
            using (Image img = Image.FromStream(stream))
            {
                double multiplier;

                if ((img.Width <= scalePixels)
                    && (img.Height <= scalePixels))
                {
                    context.Response.BinaryWrite(originalImage);
                    return;
                }
                else if (img.Height < img.Width)
                {
                    multiplier = (double)img.Width / (double)scalePixels;
                }
                else
                {
                    multiplier = (double)img.Height / (double)scalePixels;
                }

                using (Bitmap finalImg = new Bitmap(
                    img,
                    (int)(img.Width / multiplier),
                    (int)(img.Height / multiplier)))
                using (Graphics g = Graphics.FromImage(finalImg))
                {
                    g.InterpolationMode =
                        InterpolationMode.HighQualityBicubic;
                    finalImg.Save(
                        context.Response.OutputStream,
                        ImageFormat.Jpeg);
                }
            }
        }
        else
        {
            context.Response.BinaryWrite(originalImage);
        }
    }

    /// <summary>
    /// Gets a value indicating whether another request can use the
    /// <see cref="T:System.Web.IHttpHandler"/> instance.
    /// </summary>
    /// <value></value>
    /// <returns>true if the <see cref="T:System.Web.IHttpHandler"/>
    /// instance is reusable; otherwise, false.
    /// </returns>
    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}
Jesse C. Slicer
The problem is my application is not writen in asp.net, and I use WebBrowser Controler from C#. How can I make ProcessRequest function to execute?
Emanuel
I think you're going to have to go with your undesirable option of having the images on a local path. Unless you can host them centrally and have them accessed through the network via a UNC path or on a web server accessible by http.
Jesse C. Slicer