2009-05-20 12 views
11

Je voudrais être capable de créer une image PNG simple, par exemple un carré rouge en utilisant un service web C# pour générer l'image, appelé à partir d'un élément HTML <img src="myws.ashx?x=100>.Créer une image PNG avec le service web C# HttpHandler

quelques exemples HTML:

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

Est-ce il y a quelqu'un qui peut concocter un simple (travail) C# classe juste pour me commencer? Une fois hors tension, je suis sûr que je peux finir ça pour faire ce que je veux faire.

  • jeu final est de créer de simples rouge/orange/vert (RAG) des marqueurs d'état intégrés pour une page Web axée sur des données qui montre des indicateurs de performance, etc. *
  • Je l'aime utiliser la PNG comme je prévois l'aide la transparence à l'avenir *
  • ASP.NET 2.0 C# solution s'il vous plaît ... (Je n'ai pas une production 3.5 boîte encore)

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;} 
    } 
} 
+0

pouvez-vous demander à un gestionnaire http de renvoyer une image? disons une image bitmap ou un octet [] tampon à une méthode C# (code derrière le fichier) d'où il est appelé? Je suis désolé si je semble stupipd mais je suis nouveau pour les gestionnaires http – zack

+0

@YP, voir la réponse acceptée ?? Sinon je ne comprends pas ce que tu veux dire et franchement, je ne saurais pas comment le faire quand même. Mon C# est bleh! – Guy

+0

@guy Merci d'avoir posté la solution - m'a beaucoup aidé! –

Répondre

20

services Web, en particulier SOAP attendre des choses comme une enveloppe XML avec les détails de l'appel Vous seriez mieux d'utiliser un HttpHandler..

Quelque chose comme ceci:

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

} 

Ceci est très difficile bien sûr. Vous souhaitez l'appeler alors:

<img src="myhandler.ashx?width=10&height=10"/> 
+2

Oui, j'ai manqué des bits, si vous allez dans la boîte de dialogue Ajouter un nouvel élément, vous créerez un HttpHandler pour vous correctement, ou passez la souris sur IHttpHandler et sélectionnez "Implémenter cette interface". C'est quelque chose comme: public bool IsReusable {get {return true; }} – Lloyd

+0

Merci - j'ai compris! Aussi faute de frappe sur le Response.ContentType et ImageFormat.Png Maintenant juste besoin de l'obtenir pour dessiner quelque chose/n'importe quoi ... – Guy

+1

Pour la mise en cache, je vous ai vu mentionner que vous pouvez utiliser HttpRuntime.Cache, juste vider l'octet [] revenir du MemoryStream là-bas. – Lloyd

3

Un service Web ne convient pas à ce sujet. Il renvoie un message dans un format spécifique, typiquement SOAP, donc il ne peut pas être une image.

Utilisez un formulaire Web normal à la place, où vous supprimez tout le balisage à l'exception de la directive @page. Utilisez la méthode BinaryWrite pour écrire les données d'image dans le flux de réponse.

Exemple:

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

Le seul changement que je ferais est d'utiliser un gestionnaire générique (fichier .ashx). Il n'y a pas besoin de toute la surcharge de la page (.aspx). – Keltex

+0

Il est effectivement possible de le faire via un service Web; Je le fais avec des PDF. La clé est de le renvoyer sous la forme d'un tableau d'octets, de le reconstituer à l'autre extrémité, puis de l'écrire avec le ContentType approprié. –

+0

@Adam V: Ensuite, vous utilisez uniquement le service Web comme back-end pour une page Web. Vous ne pouvez pas utiliser directement la réponse du service Web, comme l'a demandé Guy. – Guffa

0

Il est impossible à l'image de sortie d'un WebService.

Vérifiez ceci: http://www.c-sharpcorner.com/UploadFile/gnsrinivas1511/Webservice05112009034709AM/Webservice.aspx

+0

Cela dépend de la façon dont on voit un service Web. Il est parfaitement possible de renvoyer un binaire (image) en utilisant un encodage mime multipart à travers une API web C#. C'est fait. Référez-vous à cela pour les débutants: http://en.wikipedia.org/wiki/MIME Ce n'est pas très difficile à faire en C# – Demi

+1

"Cela dépend de la façon dont on voit un service Web." << Je suis d'accord. – NinethSense

+0

Ou juste retourner binaire, comme mentionné dans la publication de Guffa. :-) – Demi

0

En outre, selon la façon dont vous implémentez cela, s'il vous plaît soyez conscient que vous pourriez vous mettre en place pour une attaque DOS. Générer des images n'est pas la chose la plus favorable au processeur. Assurez-vous de mettre en place un mécanisme d'authentification et/ou de mise en cache pour vous aider à soulager ce point douloureux potentiel.

+0

Il est uniquement destiné à un usage interne/intranet, mais la mise en cache devra être implémentée! Merci. – Guy

2

Je pense que la réponse de Lloyd est un bon début.

J'ai eu des problèmes avec des transparents alpha et PNGs: Can you make an alpha transparent PNG with C#?

+0

Ha! J'ai étudié votre question pour la dernière heure.Si je peux juste obtenir quelques-uns des «trucs simples», alors je suis sûr que je peux terminer ceci avec même mes connaissances C# numpty. – Guy

1

Il y a une autre façon d'accomplir au service d'une image dynamique.

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

Pour la mise en œuvre:

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

Démarrez le service comme un service régulier WCF et ajoutez le service dans votre app.config

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

Vous pouvez transmettre des paramètres pour le rendre plus dynamique.

Questions connexes