Friday, March 19, 2010

Gone for a while

I had hoped to get a little more done with the new project before spring break, but seeing as how it was finals week, it's really not surprising that I didn't. And so, spring break is here, and I won't be able to do anything computer-related for around a week or so (thank god). When I get back, though, that <audio> tag will dance for me. I promise.

Tuesday, March 16, 2010

Hubble Kaleidoscope

Turns out, when a piece of javascript runs very slow and everything I try to speed it up has no real effect, a previously fun project pretty quickly turns tedious. In this case, the culprit was slow drawing code, which in an animation gets called pretty often. Since it's the drawing that's the interesting bit here, there really wasn't much I could do. I decreased the number of calls to drawImage() by making the strips run horizontal instead of vertical, and then decreased the number of transformations the canvas undergoes by once again increasing the number of calls to drawImage(). In the end, I ended up using the drawImage() function to reflect the wedge I copy from the source image. Originally, I had used a scale transform on the canvas to do the reflection, but I suspect it's a bit faster this way.

At any rate, after a long week of tedium and end-of-term homework, the Hubble Kaleidoscope is finished. It runs really quite slow, and does its best to light my computer's processor on fire, so I've decided not to embed it into this blog post. It was getting to be quite tedious to make sure every variable I used had a different name for every blog post anyway. Be wary, javascript will certainly try to kill your computer, and if that doesn't work, it will try to hypnotize you into total obedience.

Here is the actual webpage with the Kaleidoscope on it.
Here is the source code (at pastebin.com).
And here is a neat image to try the damn thing out with.

Next time I have free time, I think I will play around with the <audio> tag, and see if I have any better luck than when I first tried to add sound to the box killer game thing.

Monday, March 8, 2010

Zebras and stars

While thinking about how to best go about copying a triangular section of an image, I've realized just how much easier it would be to do this if the triangle had a couple of sides that are always parallel to the sides of the source image. This would also mean a much simpler algorithm for bouncing the wedge around the source image. On the downside, the bouncing would also be more likely to end up in a loop, where the wedge goes over the same areas of the source image over and over again. This seems like a small price to pay, but who knows, maybe it'll be annoying enough to go need fixing.

So, with everything nice and perpendicular, it seems easy enough to carve a wedge out of an image: just loop through the width of the wedge, copying a progressivly taller and taller 1px-wide strip of the source image. Doing this is much helped by this section of the canvas element's description.

...
triangle = function(kc,img,x,y){
 for(i=0;i<161;i++){
  kc.drawImage(img,       //Source
            x+i,y,        //Pos. in source
            1,(i*0.419),  //Size in source
            i,0,          //Pos. in destination
            1,(i*0.419)); //Size in destination
 }
}
I pass into this function a drawing context, the source image, and the x-y coordinates of where the wedge starts. The factor of 0.419 comes partially from basic trigonometry, to make the wedge have a nice 22.5 degree angle, and partially from experimentation, to make the wedges blend into a circle nicely. As it stands, this function, when called a few times on a translated and rotated canvas, will produce an image that looks like this:

It's pretty clear that while this is along the lines of what I want, it's not quite right. The problems are twofold: the white creases along where two wedges meet, and a striping of the wedges that aren't along the x or y axis.

The striping is caused by the fact that the little strips I am copying end up too skinny when distorted by the rotation of the wedge sections. A very simple solution to this is to simply make the strips wider than one pixel, so that they overlap, and stretching them apart a bit won't let the white-space underneath show through.

The white dot at the center is caused by the simple fact that anything multiplied by zero will be zero, and I start the for loop at zero. This too is easily solved by modifying the call to drawImage() to make the whole wedge shift slightly along the x-axis. This also happens to close up the white rays coming from the middle, in addition to the big hole.

The function, then, becomes this:

...
triangle = function(kc,img,x,y){
 for(i=0;i<161;i++){
  kc.drawImage(img,
            x+i,y,
            2,(i*0.419),
            i-1,0,
            2,(i*0.419));
 }
}
And the result looks more like this:

All that's left is some animation and an interface, but a combination of schoolwork and the time taken to write this post means I'll have to put all that off for a little later. Still, pretty good progress for a couple hours worth of work.

Saturday, March 6, 2010

Space looking all crazy

A couple of years ago, someone had sent me a link to this Onion article. I thought it was hilarious, and that the picture was a very neat effect. I also though I could totally do that, and it would be really awesome.

At the time, I was infatuated with flash, and figured that if anything could do the things I needed to be done, it would be flash. I suspect that was actually true, but I had conveniently failed to notice that it would really be me doing the hard work, rather than the platform. And so, through a combination of my laziness and one or two shortcomings of flash, the project stalled quickly.

I can't say for sure that the javascript/<canvas> combination is better suited to the task, but I am pretty sure it is at least sufficient, and there is at least one aspect in which it is better: the ease with which I can load images from off-site. As far as I know, such a thing in flash is either impossible, or requires more server configuration details than I was either able or willing to access. The ability to load images from wherever means I can pull in cool images myself, and let users enter image URLs to load into the kaleidoscope.

So, as I get started on this hopefully short project, let me define some goals and maybe even approached.

The Hubble Kaleidoscope
Making images look all crazy
1: Basic idea.
A Kaleidoscope is a neat toy. It consists of a cardboard tube, a couple of mirrors, and some glass or plastic beads. The mirrors are placed at an angle to each other at one end of the tube, the beads are poured in between them, and that end is capped off with a translucent piece of plastic. This way, when someone looks in the other end of the tube, pointing the end with the beads in it toward a bright light, the image of the beads is replicated by the mirrors into a repeating circle. Wikipedia has a nice article if this isn't clear.
The effect is quite cool, and there is no reason not to reflect a section of this or that image around a circle a few times, and as the Onion article clearly states, space looks all crazy as it is, so making it look even crazier should have great results.
2: Interface.
The resulting image will be a circle, so there ought to be a nice, neat circular frame to go around it. In addition to the frame and image, there needs to be a way to select an source image. I think a drop-down menu of some neat images I've found, as well as a text box to enter an image of your own will be good. Since I'd like the image to be animated, a way to stop the animation at a particularly cool-looking place would be nice. I always thought that clicking on the kaleidoscope image would be a neat way to do that, but a clearly marked button is probably a better idea.
3: Animation.
A lot of the hubble images I've found online are really big. This is great, but I would like to have a manageable size to the kaleidoscope. Specifically, I want it to fit into an iphone's screen. This means that at any one time, I'll only be able to reflect a small portion of a huge image, meanwhile other bit of the image might well be just as interesting to look at. To cover the whole image, I image the section of the image to be reflected as a triangle, bouncing around the frame of the source image. The script will then copy the pixels within that triangle to the portions of the screen where they need to go.
4: Resources.
Obviously, I won't be able to do without my canvas reference. I'll also need a good source of space images. The Hubble Heritage Gallery looks to be the perfect place to get them images, so it looks like I'm all set.

Now, all that's left is to sit down and put in the work. But I think I'll put that off.