开发者

How do I get a bitmap of the WatiN image element?

I have some textfields processed and other elements, but I want to get the bitmap so I ca开发者_运维技巧n 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜