Tuesday, November 27, 2012

iPhone multi-touch events and braille-like input

Below is a quick demo of me "typing" a short phrase and some numbers using a modified version of my Blind Input iPhone web app. This is a proof of concept app that doesn't integrate into the phone's other text entry forms, and is arguably more difficult to learn than braille. In case it appears I've solved some great accessibility problem, Siri and the iPhone's native accessibility features has me beat in spades, and my app is only an interesting idea I wanted to experiment with.

Monday, November 12, 2012

The math behind HTML5 context transforms

If you've drawn widgets with HTML5 canvases, you've no doubt come across such methods as ctx.translate(x, y), ctx.scale(x, y), and ctx.rotate(radians). These are all convenience methods for ctx.transform(a, b, c, d, e, f), which applies a generic affine transform to the canvas. Consulting the specs will show that the a-f variables refer to this transformation matrix:

If this looks incomprehensible, it might help to express the matrix in basic Algebraic terms:

 x' = ax + cy + e, and
 y' = bx + dy + f

Sunday, November 04, 2012

Simple Javascript RGB/HSV converter

This is a simple and straightforward converter between RGB and HSV values, with RGBs from 0 - 255 and HSV values with hue from 0 - 359 and S/V from 0 - 1. I wrote it for an as yet unfinished HTML5 red-eye correction tool, but I'll be unable to devote much time to side-projects until after the holidays, so I thought I'd put this up now in case someone found it useful.

Enjoy!


function getHSV(r, g, b) {
  var h, s, v, max, delta;

  // v (value) is the highest of the RGB values scaled to [0-1]
  max = Math.max(r, Math.max(g, b));
  if (max == 0) return [0, 0, 0];
  v = max / 255;

  // delta is the difference between the largest and smallest of RGB
  delta = max - Math.min(r, Math.min(g, b));
  if (delta == 0) return [0, 0, v]; // No delta = grey, only v is significant

  // s (saturation) is delta divided by max
  s = delta / max;

  // h (hue) is a number in degrees describing the color's angle on the hsv color wheel
  if      (r == max) h =     (g - b) / delta;
  else if (g == max) h = 2 + (b - r) / delta;
  else if (b == max) h = 4 + (r - g) / delta;

  // convert hue to degrees
  if (h < 0) h += 6;
  h *= 60;

  return [h, s, v];
}

function getRGB(h, s, v) {
  var quadrant, max, mid, min, fraction;
  max = Math.round(v * 255);
  if( s == 0 ) return ([max, max, max]); // Greys

  // Quadrant is between 0 and 5, where 0, 2, and 4 are red, green, and blue
  h /= 60;
  quadrant = Math.floor(h);

  // fraction is distance away from quadrant representing hue's primary color
  fraction = (quadrant % 2 == 0) ? (1 - h % 1) : h % 1;

  // min and mid are the smaller two RGB colors in the final return array
  // We don't know what primary colors they represent...
  min = Math.round(max * ( 1 - s ));
  mid = Math.round(max * ( 1 - s * fraction ));

  // ...until we check what quadrant we're in
  switch (quadrant) {
    // reds
    case 5: return [max, min, mid];
    case 0: return [max, mid, min];
    // greens
    case 1: return [mid, max, min];
    case 2: return [min, max, mid];
    // blues
    case 3: return [min, mid, max];
    case 4: return [mid, min, max];
  }
}