Created
October 8, 2010 01:56
-
-
Save reklis/616240 to your computer and use it in GitHub Desktop.
working bmp decoding
This file contains hidden or 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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<title>fetch</title> | |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script> | |
<script src="jquery.base64.min.js" type="text/javascript"></script> | |
<!--[if IE]><script src="excanvas.compiled.js" type="text/javascript"></script><![endif]--> | |
<script src="texture2d.js" type="text/javascript"></script> | |
<script type="text/javascript"> | |
function makeNoise() { | |
var w = $("#txtWidth").val(); | |
var h = $("#txtHeight").val(); | |
var t = Texture2d.noise(w, h); | |
t.draw($("#renderingTarget")[0]); | |
} | |
function draw(data) { | |
// convert vb hex csv hackery to actual byte array | |
if (data.substring(0, 19) == "BinaryArrayToAscCSV") { | |
data = data.substring("BinaryArrayToAscCSV".length, data.length - 1).split(','); | |
} | |
var bmp = new BitmapDecoder(); | |
var texture = bmp.decode(data, true); | |
texture.draw($("#renderingTarget")[0]); | |
} | |
function makeXMLHttpRequest() { | |
if (window.XMLHttpRequest) { | |
return new window.XMLHttpRequest; | |
} | |
else { | |
try { | |
return new ActiveXObject("MSXML2.XMLHTTP.3.0"); | |
} | |
catch (ex) { | |
return null; | |
} | |
} | |
} | |
function fetchBmp() { | |
// $.get('http://localhost:3168/experimental/imgrender/beta.bmp', function (data) { | |
// draw(data); | |
// }); | |
var oReq = makeXMLHttpRequest(); | |
if (oReq != null) { | |
oReq.open("GET", "http://localhost:3168/experimental/imgrender/beta.bmp", true); | |
oReq.onreadystatechange = function () { | |
if (oReq.readyState == 4) { | |
if (oReq.status == 200) { | |
draw(oReq.responseBody); | |
} else { | |
alert("Error Code: " + oReq.status); | |
} | |
} else { | |
//alert("State Change: " + oReq.readyState); | |
} | |
} | |
oReq.send(); | |
} else { | |
window.alert("AJAX (XMLHTTP) not supported."); | |
} | |
} | |
function fetchBase64() { | |
$.get('http://localhost:3168/experimental/imgrender/beta.bmp', function (data) { | |
var base64Data = $.base64.encode(data); | |
$('#my-image').attr('src', 'data:image/bmp;base64,' + base64Data); | |
}); | |
} | |
</script> | |
<script type="text/vbscript"> | |
Function BinaryArrayToAscCSV( aBytes ) | |
Dim j, sOutput | |
sOutput = "BinaryArrayToAscCSV" | |
For j = 1 to LenB(aBytes) | |
sOutput= sOutput & AscB( MidB(aBytes,j,1) ) | |
sOutput= sOutput & "," | |
Next | |
BinaryArrayToAscCSV = sOutput | |
End Function | |
Dim objXML | |
Function objXML_onreadystatechange() | |
If (objXML.readyState = 4) Then | |
If (objXML.status = 200) Then | |
Dim hexString | |
hexString = BinaryArrayToAscCSV(objXML.responseBody) | |
draw(hexString) | |
End If | |
End If | |
End Function | |
Function btnFetchVb_OnClick() | |
Set objXML = CreateObject("MSXML2.XMLHTTP.3.0") | |
objXML.Open "GET", "http://localhost:3168/experimental/imgrender/beta.bmp", True | |
objXML.OnReadyStateChange = GetRef("objXML_onreadystatechange") | |
objXML.Send | |
End Function | |
</script> | |
</head> | |
<body> | |
<form id="frm1"> | |
<div> | |
<input id="txtWidth" type="text" value="100" /> | |
<input id="txtHeight" type="text" value="100" /> | |
</div> | |
<div> | |
<input id="btnNoise" type="button" value="Generate Noise" onclick="makeNoise()" /> | |
</div> | |
<div> | |
<input id="btnBase64" type="button" value="Fetch Base64" onclick="fetchBase64()" /> | |
<input id="btnFetch" type="button" value="Fetch BMP" onclick="fetchBmp()" /> | |
<input id="btnFetchVb" type="button" value="Fetch with VB" /> | |
</div> | |
</form> | |
<canvas id="renderingTarget"></canvas> | |
<img id="my-image" /> | |
</body> | |
</html> |
This file contains hidden or 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
Math.randInRange = function (lbounds, ubounds) { | |
return (Math.random() * ubounds) + lbounds; | |
} | |
function Texture2d(d,w,h) { | |
this._data = d; | |
this._width = w; | |
this._height = h; | |
} | |
Texture2d.noise = function (width, height) { | |
var d = []; | |
for (var x = 0; x != width; ++x) { | |
for (var y = 0; y != height; ++y) { | |
var i = (x + y * width) * 4; | |
d[i + 0] = parseInt(Math.randInRange(0, 255)); // Red channel | |
d[i + 1] = parseInt(Math.randInRange(0, 255)); // Green channel | |
d[i + 2] = parseInt(Math.randInRange(0, 255)); // Blue channel | |
d[i + 3] = parseInt(Math.randInRange(0, 255)); // Alpha channel | |
} | |
} | |
return new Texture2d(d, width, height); | |
} | |
// the one-dimensional array containing the data in RGBA order, as integers in the range 0 to 255. | |
Texture2d.prototype.data = function (d) { | |
if (undefined != d) { | |
this._data = d; | |
} | |
return this._data; | |
} | |
Texture2d.prototype.width = function (w) { | |
if (undefined != w) { | |
this._width = w; | |
} | |
return this._width; | |
} | |
Texture2d.prototype.height = function (h) { | |
if (undefined != h) { | |
this._height = h; | |
} | |
return this._height; | |
} | |
Texture2d.prototype.draw = function (canvas) { | |
ctx = canvas.getContext("2d"); | |
canvas.setAttribute('width', this.width()); | |
canvas.setAttribute('height', this.height()); | |
var w = this.width(); | |
var h = this.height(); | |
for (var x = 0; x < w; x++) { | |
for (var y = 0; y < h; y++) { | |
var i = (x + y * w) * 4; | |
var r = this._data[i + 0]; | |
var g = this._data[i + 1]; | |
var b = this._data[i + 2]; | |
var a = this._data[i + 3]; | |
ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; | |
ctx.fillRect(x, y, 1, 1); | |
} | |
} | |
} | |
function ByteStream(byteArray) { | |
if (byteArray == undefined) { | |
this._stream = []; | |
} else { | |
this._stream = byteArray; | |
} | |
this._position = 0; | |
} | |
ByteStream.prototype.position = function(p) { | |
if (undefined != p) { | |
this._position = p; | |
} | |
return this._position; | |
} | |
ByteStream.prototype.length = function() { | |
return this._stream.length; | |
} | |
ByteStream.prototype.eof = function() { | |
var l = this.length(); | |
var p = this.position(); | |
return (p >= l); | |
} | |
ByteStream.prototype.seek = function(origin, count) { | |
this.position(origin + count); | |
} | |
ByteStream.prototype.readByte = function () { | |
if (this.eof()) { | |
return undefined; | |
} | |
var p = this.position(); | |
var b = this._stream[p]; | |
this.position(p + 1); | |
// strings would be this way | |
// var c = b.charCodeAt(0); | |
// if (undefined == c) { | |
// debugger; // yikes! | |
// } | |
// return c; | |
// for byte arrays just return it | |
//return b; | |
// with hex CSV make sure we call parseInt | |
return parseInt(b); | |
} | |
ByteStream.prototype.readBytes = function (numBytes) { | |
var b = []; | |
for (var i = 0; i < numBytes; ++i) { | |
b[i] = this.readByte(); | |
} | |
return b; | |
} | |
ByteStream.prototype.readInt16 = function () { | |
var b = this.readBytes(2); | |
var i = (b[1] << 8) + b[0]; | |
return i; | |
} | |
ByteStream.prototype.readInt32 = function () { | |
var b = this.readBytes(4); | |
var i = (b[3] << 24) + (b[2] << 16) + (b[1] << 8) + b[0]; | |
return i; | |
} | |
ByteStream.prototype.readString = function (length) { | |
var b = this.readBytes(length); | |
var s = ""; | |
for (var i = 0; i < length; ++i) { | |
s += String.fromCharCode(b[i]); | |
} | |
return s; | |
} | |
function BitmapDecoder() { | |
} | |
BitmapDecoder.prototype.decode = function (byteArray) { | |
var memStream = new ByteStream(byteArray); | |
// based on http://www.dragonwins.com/bmp/bmpfileformat.htm | |
this.magic = memStream.readString(2); | |
this.fileSize = memStream.readInt32(); | |
memStream.readInt16(); // unused | |
memStream.readInt16(); // unused | |
this.dataStart = memStream.readInt32(); | |
this.headerLength = memStream.readInt32(); | |
this.width = memStream.readInt32(); | |
this.height = memStream.readInt32(); | |
this.colorPlaneCount = memStream.readInt16(); | |
this.bitsPerPixel = memStream.readInt16(); | |
this.compressionMethod = memStream.readInt32(); | |
this.rawSize = memStream.readInt32(); | |
this.horizontalResolution = memStream.readInt32(); | |
this.verticalResolution = memStream.readInt32(); | |
this.numberOfPaletteColors = memStream.readInt32(); | |
this.numberOfImportantColors = memStream.readInt32(); | |
if (memStream.position() != this.dataStart) { | |
debugger; | |
return; // corrupt header | |
} | |
var textureData = []; | |
var padding = 4 - ((this.width * 3) % 4); // scanlines are padded to ensure DWORD size | |
for (var y = this.height; y > 0; --y) { // bmp scanlines go bottom up | |
for (var x = 0; x < this.width; ++x) { | |
var pixel = memStream.readBytes(3); | |
var i = (x + y * this.width) * 4; | |
textureData[i++] = pixel[0]; // r | |
textureData[i++] = pixel[1]; // g | |
textureData[i++] = pixel[2]; // b | |
textureData[i++] = 1; // a | |
if (x == this.width-1) { | |
memStream.readBytes(padding); | |
} | |
} | |
} | |
this.texture = new Texture2d(textureData, this.width, this.height); | |
return this.texture; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment