Test post

Monday, February 15, 2010 10:58 PM

Test post

Test post

10:58 PM

Test post

Wednesday, January 13, 2010 5:34 PM

"But you, sir, are no painter. And while you hack away at your terminal, or ride your homemade Segway, we painters and musicians are going to be right over here with all the wine, hash, and hot chicks.

Hee hee."

Aww.

Experimenting with different fonts

Friday, January 8, 2010 4:41 PM

Was bored today, and decided to experiment a little with different types of fonts for Visual C++. Now for the past 5 years I've been using courier new, and occasionally consolas as my editor font, but I wonder how proportional fonts can look with blocks of code. Here are my results:



The original, in Courier New. Fairly readable font, the onlything that bugs me is the curly braces are fairly hard to distinguish from parenthesis.



I've been using consolas for the past little while, and have few complaints. It's clean and clear, and has no big readability problems.



Ah into the proportional fonts. Helvetica seems fairly difficult to read as the text comes out to be way too thin, and the text don't line up nicely(as with all proportional fonts)



I actually liked gills. It looks tidy and the brackets are all fairly readable. One thing I really like about this is how wide each space is in comparison to the white space between letter. This "bunches up" the keywords and makes it really easy to read each word. One little complaint is that the number 1 looks almost indistinguishable from a small L.



I was never a big fan of serif fonts in documents, but the look of this turns out better than I expected. The words are easy to read, although the width of the space seems to be a little to narrow for my liking. Also the '()' looks a bit weird.



Verdana is one of the most legible fonts for programming. The L/i/1 all look different, as is O and 0. Horizontal whitespace wise it's fairly good as it has sufficent width for space to distinguish each word. The space between each letter is a bit too thin, as rn turns out to look a lot like m.



Deja vu isn't as well known as the other fonts in this list, but I think that it is one of the better looking monospaced fonts. No big complaints about anything, only that the l looks a bit weird.

You can get the font here: http://dejavu-fonts.org/wiki/index.php?title=Download



Ah the IKEA font. Visually I think it looks the best out of all the fonts here; however one big flaw of this font is that small L looks identical to a capital i. The stacked parenthesis look a bit hard to read though(difficult to count if there are 5+ parenthesis).

In the end I decided to use verdana. If I were to rank the fonts here though, these would be my top 3(Except verdana):
1. Deja vu
2. cambria
3. Gills sans

Using smoothscroll on blogger

Tuesday, January 5, 2010 6:01 PM

The smoothscroll plugin for chrome(link) is a cute plugin that intercepts mousewheel events and animates the scrolling of the page so it scrolls in a nice fluid motion rather than the epileptic fashion of the default scrolling in chrome. After examining the source of the extension I decided to add it in to this blog, since blogger is so liberal about the use of javascript on the website.

Unfortunately according to this:


Firefox users will not be able to experience the endless joy of scrolling smoothly; however it is compatible with most version of IE and chrome and safari.

To get this working, just paste this in the blogger template somewhere in a pair of script tags in the header section:


// Frame Variables
var frame = false;
var noscrollframe = false;
var yoff = 0;

// Scroll Variables
// tweakables
var framerate = 60; // hz
var animtime = 400; // faster than picasa
var scrollsz = 180; // pixels

// less tweakables
var PulseScale = 10; // ratio of 'tail' to 'acceleration'
var PulseNormalize = 1;

ComputePulseScale();
var scrolls;
// Keyboard Settings
var keyboardsupport = true;
var arrscroll = 40; //in px
var arrframes = 6;
var pgscroll = 800; //in px
var pgframes = 20;

// Arrays of timeouts
var up = [], down = [];

// Other Variables
var sTop = 1337;
var delta = 0;
var initdone = false;
var d = 10;

function onloadf() {
if (!scrolls)
scrolls = setupScrolls();
if (top != self) { // Checks if this script is running in a frame
frame=true;
//if (document.documentElement.scrollHeight < (document.documentElement.clientHeight+10))
if (document.body.scrollHeight <= (document.body.clientHeight+10))
noscrollframe=true;
}

// Fix acid3 test -> make some people happy
if (document.URL != "http://acid3.acidtests.org/") {
var underlay = document.createElement('div');
underlay.setAttribute("style","z-index: -1; position:absolute; top:0px; left: 0px; width: 100%; height: "+document.body.scrollHeight+"px;");
document.body.appendChild(underlay);
/* This fixes a bug where the areas left and right
to the content does not trigger the onmousewheel event
on some pages */
}
initdone=true;
}

function wheel(event){
if (initdone==false) onloadf();
var scroll=true;
var prevent = false;
var src = window.event.srcElement;
var scrollup = true;
var scrolldown = true;
var lastdelta = delta;

delta = 0;
if (event.wheelDelta)
delta = event.wheelDelta/120;

do {
if (document.body.scrollHeight == src.scrollHeight) {
scroll=true;
break;
}
else {
if ((src.clientHeight+10) < src.scrollHeight) {
overflow = document.defaultView.getComputedStyle(src,"").getPropertyValue("overflow");
if (overflow=="scroll" || overflow=="auto") {
prevent = true;
if (src.scrollTop == sTop) {
if (src.scrollTop == 0) {
scrollup = true;
scrolldown = false;
}
else {
scrolldown = true;
scrollup = false;
}
} else {
scroll = false;
}
sTop = src.scrollTop;
scrollelm(delta,src,1); //Fixes a bug
var a = delta<0 ? up : down;
while(a.length) {
try {
clearTimeout(a.pop(a[i]));
} catch(e) {}
}
for (var i=0; i < 10; i++) {
d = 10;
(delta>0 ? up: down).push(setTimeout(function () {
scrollelm(delta,src,d)
}, i * 1000 / framerate + 1));
}
break;
}
}
}
} while(src = src.parentElement)

if (frame==true) {
if (noscrollframe==true) {
scroll=false;
}
else {
if ((yoff==window.pageYOffset) && (lastdelta<0)) {
//The last scroll downwards did nothing
scrollup=true;
scrolldown=false;
}
if ((yoff==window.pageYOffset) && (lastdelta>0)) {
//The last scroll upwards did nothing
scrollup=false;
scrolldown=true;
}
yoff = window.pageYOffset;
}
}
if (scroll==true) {
if (((scrolldown==true) && (delta < 0)) || ((scrollup==true) && (delta > 0))) {
handle(delta);
if (event.preventDefault)
event.preventDefault();
event.returnValue = false;
}
}
if (prevent == true) {
// Prevention for scrollable html elements
if (event.preventDefault)
event.preventDefault();
event.returnValue = false;
}

//Debug
//console.log("scrollup "+scrollup);
//console.log("scrolldown "+scrolldown);
//console.log("scroll "+scroll);
//console.log("frame "+frame);
//console.log("prevent "+prevent);
//console.log("noscrframe "+noscrollframe);
//console.log(document.documentElement.scrollHeight);
//console.log(document.documentElement.clientHeight+10);
}

// viscous fluid with a pulse for part and decay for the rest
function Pulse_(x)
{
var val;

// test
x = x * PulseScale;
if (x < 1) {val = x - (1 - Math.exp(-x));}
else {
// the previous animation ended here:
var start = Math.exp(-1);

// simple viscous drag
x -= 1;
var expx = 1 - Math.exp(-x);
val = start + (expx * (1.0 - start));
}

return val * PulseNormalize;
}

function ComputePulseScale()
{
PulseNormalize = 1 / Pulse_(1);
}

// viscous fluid with a pulse for part and decay for the rest
function Pulse(x)
{
if (x >= 1) return 1;
if (x <= 0) return 0;

if (PulseNormalize == 1) {
ComputePulseScale();
}

return Pulse_(x);
}

function setupScrolls() {

scrolls = new Array();

var last = 0;
var frm = parseInt(framerate * animtime / 1000);

for (var i = 0; i < frm; i++) {

// scroll is [0, 1]
var scroll = (i + 1) / frm;
// transform [0, 1] -> [0, 1]:
scroll = Pulse(scroll);

// scale and quantize to int so our pixel difference works:
var iscroll = parseInt(scrollsz * scroll + 0.99);

scrolls.push(iscroll - last);
last = iscroll;
}

return scrolls;
}

function handle(delta) {
var a = delta<0 ? up : down;
while(a.length) {
try {
clearTimeout(a.pop(a[i]));
} catch(e) {}
}
for (var i=0; i < scrolls.length; i++)
(delta>0 ? up : down).push(setTimeout('window.scrollBy( 0 ,' + -delta * scrolls[i] + ');', i * 1000 / framerate + 1));
}

function scrollelm(delta,src,d) {
if (delta > 0) {
src.scrollTop -= d;
} else {
src.scrollTop += d;
}
}


function keypress()
{
if(window.event) {
if (!(event.target instanceof HTMLInputElement) &&
!(event.target instanceof HTMLTextAreaElement) &&
(event.target.contentEditable == "false") &&
!(event.ctrlKey || event.altKey || event.shiftKey)) {
if(event.keyCode==38) {
arrscrollwindow(event.altKey ? 2 : 1);
event.preventDefault();
}
if(event.keyCode==40) {
arrscrollwindow(event.altKey ? -2 : -1);
event.preventDefault();
}
}
if(event.keyCode==33 && !event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey) {
pgscrollwindow(1);
event.preventDefault();
}
if(event.keyCode==34 && !event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey) {
pgscrollwindow(-1);
event.preventDefault();
}
}
}

function arrscrollwindow(delta) {
var a = delta<0 ? up : down;
while(a.length) {
try {
clearTimeout(a.pop(a[i]));
} catch(e) {}
}
for (var i=0; i < arrframes; i++)
(delta>0 ? up : down).push(setTimeout ('window.scrollBy( 0 ,' + -delta * (arrscroll/arrframes) + ');', i * 25));
}

function pgscrollwindow(delta) {
var a = delta<0 ? up : down;
while(a.length) {
try {
clearTimeout(a.pop(a[i]));
} catch(e) {}
}
for (var i=0; i < pgframes; i++)
(delta>0 ? up : down).push(setTimeout ('window.scrollBy( 0 ,' + -delta * (window.innerHeight/pgframes) + ');', i * 25));
}
window.onmousewheel = wheel;
window.onload = onloadf;


Basically I just deleted the parts in the plugin source that was communicating with the plugin internals, which makes this any plain old javascript.

Original source by: patrickb1991, https://chrome.google.com/extensions/detail/cccpiddacjljmfbbgeimpelpndgpoknn

Rolling Stones releases 100 top albums of the decade

Monday, January 4, 2010 9:13 PM

The link can be found here:
http://www.rollingstone.com/news/story/31248017/100_best_albums_of_the_decade/print

Now, as much as I approve of their decision to put Kid A as the album of the decade, I think the rest of the list is utter shit.

"Is This It" was a fairly 'listenable' album. By listenable, I mean precisely that: all tracks were fairly straightforward, nothing experimental going on, all potential radio hits. Surely some solid tracks such as Someday and Trying Your Luck was on the album, I definitely would not have put it as the number 2 album of the decade.

Seeing MGMT's Oracular Spectacular in the top 20 makes me die a little inside. Seriously? These guys are pretty much the definition of throwing pretentious shit together and calling it art. Most tracks had the formulaic structure of a catchy electronic riff with heavy distortion bass undertones, and upon hearing the vocals, I realize WHY they were trying to drown it out with the distortion bass.

Coldplay's "A Rush Of Blood to The Head" at 21? I didn't realize the Rolling Stones put elevator music on such a high pedestal.

After reading this list, I realize Kanye West's ENTIRE DISCOGRAPHY was feature, yet I hear no mention of Lady Gaga anywhere. Yes I understand that Kanye's rise to fame is one of the most discussed topics in the decade, but it's incomprehensible how the female icon of pop -perhaps the most talented entertainer in the industry in years- was never even mentioned. Yet Kanye West, someone in a similar position and already on his fall from grace, is given recognition and praise.

Implementation of the classes in mosaic.flickr

Sunday, January 3, 2010 7:22 PM

After I had the idea of coding this I had this feeling of "fuck this is so brilliant why am i not coding" whenever i was NOT at the computer and typing" , so in about 8 hours of straight coding I had pretty much the rough implementation finished. in the next few posts i'll briefly describe their conception and show off some pretty neat code.

Photostream Class:
This class was pretty easy to write considering that a fairly large amount of work has been devoted to creating a useable flickr API for java. Thanks to jickr(which unfortunately, is no longer being developed), obtaining a stream of photos based on a search string has about all the difficulty of stealing candy from a well endowed baby. Based on a few search parameters, the Photostream class returns a list of Photo objects, from which I can obtain a BufferedImage of a desireable size.

ProcessPhotostream class:
This class will omnomnom the list of Photos and eventually organize them in an accessible datastructure. For simplicity's sake, I will save the bufferedimages at the size of 75x75 in folders, since by storing the data on the harddrive we sort of create a cache that's easily acccessed at the cost of some speed and storaged. To keep track of the folders we can use an int array to keep track of number of bufferedimages in each subfolder.
This class will begin by iterating through the list of photos, obtain the corresponding BufferedImages, and by some sort of analyzation method, sort them into folders. Firstly I will try to sort them by dominant hue, then I can write the code to sort by brightness(which is considerably simpler). Therefore the flow of this class will be like this:


for(Photo p:photos){
BufferedImage i = p.getImage(Photo.Size.Square);
process(i);
}

void process(BufferedImage b){
if(b==null)return;
...//insert processing code

//obtain an 'index' value which represents the image

//increment the counter in the int array which represents the number of pages with the current counter
database.map[index]++;

/*write the image to a file with its corresponding index.*/
ImageIO.write(b,"png",new File("output/"+index+"/"+database.map[index]+".png"));
}




To process the image, a simple(probably inefficient) way would be loop through all the pixels, and do calculations on the RGB value of each pixel. Since we want to find the dominant color of an image, we can simply find the average RGB of each pixel, and the resulting RGB will be the 'dominant' color. This is, of course, a large oversimplification of image processing, but it will have to do.


/*store the overall rgb values in these three variables, might have to use long for really large images*/
int r=0;
int g=0;
int b=0;


if(Constants.colored){//have a simple control variable for colored/monotone images
for(int i =0;i<Constants.size;i++){
for(int j =0;j<Constants.size;j++){

//getRGB() returns the colorvalue in the form of 0xAARRGGBB, a signed int
int c = bi.getRGB(i,j);

//performing & operation isolates the third byte, and shifts over by 2 bytes = 0x000000RR
int red = (c & 0x00ff0000) >> 16;

//isolates the second byte, shifts over by one byte = 0x000000GG
int green = (c & 0x0000ff00) >> 8;

//isolates the first byte = 0x000000BB
int blue = c & 0x000000ff;

//add the RGB values to the tracker variables
r+=red;
g+=green;
b+=blue;
}

}
//find the avg rgb
r/=Constants.size*Constants.size;
g/=Constants.size*Constants.size;
b/=Constants.size*Constants.size;



At this point, we can get by with simply 8 bit color(256 possible colors). however, for future development we might want more colors.

The 8 bit color architecture is a bit icky. in 8 bit color, the bits are ordered as RRRGGGBB in binary, which means 3 bits are devoted to red, 3 bits to green, and 2 bits to blue.

So first we'll want to convert the corresponding rgb values to its corresponding 8 bit color value:


r=(r>>5);//r was 8 bits, now it will be 3 bits
g=(g>>5);//g was 8 bits, now it will be 3 bits
b=(b>>6);//b was 8 bits, now it will be 2 bits


//r is now 00000RRR, shifting it to the left by 5 will make it RRR00000
//g is now 00000GGG, shifting it to the left by 2 will make it 000GGG00
//b is now 000000BB, no need to shift
//adding them together will produce RRRGGGBB
int index = (r<<5)+(g<<2)+b;



Note: Just because we shift r to the right by 5, then left by 5, does not mean these 2 operations cancel out. By shifting r to the right by 5, we effectively "set" the 5 rightmost bits to 0 when we shift it back to the left.

With the index we can now store the image to the appropriate folder and increment the appropriate element in the database array.

Next: using the image database to generate a mosaic.

Categories