使用 C# HttpHandler webservice 创建 PNG 图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/887985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 08:32:06  来源:igfitidea点击:

Create PNG image with C# HttpHandler webservice

c#web-servicespnghttphandlerimage

提问by Guy

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.

我希望能够创建一个简单的 PNG 图像,比如使用基于 ac# web 的服务生成图像的红色方块,从<img src="myws.ashx?x=100>HTML 元素调用。

some example HTML:

一些示例 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.

有没有人可以拼凑一个简单的(工作)C# 类来让我开始?一旦离开并开始,我相信我可以完成它来真正做我想要它做的事情。

  • 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)
  • 最终游戏是为显示性能指标等的数据驱动网页创建简单的红色/琥珀色/绿色 (RAG) 嵌入式状态标记*
  • 我希望它使用 PNG,因为我预计将来会使用透明度*
  • ASP.NET 2.0 C# 解决方案请...(我还没有生产 3.5 框)

tia

蒂亚

SOLUTION

解决方案

rectangle.html

矩形.html

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

rectangle.ashx

矩形.ashx

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

rectangle.cs

矩形.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;}
    }
}

采纳答案by Lloyd

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.

Web 服务,尤其是 SOAP 需要诸如包含调用详细信息的 XML 信封之类的东西。最好使用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"/>

回答by Guffa

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.

Web 服务不适合于此。它以特定格式(通常是 SOAP)返回消息,因此它不能是图像。

Use a regular web form instead, where you remove all markup except the @pagedirective. Use the BinaryWritemethod to write the image data to the response stream.

改用常规 Web 表单,在其中删除除@page指令之外的所有标记。使用该BinaryWrite方法将图像数据写入响应流。

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);

回答by NinethSense

回答by Chad Ruppert

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.

此外,根据您如何实现这一点,请注意您可能正在为 DOS 攻击做好准备。生成图像并不是对处理器最友好的事情。请确保有一些身份验证和/或缓存机制来帮助缓解这个潜在的痛点。

回答by Keith

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

我认为@Lloyd 的回答是一个好的开始。

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

我在使用 alpha 透明胶片和 PNG 时遇到了问题:你能用 C# 制作一个 alpha 透明的 PNG 吗?

回答by Jan Staal

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

将该服务作为常规 WCF 服务启动并在您的 app.config 中添加该服务

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

You can pass parameters to make it more dynamic.

您可以传递参数以使其更具动态性。