Created
December 5, 2019 18:35
-
-
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!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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