Last active
August 29, 2015 14:20
-
-
Save arcollector/71be4048fc5a9e1980e5 to your computer and use it in GitHub Desktop.
BMP file creation in js
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
function long2LittleEndian( val ) { | |
return new Uint8Array( [ val & 0x000000ff, (val & 0x0000ff00) >> 8, (val & 0x00ff0000) >> 16, (val & 0xff000000) >> 24 ] ); | |
} | |
function bmp( width, height, canvas ) { | |
var extraBytes = width % 4, | |
canvaSize = height*(width*3 + extraBytes), | |
fileSize = 54 + canvaSize, | |
fz = long2LittleEndian( fileSize ), | |
w = long2LittleEndian( width ), | |
h = long2LittleEndian( height ), | |
data = new Uint8Array( fileSize ); | |
data.set( [ | |
66,77, // 'BM' | |
fz[0],fz[1],fz[2],fz[3], // file size in long in little endian | |
0,0, // always 0 | |
0,0, // always 0 | |
54,0,0,0, // canvas image starting address, 54 for 24 bits images | |
40,0,0,0, // header size, always 40 | |
w[0],w[1],w[2],w[3], // width in long in little endian | |
h[0],h[1],h[2],h[3], // height | |
1,0, // image planes, always 1 | |
24,0, // 24 bits color depth | |
0,0,0,0, // compression type, 0 for uncompressed | |
0,0,0,0, // ignore these fields | |
0,0,0,0, | |
0,0,0,0, | |
0,0,0,0, | |
0,0,0,0, | |
], 0 ); | |
var x, y, | |
i, address, | |
canvasBMP = new Uint8Array( canvaSize ); | |
for( i = 0, y = height - 1; y >= 0; y-- ) { | |
for( x = 0; x < width; x++ ) { | |
address = 4*(y*width + x); | |
canvasBMP[i++] = canvas[address + 2]; | |
canvasBMP[i++] = canvas[address + 1]; | |
canvasBMP[i++] = canvas[address]; | |
} | |
for( x = 0; x < extraBytes; x++ ) { | |
canvasBMP[i++] = 0; | |
} | |
} | |
data.set( canvasBMP, 54 ); | |
return data; | |
} | |
function download( arrayBuffer ) { | |
var $a = document.createElement( 'a' ); | |
$a.setAttribute( 'download', +new Date() + '.bmp' ); | |
$a.setAttribute( 'href', URL.createObjectURL( new Blob( [ arrayBuffer ], { type: 'application/octet-binary' } ) ) ); | |
$a.style.display = 'none'; | |
document.body.appendChild( $a ); | |
$a.click(); | |
document.body.removeChild( $a ); | |
} | |
function randomImage( width, height ) { | |
var canvas = new Uint8Array( width*height*4 ), | |
i, r, g, b, x, y, | |
left, top, bottom, right, maxX, maxY, | |
blockSize = 16, address, | |
rows = Math.ceil( height/blockSize ), | |
cols = Math.ceil( width/blockSize ); | |
for( i = 0; i < rows*cols; i++ ) { | |
r = ~~(Math.random() * 256); | |
g = ~~(Math.random() * 256); | |
b = ~~(Math.random() * 256); | |
left = ~~(i/rows)*blockSize; | |
top = ~~(i%rows)*blockSize; | |
right = blockSize + left; | |
bottom = blockSize + top; | |
maxY = Math.min( bottom, height ); | |
maxX = Math.min( right, width ); | |
for( y = top; y < maxY; y++ ) { | |
address = 4*(y*width + left); | |
for( x = left; x < maxX; x++ ) { | |
canvas[address++] = r; | |
canvas[address++] = g; | |
canvas[address++] = b; | |
canvas[address++] = 255; | |
} | |
} | |
} | |
// DEBUG | |
var $canvas = document.createElement( 'canvas' ); | |
$canvas.width = width; | |
$canvas.height = height; | |
var ctx = $canvas.getContext( '2d' ); | |
var image = ctx.getImageData( 0,0, width, height ); | |
for( var i = 0, j = 0; i < canvas.length; ) { | |
image.data[i++] = canvas[j++]; | |
image.data[i++] = canvas[j++]; | |
image.data[i++] = canvas[j++]; | |
image.data[i++] = canvas[j++]; | |
} | |
ctx.putImageData( image, 0,0 ); | |
document.body.appendChild( $canvas ); | |
return canvas; | |
} | |
width = 1920; | |
height = 1080; | |
download( bmp( width, height, randomImage( width, height ) ) ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment