I'm a newb when it comes to creating an ASP.NET custom user control that will render and return .png charts to an ASP.NET web application.
I've created a simple sandbox project that creates an ellipse on a bitmap, renders it to a MemoryStream, and now I want to stream the output connected via an HTTP handler so as to render an asp:image in my markup page.
My problem is that I don't know how to connect the MemoryStream created in my usercontrol to the GetImage method of the http handler. I know that the GetMethod of the HTTP Handler creating a memory stream within the method isn't correct, but I don't know how to access the memorystream of the codebehind.
My prototype test project code is:
namespace ChartControl
{
public partial class ChartCtl : System.Web.UI.UserControl
{
private int imageHeight = 150;
private int imageWidth = 400;
protected void Page_Load(object sender, EventArgs e)
{
renderChart();
}
protected MemoryStream renderChart()
{
Image imgChart = new Bitmap(imageWidth, imageHeight);
Graphics g = Graphics.FromImage(imgChart);
Rectangle r = new Rectangle(0, 0, imageWidth, imageHeight);
g.DrawEllipse(Pens.Orange, g.VisibleClipBounds);
MemoryStream ms = new MemoryStream();
imgChart.Save(ms, ImageFormat.Png);
return ms;
}
}
}
My HTTP Handler is:
namespace WIChart.UserControls
{
public class ImageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.Clear();
if (!String.IsNullOrEmpty(context.Request.QueryString["id"]))
{
int id = Int32.Parse(context.Request.QueryString["id"]);
// Now we have the id, just pass it to GetImage to build the image
Image image = GetImage(id);
context.Response.ContentType = "image/png";
image.Save(context.Response.OutputStream, ImageFormat.Png);
}
else
{
context.Response.ContentType = "text/html";
context.Response.Write("<p>Valid id is required.</p>");
}
}
#region IHttpHandler Members
public bool IsReusable
{
get { return false; }
}
private Image GetImage(int id)
{
MemoryStream stream = new MemoryStream();
return Image.FromStream(stream);
}
#endregion
}
}
My .ascx page is:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="ChartCtl.ascx.cs" Inherits="ChartControl.ChartCtl" %>
<%# Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">
<asp:Image id="imgChart" ImageUrl="~/ImageHandler.ashx?id=1" runat="server" />
</p>
</div>
</div>
Thank you for any help that you can provide!
I couldn't understand what exactly you need here. But You can load image from user control using below code.
using System.Web;
using System.Web.UI;
using System.IO;
namespace WebApplication1
{
public class ImageHandler : Page, IHttpHandler
{
public new void ProcessRequest(HttpContext context)
{
context.Response.Clear();
ChartCtl chartCtl = (ChartCtl)LoadControl(ResolveClientUrl("ChartCtl.ascx"));
MemoryStream ms = new MemoryStream();
ms = chartCtl.renderChart(ms);
context.Response.Clear();
context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite(ReadFully(ms));
context.Response.End();
}
public static byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
#region IHttpHandler Members
public new bool IsReusable
{
get { return false; }
}
#endregion
}
}
HTML-
<asp:Image ID="imgChart" ImageUrl="~/ImageHandler.ashx" runat="server" />
ChartCtrl -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
namespace WebApplication1
{
public partial class ChartCtl : System.Web.UI.UserControl
{
private int imageHeight = 150;
private int imageWidth = 400;
public MemoryStream renderChart(MemoryStream ms)
{
Image imgChart = new Bitmap(imageWidth, imageHeight);
Graphics g = Graphics.FromImage(imgChart);
Rectangle r = new Rectangle(0, 0, imageWidth, imageHeight);
g.DrawEllipse(Pens.SteelBlue, g.VisibleClipBounds);
imgChart.Save(ms, ImageFormat.Jpeg); // save the image to the memorystream to be processed via the Image/HttpHandler
imgChart.Save(Context.Response.OutputStream, ImageFormat.Jpeg); // save to drive just to verify that image is being properly created.
return ms;
}
}
}
Web.Config [IIS 7] -
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<handlers>
<add name="ImageHandler" verb="*"
path="ImageHandler.ashx"
type="WebApplication1.ImageHandler, WebApplication1"
resourceType="Unspecified" />
</handlers>
</system.webServer>
Mem Stream to byte array conversion is from Creating a byte array from a stream
Check this link also http://www.codeproject.com/Articles/34084/Generic-Image-Handler-Using-IHttpHandler
P.S - I don't know why your code is being executed only with constructor. Without constructor I'm able to execute the code. When you are loading a web control from Handler, normal page events wouldn't get executed. We need call methods manually.
I think You need to host your website in IIS to get HTTpHandler called, I am not sure about this part.
You are coming at this a bit backwards with using your imagehandler as a page -- try to think of the page as static HTML where you are referencing an image and the answer is pretty straightforward. What you need to do is add an image tag referencing your graphic-generating handler -- ie <img src="~/MyHandler.ashx" />.
The challenge then becomes how to marshal data into the handler. There are loads of ways to handle this, the basic ones being query string variables if the data is simple or a query string with enough data so the handler can go back and load it's own data.
Related
I have to "generate" a png file and send it to the Telegram bot via SendPhotoAsync of SeendDocumentAsync.
This is a piece of my C# code:
...
Bitmap speedometer = new Bitmap(#"C:\Immagini\bot\speedometer.png");
Bitmap pointer = new Bitmap(#"C:\Immagini\bot\pointer.png");
Bitmap finalImage = new Bitmap(speedometer);
using (Graphics graphics = Graphics.FromImage(finalImage))
{
Bitmap rotatedPointer = RotateImage(pointer, efficienza_int * (float)1.8);
rotatedPointer.MakeTransparent(Color.White);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(rotatedPointer, 0, 0);
?????????????
}
Now, I want to send my finalImage without saving it on the disk with Save method.
How can I?
Thanks in advice!
Save it to MemoryStream, and send the MemoryStream in your call to the bot, like this:
using (MemoryStream ms = new MemoryStream())
using (Bitmap finalImage = new Bitmap(speedometer))
{
using (Graphics graphics = Graphics.FromImage(finalImage))
{
// ... stuff
}
finalImage.Save(ms, ImageFormat.Png);
// This is important: otherwise anything reading the stream
// will start at the point AFTER the written image.
ms.Position = 0;
Bot.SendPhotoAsync(/* send 'ms' here. Whatever the exact args are */);
}
It is possible that async sending requires the stream to remain open. Though, normally, when you have such an async send, you can specify a function that should be called after the sending has finished.
In that case, you should not put the MemoryStream in a using block, but instead store the stream object in a global variable in your class, and make sure that the function handling the end of the async send disposes it.
Also do note this question...
bot.sendphoto does not work asp.net
Apparently SendPhotoAsync is not enough to actually send it; the answer there specifies you need to call .GetAwaiter() and .GetResult(). I don't know the API, so you'll have to figure that out yourself.
From the Telegram Bot API documentation (link)
Sending files
There are three ways to send files (photos, stickers, audio, media, etc.):
...
Post the file using multipart/form-data in the usual way that files are uploaded via the browser. 10 MB max size for photos, 50 MB for other files.
Your question is not clear!
However, (if I understand your question right)
You are using TelgramBotClient from this repository: https://github.com/TelegramBots
when you invoke SendPhotoAsync from this client it takes FileToSend as a parameter which represent the photo you processed with rotation, transparency and smoothing.
when you pass this FileToSend you can set the photo either by loading it from temp file you created after processing or you can load it directory from MemoryStream like this:
using System.Drawing;
using System.Drawing.Drawing2D;
using Telegram.Bot;
using Telegram.Bot.Args;
using System.IO;
using System.Drawing.Imaging;
namespace LoadGraphicsFromMemory
{
public static class ImageExtensions
{
public static MemoryStream ToMemoryStream(this Bitmap image, ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
image.Save(ms, format);
return ms;
}
}
}
class Program
{
private static float efficienza_int;
private static readonly TelegramBotClient Bot = new TelegramBotClient("Your API key");
static void Main(string[] args)
{
Bot.OnMessage += BotOnMessageReceived;
}
private static void BotOnMessageReceived(object sender, MessageEventArgs e)
{
Bitmap speedometer = new Bitmap(#"C:\Immagini\bot\speedometer.png");
Bitmap pointer = new Bitmap(#"C:\Immagini\bot\pointer.png");
Bitmap finalImage = new Bitmap(speedometer);
using (Graphics graphics = Graphics.FromImage(finalImage))
{
Bitmap rotatedPointer = RotateImage(pointer, efficienza_int * (float)1.8);
rotatedPointer.MakeTransparent(Color.White);
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(rotatedPointer, 0, 0);
}
Bot.SendPhotoAsync(e.Message.Chat.Id, new Telegram.Bot.Types.FileToSend("My File", finalImage.ToMemoryStream(ImageFormat.Jpeg)));
}
private static Bitmap RotateImage(Bitmap pointer, object p)
{
return pointer;
}
}
}
I'm trying to load a remote image from my Amazon S3 bucket and send it to browser in binary. I'm also trying to learn ASP.Net at the same time. I've been a classic programmer for many years and need to change. I started yesterday and have my first headache today.
On a page in my application I have this image element:
<img src="loadImage.ashx?p=rqrewrwr">
and on loadImage.ashx, I have this exact code:
-------------------------------------------------
<%# WebHandler Language="C#" Class="Handler" %>
string url = "https://............10000.JPG";
byte[] imageData;
using (WebClient client = new WebClient()) {
imageData = client.DownloadData(url);
}
public void ProcessRequest(HttpContext context)
{
context.Response.OutputStream.Write(imageData, 0, imageData.Length);
}
-------------------------------------------------
There is probably quite a lot wrong with this, as it's my first attempt at .net and don't know what I'm doing. To start with, I'm getting the following error but sure there's more to come.
CS0116: A namespace does not directly contain members such as fields or methods
This is on line 3, which is string url = "https://............"
For an HttpHandler, you have to put the code in the code behind... if you expand loadimage.ashx in Solution Explorer, you should see a loadimage.ashx.cs file. This file is where your logic should be, and all of it should be in the ProcessRequest method.
So loadimage.ashx should be basically empty:
<%# WebHandler Language="C#" Class="loadimage" %>
And loadimage.ashx.cs should contain the rest:
using System.Web;
public class loadimage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string url = "https://............10000.JPG";
byte[] imageData;
using (WebClient client = new WebClient())
{
imageData = client.DownloadData(url);
}
context.Response.OutputStream.Write(imageData, 0, imageData.Length);
}
public bool IsReusable
{
get { return false; }
}
}
Alternatively, you can create an aspx page that serves the image. This removes the code behind requirement, but adds a little more overhead... create a loadimage.aspx page with the following:
<%# Page Language="C#" AutoEventWireup="true" %>
<script language="c#" runat="server">
public void Page_Load(object sender, EventArgs e)
{
string url = "https://............10000.JPG";
byte[] imageData;
using (System.Net.WebClient client = new System.Net.WebClient())
{
imageData = client.DownloadData(url);
}
Response.ContentType = "image/png"; // Change the content type if necessary
Response.OutputStream.Write(imageData, 0, imageData.Length);
Response.Flush();
Response.End();
}
</script>
Then reference this loadimage.aspx in the image src instead of the ashx.
I created an ASP.NET/C# application to upload an image to MySQL database. The process executes without any error but for whatever image I upload I am getting output of 100x100 white image. The procedure I followed is.
1) Created a database with field picture and type Binary(255).
2) Uploaded an image as cmd.Parameters.Add("#picture", OdbcType.Binary, 255).Value = FileUpload1.FileBytes;
3) Doing above a new record is being inserted and a value something of below kind is generated.
89504e470d0a1a0a0000000d49484452000002600000010008020000009b155d400000100049444154789cd4dc05745b57a2377a15c26088d99651b2248b999959b2c0966cc9cccccc8e1ddb01439899d3a4499a869999e33037d0340d34d4b4d5dbaee7e6f6b5337367eefad67bf3adf55f676dd98e221f6b9ddffeef738e20db5cbf826c77fd3638d8eafa6587ebd79daedfc0f6afd9eefae5ab372fd6bf7db9e5e7b7075dae4daf5e1c76b98ebb5cfb7ef935a5b31b028b32ea53f6ec3a77efe60fb919156e34222b297ee3aedd2e97ebe6dd870b96acd8b0efc0891bb76ae7ce8ba9a8dc70f1f2c917afaeb95ce75c1f276cd988b0180329c4c4aaf2d2
//--------------- Uploading module completed -----------------//
1) Created a ASPX page with
<asp:Image ID="img" runat="server" ImageUrl="~/MyImage.ashx" />
2) Left ASPX.CS file without any code
3) Added a ASHX file with
<%# WebHandler Language="C#" Class="MyImage" %>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Drawing.Imaging;
public class MyImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/png";
var data = "89504e470d0a1a0a0000000d49484452000002600000010008020000009b155d400000100049444154789cd4dc05745b57a2377a15c26088d99651b2248b999959b2c0966cc9cccccc8e1ddb01439899d3a4499a869999e33037d0340d34d4b4d5dbaee7e6f6b5337367eefad67bf3adf55f676dd98e221f6b9ddffeef738e20db5cbf826c77fd3638d8eafa6587ebd79daedfc0f6afd9eefae5ab372fd6bf7db9e5e7b7075dae4daf5e1c76b98ebb5cfb7ef935a5b31b028b32ea53f6ec3a77efe60fb919156e34222b297ee3aedd2e97ebe6dd870b96acd8b0efc0891bb76ae7ce8ba9a8dc70f1f2c917afaeb95ce75c1f276cd988b0180329c4c4aaf2d2";
var buffer = StringToByteArray(data);
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
private byte[] StringToByteArray(string hex)
{
return Enumerable
.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public bool IsReusable
{
get { return false; }
}
}
By executing this code a white 100x100 image is being displayed in output for any colorful input. I double checked ContentType and uploaded various images of various sizes and formats but whatever I do I am getting an output of same White image. What's wrong in my code? any corrections?
You can try saving the image as a Base64 encoded string, then converting it back to an image when you want it to render on your web page.
Here is a link on how to do it.
Base64String to Image and visa versa
Here is a link to how I used it in my project, not quite from an image or from a database but the concept is the same.
When using my method in your webpage you'll use
<img src="${downloadurl}" />
A 255 byte binary field type is not going to be large enough to handle anything except the very tiniest of images. Check the size of the files you are uploading and re-size the field accordingly.
I have this code in an ashx which pulls image data and displays it from an MSSQL database
public void ProcessRequest(HttpContext context)
{
Guid picid;
if (context.Request.QueryString["picid"] != null)
picid = new Guid(context.Request.QueryString["picid"]);
else
throw new ArgumentException("No parameter specified");
context.Response.ContentType = "image/jpeg";
Stream strm = ShowPicImage(picid);
byte[] buffer = new byte[4096];
int byteSeq = strm.Read(buffer, 0, 4096);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 4096);
}
}
public Stream ShowPicImage(Guid piciddata)
{
ProductPicture pictureData = new ProductPicture("ProductPictureID", piciddata);
object img = pictureData.Data;
try
{
return new MemoryStream((byte[])img);
}
catch
{
return null;
}
}
i don't know if it's something you can try for your problem. (Where the pictureData.Data property type is a byte[] and the relevant database column is a varbinary(max))
updated answer
You may also want to consider storing the data in the database as a BLOB
I have some textfields processed and other elements, but I want to get the bitmap so I can save it somewhere on disk. I need to do it directly from WatiN if this is possible.
How can I do this?
I had a similar problem some time ago.
Watin can't do this directly but it exposes the mshtml objects needed to get some results.
At the time my code was pretty much like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WatiN.Core;
using WatiN.Core.Native.InternetExplorer;
using mshtml;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program
{
[STAThread]
static void Main(string[] args)
{
Browser browser = new IE("http://www.google.com");
IEElement banner = browser.Images[0].NativeElement as IEElement;
IHTMLElement bannerHtmlElem = banner.AsHtmlElement;
IEElement bodyNative = browser.Body.NativeElement as IEElement;
mshtml.IHTMLElement2 bodyHtmlElem = (mshtml.IHTMLElement2)bodyNative.AsHtmlElement;
mshtml.IHTMLControlRange controlRange = (mshtml.IHTMLControlRange)bodyHtmlElem.createControlRange();
controlRange.add((mshtml.IHTMLControlElement)bannerHtmlElem);
controlRange.execCommand("Copy", false, System.Reflection.Missing.Value);
controlRange.remove(0);
if (Clipboard.GetDataObject() != null)
{
IDataObject data = Clipboard.GetDataObject();
if (data.GetDataPresent(DataFormats.Bitmap))
{
System.Drawing.Image image = (System.Drawing.Image)data.GetData(DataFormats.Bitmap, true);
// do something here
}
}
}
}
}
This little hack, basically, tries to copy the image to the clipboard. However I had a couple of problems making it work properly and ended up snapshoting the region around the image and saving it to disk.
Although this may not be very helpful it may point you in some directions..
I don't think you can get the binary information directly from WatiN. However you have Image.Uri method give you the URI of the image. So then it is easy to download it wih http request.
using (Browser browser = new IE("http://www.sp4ce.net/computer/2011/01/06/how-to-use-WatiN-with-NUnit.en.html"))
{
Image image = browser.Images[0];
Console.Write(image.Uri);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(image.Uri);
WebResponse response = request.GetResponse();
using (Stream stream = response.GetResponseStream())
using (FileStream fs = File.OpenWrite(#"c:\foo.png"))
{
byte[] bytes = new byte[1024];
int count;
while((count = stream.Read(bytes, 0, bytes.Length))!=0)
{
fs.Write(bytes, 0, count);
}
}
}
Hope this helps
A while ago I needed to extract image data too so I came with this solution:
Create an hidden field and a canvas inside the page using
ie.RunScript("document.body.innerHTML += \"<input type='hidden' id='hidden64'/>\";");
ie.RunScript("document.body.innerHTML += \"<canvas id='canv' width='150px' height='40px' ></canvas>\";");
transform it to base64 using javascript and retrieving its value
ie.RunScript("var c = document.getElementById('canv');");
ie.RunScript("var ctx = c.getContext('2d');");
ie.RunScript("var img = document.getElementsByName('imgCaptcha')[0];");
ie.RunScript("ctx.drawImage(img, 10, 10);");
ie.RunScript("document.getElementById('hidden64').value=c.toDataURL();");
then retrieving the codified value
string data = ie.Element(Find.ById("hidden64")).GetAttributeValue("value");
var base64Data = Regex.Match(data, #"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
Bitmap im;
using (var stream = new MemoryStream(binData))
{
im = new Bitmap(stream);
}
Hope it helps :)
public Image GetImageFromElement(IHTMLElement Element)
{
int width = (int)Element.style.width;
int height = (int)Element.style.height;
IHTMLElementRender2 render = (IHTMLElementRender2)Element;
Bitmap screenCapture = new Bitmap(width, height);
Rectangle drawRectangle = new Rectangle(0, 0, width, height);
this.DrawToBitmap(screenCapture, drawRectangle);
Graphics graphics = Graphics.FromImage(screenCapture);
IntPtr graphicshdc = graphics.GetHdc();
render.DrawToDC(graphicshdc);
graphics.ReleaseHdc(graphicshdc);
graphics.Dispose();
return screenCapture as Image;
}
That's the Method i use for php generated images.
It's implimented in my own WebBrowserClass, which extends the webbrowser control.
(so "this" = WebBrowser)
But we have to import the IHTMLElementRender2 interface, to use the method.
[Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
ComVisible(true),
ComImport]
interface IHTMLElementRender2
{
void DrawToDC([In] IntPtr hDC);
void SetDocumentPrinter([In, MarshalAs(UnmanagedType.BStr)] string bstrPrinterName, [In] IntPtr hDC);
};
I found this method in web, about 1 year ago, so if you search for it you might find more information.
Iwan
I had such problem, and I could not solve it. PHP generated new images all the time so I used the CaptureWebPageToFile() method.
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;}
}
}
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"/>
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);
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#?
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.
It is NOT possible to output image from a WebService.
Check this: http://www.c-sharpcorner.com/UploadFile/gnsrinivas1511/Webservice05112009034709AM/Webservice.aspx
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.