13

I'd like to be able to create a simple PNG image, say of a red square using a c# web based service to generate the image, called from an <img src="myws.ashx?x=100> HTML element.

some example HTML:

<hmtl><body>
     <img src="http://mysite.com/webservice/rectangle.ashx?size=100">
</body></html>

Is there is anyone who can cobble together a simple (working) C# class just to get me started? Once off and going I'm sure I can finish this off to actually do what I want it to do.

  • End game is to create simple Red/Amber/Green (RAG) embedded status markers for a data driven web page that shows performance metrics etc*
  • I'd like it to use PNG's as I anticipate using transparency in the future*
  • ASP.NET 2.0 C# solution please... (I don't have a production 3.5 box yet)

tia

SOLUTION

rectangle.html

<html>
<head></head>
<body>
    <img src="rectangle.ashx" height="100" width="200">
</body>
</html>

rectangle.ashx

<%@ WebHandler Language="C#" Class="ImageHandler" %>

rectangle.cs

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

public class ImageHandler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        int width = 600; //int.Parse(context.Request.QueryString["width"]);
        int height = 400; //int.Parse(context.Request.QueryString["height"]);

        Bitmap bitmap = new Bitmap(width,height);

        Graphics g = Graphics.FromImage( (Image) bitmap );
        g.FillRectangle( Brushes.Red, 0f, 0f, bitmap.Width, bitmap.Height );    // fill the entire bitmap with a red rectangle

        MemoryStream mem = new MemoryStream();
        bitmap.Save(mem,ImageFormat.Png);

        byte[] buffer = mem.ToArray();

        context.Response.ContentType = "image/png";
        context.Response.BinaryWrite(buffer);
        context.Response.Flush();
    }

    public bool IsReusable {
        get {return false;}
    }
}
Guy
  • 9,720
  • 7
  • 38
  • 42
  • can you make a http handler return an image? lets say a bitmap image or a byte[] buffer to a c# method (code behind file) from where it is called? I am sorry if I sound stupipd but I am new to http handlers – zack Oct 27 '10 at 15:00
  • @YP, see the accepted answer?? Otherwise I don't understand what you mean and frankly, I would not know how to do it anyway. My c# is bleh! – Guy Nov 01 '10 at 11:26
  • @guy Thanks for posting the solution - helped me a lot! – Chris B Jun 13 '12 at 09:31

6 Answers6

21

Web services, especially SOAP expect things like an XML envelope with the details of the call in. You'd be better off using a HttpHandler.

Something like this:

using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

public class ImageHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        int width = int.Parse(context.Request.QueryString["width"]);
        int height = int.Parse(context.Request.QueryString["height"]);

        using (Bitmap bitmap = new Bitmap(width,height)) {

            ...

            using (MemoryStream mem = new MemoryStream()) {
                bitmap.Save(mem,ImageFormat.Png);
                mem.Seek(0,SeekOrigin.Begin);

                context.Response.ContentType = "image/png";

                mem.CopyTo(context.Response.OutputStream,4096);
                context.Response.Flush();
            }
        }
    }

}

This is very rough of course. You'd call it then:

<img src="myhandler.ashx?width=10&height=10"/>
Lloyd
  • 29,197
  • 4
  • 84
  • 98
  • 2
    Yes I missed bits, if you go into the Add New Item dialog is will create a HttpHandler for you properly, or hover over IHttpHandler and select "Implement this interface". It's something like: public bool IsReusable { get { return true; } } – Lloyd May 20 '09 at 14:19
  • Thanks - got it! Also minor typo on the Response.ContentType and ImageFormat.Png Now just need to get it to draw something / anything... – Guy May 20 '09 at 14:30
  • 1
    For caching I've seen you mention you can use HttpRuntime.Cache, just dump the byte[] return from the MemoryStream in there. – Lloyd May 20 '09 at 14:51
  • Finally got it! Use context.Response.BinaryWrite(buffer); Lloyd, if you can correct the typo's in your answer then you get the points!!! – Guy May 20 '09 at 15:38
  • @Lloyd:can you make a http handler return an image? lets say a bitmap image or a byte[] buffer to a c# method (code behind file) from where it is called? I am sorry if I sound stupipd but I am new to http handlers – zack Oct 27 '10 at 15:00
  • The above example returns an image. – Lloyd Oct 28 '10 at 12:36
3

A web service is not suitable for this. It returns a message in a specific format, typically SOAP, so it can't be an image.

Use a regular web form instead, where you remove all markup except the @page directive. Use the BinaryWrite method to write the image data to the response stream.

Example:

byte[] imageData;
using (Bitmap image = new Bitmap(10,10)) {
   using (Graphics g = Graphics.FromImage(image)) {
      g.Clear(Color.Red);
   }
   using (MemoryStream m = new MemoryStream()) {
      image.Save(m, ImageFormat.Png);
      imageData = m.ToArray();
   }
}
Response.ContentType = "image/png";
Response.BinaryWrite(imageData);
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • The only change I would make to this is to use a generic handler (.ashx file). There's no need for all the page (.aspx) overhead. – Keltex May 20 '09 at 13:52
  • It's actually possible to do this through a web service; I do it with PDFs. The key is to return it as a byte array, reconstitute it on the other end, and then write it out with the appropriate ContentType. – Adam V May 22 '09 at 21:18
  • @Adam V: Then you are only using the web service as back end for a web page. You can't use the response from the web service directly, as Guy asked for. – Guffa May 22 '09 at 22:14
2

I think @Lloyd's answer is a good start.

I've had problems with alpha transparencies and PNGs: Can you make an alpha transparent PNG with C#?

Community
  • 1
  • 1
Keith
  • 150,284
  • 78
  • 298
  • 434
  • Ha! I've been studying your question for the last hour. If I can just get some of the "simple stuff" right then I'm sure I can finished this off with even my numpty C# knowledge. – Guy May 20 '09 at 14:14
1

There is another way to accomplish serving a dynamic image.

namespace MyApp
{
    [ServiceContract]
    public interface IMyService
    {
        [WebGet(UriTemplate = "Image.png")]
        [OperationContract]
        Stream ShowImage();
    }
}

For the implementation:

public Stream ShowImage()
{
    Bitmap image = new Bitmap(@"C:\Image.png");
    Image image2 = new Bitmap(125, 125);

    using (Graphics graphics = Graphics.FromImage(image2))
    {
           graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
           graphics.SmoothingMode = SmoothingMode.HighQuality;
           graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
           graphics.CompositingQuality = CompositingQuality.HighQuality;
           graphics.DrawImage(image, 0, 0, 125, 125);
    }

    MemoryStream imageAsMemoryStream = new MemoryStream();
    image2.Save(imageAsMemoryStream, ImageFormat.Png);
    imageAsMemoryStream.Position = 0;
    return imageAsMemoryStream;
}

Start the service as a regular WCF service and add the service in your app.config

(WebService = new WebServiceHost(typeof(MyService))).Open();

You can pass parameters to make it more dynamic.

Jan Staal
  • 21
  • 2
0

It is NOT possible to output image from a WebService.

Check this: http://www.c-sharpcorner.com/UploadFile/gnsrinivas1511/Webservice05112009034709AM/Webservice.aspx

NinethSense
  • 8,824
  • 2
  • 23
  • 23
  • This depends on how one views a web service. It is perfectly possible to return a binary (image) using multipart mime encoding through a C# web API. It has been done. Refer to this for starters: http://en.wikipedia.org/wiki/MIME This is not terribly challenging to do in C# – Demi May 20 '09 at 13:59
  • 1
    "This depends on how one views a web service." << I agree. – NinethSense May 20 '09 at 14:02
  • Or just return binary, as mentioned in Guffa's post. :-) – Demi May 20 '09 at 14:02
  • Sorry, I may have my terminology wrong (or not accurate enough for a technical community) I take it .asmx is to return xml content? I'd not heard of ashx before now. – Guy May 20 '09 at 14:18
  • 1
    @Guy, asmx is webservice and ashx is a handler. Ashx is almost same as aspx. It implements IHttpHandler. Check this for more details: http://stackoverflow.com/questions/619697/what-are-the-benefits-of-an-ashx-handler-file-in-asp-net. It can help you in image generation. – NinethSense May 20 '09 at 15:01
0

Also, depending on how you implement this, please be aware that you could be setting yourself up for a DOS attack. Generating images is not the most processor friendly thing. Please be sure to have some authentication and or caching mechanism in place to help alleviate this potential pain point.

Chad Ruppert
  • 3,650
  • 1
  • 19
  • 19
  • It's for internal / intranet use only, but caching will have to be implemented! Thanks. – Guy May 20 '09 at 14:12