Pages

Tuesday, November 13, 2012

Chrome captureVisibleTab and the Canvas

Writing a browser plugin at work to capture what is being displayed in the current tab.
Was originally looking at cool Javascript -> Canvas -> Image processors like http://html2canvas.hertzen.com/ but it just wasn't going to cut the cake.

Chrome has a lovely call chrome.tabs.captureVisibleTab that just gave me what I wanted.
Mocked up something simple to do a round trip to our server and I was good to go.

Started working on the problem and it was obvious that I needed to crop the image before sending it to the server. Not a problem. I knew Canvas had a drawImage method that allowed cropping and scaling and I was happy to read from the Chrome documentation that the image data "may be assigned to the 'src' property of an HTML Image element for display."

After writing the code to create the new image, do some cropping, passing messages between different layers in the extension I was ready for testing.
After some initial PEBKAC issues like not supplying enough parameters to drawImage, I was just ending up with a white image.
Hmmmm.
So I drew a box on my canvas to make sure I was passing the right image back to the server.
Finally got that working so I started stressing. What is with the drawImage method?

Was making smaller and smaller changes and constantly reloading the plugin and the page I was testing from and then one time, I told it to capture a second time.

Only when it fired the second time did it work.

So straight to google to find concerning messages like drawImage doesn't draw the first time.
It seems that even when the image is generated from a canvas, I was still required to wait for the image element to load.

So for the whole purpose of posting some demo code:


    chrome.windows.getCurrent(function(win)
    {
        chrome.tabs.captureVisibleTab(
            null, null, function(data)
                {
                    var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'html:canvas')
                    var image = new Image(800,600);
                    var context = canvas.getContext('2d');
                    canvas.width = 800;
                    canvas.height = 600;
                    image.onload = function() {
                        context.drawImage(image, 0, 0); // Obviously cropping goes here
                        var sender = new XMLHttpRequest();
                        sender.open("POST", <<some url>>, false);
                        var cropped = canvas.toDataURL('image/jpg', 90)
                        sender.send(cropped.substring(cropped.indexOf(',')));
                    }
                    image.src = data;

                 });
    });


Hooray for code on a code blog \o/

2 comments:

  1. Thanks for useful post. I was surprised to find that the uploaded image was a PNG at the server. This is because 'image/jpg' should be 'image/jpeg' in your code above, as jpg is not a valid MIME type.

    ReplyDelete
  2. How interesting. When I get back to this code I'll have to check if I am missing an e or not.

    ReplyDelete