Skip to content

Instantly share code, notes, and snippets.

@bbars
Created December 5, 2019 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbars/6b469e3c59e749000f01a7c6108a7436 to your computer and use it in GitHub Desktop.
Save bbars/6b469e3c59e749000f01a7c6108a7436 to your computer and use it in GitHub Desktop.
Generate proper header and append pixel colors - and you have a valid BMP image just for free!
var bytes = [
0xff0000, 0x00ff00, 0x0000ff,
0x0000cc, 0xcc0000, 0x00cc00,
0x00ee00, 0x0000ee, 0xee0000,
];
var img = pixelsToImage(bytes);
console.log(img.src);
img.width = 90;
img.height = 90;
img.style.imageRendering = 'pixelated';
document.body.appendChild(img);
////
//// Functions:
////
function genBmpHeader(w, h, bpp, pad, size) {
pad = pad || 0;
var buffer = new ArrayBuffer(14
+ 40 // + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4
);
var view = new DataView(buffer);
// BM
view.setInt8(0x00, 0x42, true);
view.setInt8(0x01, 0x4d, true);
// File size
view.setInt32(0x02, buffer.byteLength + pad + size, true);
// Pixel data offset
view.setInt32(0x0a, buffer.byteLength + pad, true);
// 0E 14 4 the size of this header, in bytes (40)
view.setInt32(0x0e, 40, true);
// 12 18 4 the bitmap width in pixels (signed integer)
// 16 22 4 the bitmap height in pixels (signed integer)
view.setInt32(0x12, w, true);
view.setInt32(0x16, h, true);
// 1A 26 2 the number of color planes (must be 1)
view.setInt16(0x1a, 1, true);
// 1C 28 2 the number of bits per pixel, which is the color depth of the image. Typical values are 1, 4, 8, 16, 24 and 32.
view.setInt16(0x1c, bpp, true);
// 1E 30 4 the compression method being used. See the next table for a list of possible values
view.setInt32(0x1e, 0, true);
// 22 34 4 the image size. This is the size of the raw bitmap data; a dummy 0 can be given for BI_RGB bitmaps.
view.setInt32(0x22, size, true);
// 26 38 4 the horizontal resolution of the image. (pixel per metre, signed integer)
// 2A 42 4 the vertical resolution of the image. (pixel per metre, signed integer)
view.setInt32(0x26, 2835, true);
view.setInt32(0x2a, 2835, true);
// 2E 46 4 the number of colors in the color palette, or 0 to default to 2n
// 32 50 4 the number of important colors used, or 0 when every color is important; generally ignored
view.setInt32(0x2e, 0, true);
view.setInt32(0x32, 0, true);
return String.fromCharCode.apply(null, new Uint8Array(buffer));
}
function pixelsToImage(ints) {
let W = Math.sqrt(ints.length) | 0;
let pixelData = ints.map((b, i) => {
let bp = String.fromCharCode((b>>0)&0xff, (b>>8)&0xff, (b>>16)&0xff, (b>>24)&0xff);
return bp;
}).join('');
let header = '';
let img = new Image();
let pad = new Array(0).fill('_');
img.src = 'data:image/bmp;base64,' + btoa(genBmpHeader(W, -W, 32, pad.length, pixelData.length) + pad) + btoa(pixelData);
return img;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment