27 January 2011
canvas element actually has this functionality built-in. I used this technique to generate images in my low res paint app and favicon creator. If you hate prose, then check out the bitmap generation source code directly.
A byte is 8 bits, 2^8 = 256 possible values, as you all know that's conveniently represented as two hex characters—0x00 is 0 and 0xff is 255.
'\xff' or even
'\xff\x00\x00' which can represent the RGB value for red.
'\x00' // 0 '\xff' // 255 '\xff\x00\x00' // the RGB value for red
'\x' + '00' != '\x00' // false '\x' + '00' === 'x00' // true - we can’t represent bytes this way
To create byte strings dynamically, you can use
- official definition: the fromCharCode() method converts Unicode values to characters.
- my usage definition: you give it a number from 0-255 and it returns that as a hex string
String.fromCharCode(255) === '\xff' // true - this is the way to do it
Note: going above 255 stops producing characters that you can use as bytes, but it still produces some fun stuff, like the snowman character:
String.fromCharCode(9731) === '☃'
So to get bytes for numbers that are larger than 255, you have to break it up into chunks and do each chunk:
String.fromCharCode(value & 255); // get the last byte using a mask value >>= 8; // then shift value to the next byte
Bitmap seemed to be the simplest image format (specifically 24-bit bitmaps—24-bit, i.e., 3-bytes, i.e., RGB), there’s no compression, it’s mostly just a map of bits—I found everything I needed to know on this wikipedia page.
Bitmaps consist of a (52 byte) header that describes stuff about the file and then rows of pixel data as RGB values
Integer values are represented as little-endian (least significant byte first)
value big-endian little-endian 266 '\x01\x0a' '\x0a\x01' red '\xff\x00\x00' '\x00\x00\xff'
Bitmap data starts at the lower left of the image (and reads across rows)
Each row of the bitmap needs to be padded to be a multiple of 4 bytes (since RGB is 3 bytes, this is very common)
The data url scheme allows you to represent pretty much any media as a string.
// data:[<mediatype>][;base64],<base64_encoded_data> var src = 'data:image/bmp;base64,' + myBase64EncodedData;
The final piece of the puzzle—
btoa()—this magically converts stuff to base64, et voilà, we have an image.
var src = 'data:image/bmp;base64,' + btoa(myData);