Wednesday, November 21, 2012

Building a New Image Format

There’s now a newcomer to the stable of images we use for web development. It’s the WebP Image Format (see https://developers.google.com/speed/webp/)


WebP’s goal is to surpass compression file sizes of photographs—a role usually reserved by JPEG. But this JPEG clone has a special talent: animation! So, in essenece, the WebP image format is a hybrid of the GIF and JPEG file format.

The downside to new image formats is their historically slow adoption rate. While transparency support in the PNG format is an obviously amazing benefit for any web designer, Internet Explorer took about four years to support it after the other major browsers did. As of this writing, Mozilla is not yet supporting the WebP format. The benefits of WebP image format seems to merely replace existing features of the GIF and JPEG formats without adding anything new of substance, while it brings in a host of browser compatibility headaches for web designers and developers that could last years.

There are 20+ polyfills for adaptive images with their pros and cons, a couple of which I’ve had a hand in writing. But all these solutions are not solving the real problem. And that problem is that today’s popular raster image formats—PNG, JPEG, GIF—can’t be both low resolution and high resolution at the same. We need an image file format that is, in essence, a storage locker.

Storing Resolutions

The popular .mp3 file format isn’t just any bits of ones and zeros detailing music. It’s actually a meta data information inside an audio tag. This is where, for example, in iTunes record song information like song title, artist, album title, year the song came out and so on.

We need to have a file format for images that’s similar. Instead of capturing meta information for the image, we store different variations of the image. One “image” file might be able to contain a thumbnail image, a mobile friendly image, desktop friendly version, retina display version, and print-friendly image. This responsive image format isn’t something that’s a dream. An image file format already exists that does this called FlashPix.

Developed in 1996 by partners like Eastman Kodak, Micrsofot and Hewlett-Packard, the image file format was ahead of its time.

Benefits of Responsive Image Format

A responsive image format allows the continued use of the img element which is ingrained into the bones, the very marrow, of the Web. There isn’t a need to craft multiple lines of HTML to make one image show up in a web page. Secondly, there’s a simple reason why strict coding styles of XHTML was abandoned and loose HTML4 coding practices were instilled into HTML5—95% of websites don’t validate.

Asking web designers, bloggers, and non-techies to create multiple versions of their images in order to appease every Android, iOS device and desktop browser seems not only like a very non-standards approach, it’s also not a very practical one. Content producers that work with the web at least a little bit know the fundamental one-to-one aspect when it comes to publishing images on the web: one img element somewhat coded correctly results in one image showing up in the browser.

If we go with a solution born from the kin of video and audio elements–where we do need to balance differing file supoprt due to the browser venders’ turf wars and licensing issues, I believe we surrender a bit of the Open Web mentality for not much gain.

Content Publishers That Don’t Code

Another issue is that with a method for inserting images with additional markup means there needs to be widespread change in WYSIWYG editors, their respetive tool bars in Content Management Systems, updated old web pages. That simply is not going to happen. There need something on mini-Y2K levels (see http://www.computerworld.com/s/article/9142555/Y2K_The_good_the_bad_and_the_crazy) to get companies and organizations to start spending that sort of capital to fix the issue. And while retina display is cool, I don’t think this issue rises to that level of concern of blink red light, mission critcial as Y2K did for businesses and governments all over the world.

Save Once, Images Everywhere

If given a choice, I believe web designers would rather export one piece of artwork from Fireworks, Photoshop or whatever their favorite image editor of choice happens to be and then let the software compile multiple resolutions into one container file. This container file can then be stored on a server and referenced via an img element in an HTML page. The simple <img> got us this far and it hasn’t failed us yet. Let’s look to make image formats work smarter, work better by building smarter browsers and servers.

The web needs an image format that, when asked by a browser the server would deliver the right image that contains the right resolution. We need an image format that can work in tandem with server and browser to determine the approprirate resolution. A new image format for web design isn’t impossible. It just feels like that sometimes.


Posted on 1:53 AM | Categories:

Tuesday, November 20, 2012

JavaScript Devs: Be Careful With Comparison Operators

The results of type coercion in JavaScript can be difficult to predict, even when you know the rules. In this post, we will see how subtle differences in comparisons, can lead to significant changes in the results. Be careful when relying on 'truthyness' for logic. Whenever possible, use comparison operators to clarify your meaning. 'Falsy' values include:

0
undefined
null
empty strings
false

CAUTION - Boolean objects instantiated with new Boolean(false) are 'truthy' because they're objects, and objects are truthy! In order to test against them, you need to use the .valueOf() method. It's better in almost all cases to use true and false, instead.



Empty objects and empty arrays are truthy, including objects created with new Boolean(false).

Wrong: Don't use new Boolean()

var myBool = new Boolean(false);
test('Boolean object', function () {
  ok(!myBool, 'Should be falsy'); // Fails
  ok(!myBool.valueOf(),
    'Should be falsy.'); // Passes
});


Right: Use true or false in your boolean declarations

var myBool = false;
test('Boolean object', function () {
  ok(!myBool, '!myBool should be false.');
});


The following series of tests are meant to demonstrate how different types of comparisons in JavaScript that look similar can deliver very different results.

Always be careful that you're using the correct test for your situation:

function truthy(x) {
  if (x) {
    return true;
  } else {
    return false;
  }
}


test('Truthy', function () {
  // Falsy
  equal(truthy(0), true, 'truthy(0)'); // Fail
  equal(truthy(''), true, "truthy('')");  // Fail
  equal(truthy(null), true, 'truthy(null)'); // Fail
  equal(truthy(undefined), true,
    'truthy(undefined)'); // Fail
  equal(truthy(false), true, 'truthy(false)'); // Fail

  // Truthy
  equal(truthy('0'), true, "truthy('0')"); // Pass
  equal(truthy(new Boolean(false)), true,
    'truthy(new Boolean(false))'); // Pass
  equal(truthy({}), true, 'truthy({})'); // Pass
  equal(truthy([]), true, 'truthy([])'); // Pass
  equal(truthy([0]), true, 'truthy([0])'); // Pass
  equal(truthy([1]), true, 'truthy([1])'); // Pass
  equal(truthy(['0']), true, "truthy(['0'])"); // Pass
  equal(truthy(['1']), true, "truthy(['1'])"); // Pass
});


These are the falsy and truthy values we'll use as a baseline for a series of other comparisons.

CAUTION - Often, developers will use if (x) when they really want to see if the value has been set at all. This is especially problematic when 0, empty strings, or false are valid values. In that case, you want the test to pass as long as the expression evaluates to anything other than null or undefined. A good rule of thumb is to only use if (x) to evaluate booleans or the existence of objects or arrays.

function exists(x) {
  if (x !== undefined && x !== null) {
    return true;
  } else {
    return false;
  }
}


test('exists', function () {
  // Falsy
  equal(exists(0), true, 'exists(0)'); // Pass
  equal(exists(''), true, "exists('')"); // Pass
  equal(exists(null), true, 'exists(null)');
  equal(exists(undefined), true, 'exists(undefined)');
  equal(exists(false), true, 'exists(false)'); // Pass

  // Truthy
  equal(exists('0'), true, "exists('0')"); // Pass
  equal(exists(new Boolean(false)), true,
    'exists(new Boolean(false))'); // Pass
  equal(exists({}), true, 'exists({})'); // Pass
  equal(exists([]), true, 'exists([])'); // Pass
  equal(exists([0]), true, 'exists([0])'); // Pass
  equal(exists([1]), true, 'exists([1])'); // Pass
  equal(exists(['0']), true, "exists(['0'])"); // Pass
  equal(exists(['1']), true, "exists(['1'])"); // Pass
});


Of course, a shorter version of that function will return the same results:

function exists(x) {
  return (x !== undefined && x !== null);
}


CAUTION - The == operator can return some problematic results due to type coercion.

For example, say you're checking an array to be sure it contains a valid price, and some items cost $0.00. Your code could fail because ['0.00'] == false. Use === instead.

var isFalse = function isFalse(x) {
  return (x == false);
};


test('isFalse using ==', function () {
  // Falsy
  equal(isFalse(0), true, 'isFalse(0)'); // Pass
  equal(isFalse(''), true, "isFalse('')"); // Pass
  equal(isFalse(null), true, 'isFalse(null)'); // Fail
  equal(isFalse(undefined), true, 'isFalse(undefined)'); // Fail
  equal(isFalse(false), true, 'isFalse(false)'); // Pass


  // Truthy
  equal(isFalse('0'), true, "isFalse('0')"); // Pass
  equal(isFalse(new Boolean(false)), true,
    'isFalse(new Boolean(false))'); // Pass
  equal(isFalse({}), true, 'isFalse({})'); // Fail
  equal(isFalse([]), true, 'isFalse([])'); // Pass
  equal(isFalse([0]), true, 'isFalse([0])'); // Pass
  equal(isFalse([1]), true, 'isFalse([1])'); // Fail
  equal(isFalse(['0']), true, "isFalse(['0'])"); // Pass
  equal(isFalse(['1']), true, "isFalse(['1'])"); // Fail
});


The following code will only return true if x is actually set to false:

var isFalse = function isFalse(x) {
  return (x === false);
};


The following function is dangerous, because it will return true for 1, [1], and ['1'].

var isTrue = function isTrue(x) {
  return (x == true);
};


Use === instead to eliminate the possibility of false positives.

Remember that if (x) will always return true when x is an object -- even if the object is empty. It's common to use ducktyping when you examine objects. (If it walks like a duck and talks like a duck, treat it like a duck.) The idea is similar to using feature detection in browsers, instead of running checks against the browser string. Ducktyping is feature detection for objects.

if (typeof foo.bar === 'function') {
  foo.bar();
}