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/

Sunday, September 16, 2012

Really loving my camera

I know it isn't always about the camera
  (Wow, how did blogger lose this image?)
I know the subjects aren't particularly unique.
But I love sharing some of my shots.

Thursday, May 24, 2012

Today I wrote a Braille Converter

As just a bit of a laugh, I wrote my Facebook status in morse code.
After someone thought it was braille, I thought that doing a status in braille was a good idea.

Except there were no converters that I could copy and paste the characters from, so I had to do it on the fly. 

Since I am a coder though, I really should code my own solution.
Braille Converter!!
Feel like this is the sort of thing I could almost start a github account for.

I was going to throw it straight onto this blog but I can't control the encoding of the page, so the UTF-8 characters got lost.

 Hooray for coding!!

-- edit --
Seems I've got an encoding issue in Chrome anyway //.o

Friday, September 9, 2011

Drive out to Marysville

Just wanted to go for another drive and managed to get caught in the snow.

Saturday, August 27, 2011

Thursday, August 25, 2011

Non sequential sequence

Every now and then I've wanted to go from 0 to n in almost a random fashion. One way to solve this problem is to create a list of all the numbers from 0 to n and then shuffle the list. This works for small numbers and is definitely random but what if you have a larger set of numbers and aren't so fussed about the randomness?

I was finally able to enter the right terms into my search engine to read up on linear feedback shift registers.
I had a quick peek around the net to see if there was one written in Java and came up empty handed. So I wrote one.
A quick & on the input to get the bits we were concerned with, >> to shift the bits and ^ the relevant bits to work out if I should stick a 1 on the high order bit.
Turns out that was a bit overkill, just needed to know if the amount of relevant bits was even or odd. If odd, add the high order bit (and shift the whole lot of course).

	if(Integer.bitCount((input & trap) ^ trap) % 2 == 1)
	{
		return (input >> 1) | (1 << bits - 1);
	}
	else
	{
		return input >> 1;
	}

The interesting bit was the values for the taps based on the number of bits in the 'register' you want.
The Wikipedia article says that for a LFSR to cycle through all numbers, there needs to be an even number of taps, the set of taps needs to be relatively prime.
Not being up with the maths of that last bit, I delved deeper into Wikipedia.

Then I realised I had the tools to brute force this puppy. Create a number of LFSR with different tap values and see which ones cycle through all numbers!

Size Taps
3 11
101
4 11
1001
5 11
1001
1111
10111
11011
11101
6 11
11011
100001
100111
101101
110011
This table starts to look like 3 is a good number to use, but it doesn't work for 8, 9, 10 and 11 bit registers. So unfortunately to get a good sequence of numbers, you need to know a good tap. I just haven't worked out a nice way to find out what they are.
Might as well include a table of the numbers generated by the different taps. I'll use a 5 bit register because of the multiple taps.
101 16 8 4 18 9 20 26 13 6 19 25 28 30 31 15 7 3 17 24 12 22 27 29 14 23 11 21 10 5 2 1
1001 16 8 20 10 21 26 29 14 23 27 13 6 3 17 24 28 30 31 15 7 19 25 12 22 11 5 18 9 4 2 1
1111 16 8 20 26 13 22 11 21 10 5 2 17 24 28 14 23 27 29 30 31 15 7 19 9 4 18 25 12 6 3 1
10111 16 24 28 14 7 19 25 12 22 27 29 30 31 15 23 11 5 2 17 8 4 18 9 20 10 21 26 13 6 3 1
11011 16 24 12 22 11 21 10 5 18 9 4 2 17 8 20 26 29 30 31 15 23 27 13 6 19 25 28 14 7 3 1
11101 16 24 12 6 19 9 4 18 25 28 30 31 15 23 27 29 14 7 3 17 8 20 10 21 26 13 22 11 5 2 1

*In my code I refer to traps. Miss read the wiki :P

Wednesday, August 24, 2011

Overengineering

A while ago I used to be able to VNC from my phone to my desktop to remotely play, pause and change the volume of winamp. I didn't use it often but it was handy.

At some point, my phone just gave up on the VNC connection. I don't know whether it can't handle the screen size (poor iPhone 3g) or if there is an incompatibility in the VNC versions. I did try updating RealVNC and using a different client on my phone but no success.

I had toyed with Java Robot before and figured it would be worth a laugh.

So fired up eclipse and wrote a program that paused, played, turned up the volume and turned down the volume. Fumbled through the Robot javadoc and re-factored it a bit so it looked nice. Got it running fairly quickly.

Next problem, how to control it. I figured html would work for an interface. That means I need to set-up a http server to listen for requests. I was hoping to just fudge through it, read the socket until I got something that looked like a location and push back content.
I wasn't really in the mood to read through the RFC for http so I turned to the Internet.
It came back with NanoHTTPD

I wasn't happy with the way you were expected to subclass it to handle specific URLs so I re-factored it a bit before getting to work.
Put some html together to be served and then it basically fell together.
I love it when you start from the top and bottom of a problem and the middle is just a bit of fiddling around.

So here it is, my winamp remote:

Yup, not much but it made me a happy little coder.

Been wasting most of today re-factoring NanoHTTPD. One of it's selling points is that it is just a single file which was handy for this project, but annoys my sense of organisation. I've split it in 2, one for the pure Http stuff and the other for utilities like turning it into a file browser.
Got rid of the need to consistently spawn new threads, clean up it's stream handling a bit and brought it up to scratch in terms of Java 1.5.

Was wondering if anyone else was interested in this? Should I make the controls configurable so it can control other applications?