importScripts('zlib.js');
|
importScripts('png.js');
|
importScripts('ElevDecompress.js');
|
importScripts('jpglib2.js');
|
|
|
self.addEventListener('message', function (e) {
|
|
var data = e.data;
|
|
data.rejected = false;
|
//data.zeroLevel = false; //for rejected data (when using MPT) - There are 6 mpt requests at the begining that should not be parsed for elevation. Nevertheless, we MUST NOT mark them as unavailiable tiles.
|
|
if (isPNG(data)) {
|
var png = new PNG(new Uint8Array(data.buffer));
|
|
//postMessage(JSON.stringify({ type: 'debug', msg: data.deferedId + " 1" }));
|
var pixels = png.decodePixels();
|
var out = new Int16Array(pixels.length / 2);
|
|
for (var i = 0; i < pixels.length / 2; i++) {
|
|
out[i] = (pixels[i * 2] << 8 | pixels[i * 2 + 1]);
|
// -1 is null value, do not change
|
if (out[i] != 65535) // -1 sint16
|
out[i] = out[i] * 0.3048;
|
}
|
data.buffer = out;
|
postMessage(data/*, [data.buffer.buffer]*/);
|
}
|
else if (isMPT(data)) {
|
var bBoxSize = 96;
|
var dv = new DataView(data.buffer);
|
var dataBeginOffset = dv.getUint32(64, true);
|
var dataSize = dv.getUint32(68, true);
|
var extend = dv.getUint32(72, true);
|
var parts = dv.getUint32(76, true);
|
var sizeColor = (dv.getUint32(bBoxSize + 4, true) & 0xffffff) - (dv.getUint32(bBoxSize + 0, true) & 0xffffff);
|
var sizeElevation = (dv.getUint32(bBoxSize + 8, true) & 0xffffff) - (dv.getUint32(bBoxSize + 4, true) & 0xffffff);
|
var dataStreamBegin = bBoxSize + sizeColor + dataBeginOffset;
|
var channelOffset = (dv.getUint32(dataStreamBegin + 0, true) & 0x00FFFFFF); //16
|
var channelType = dv.getUint32(dataStreamBegin + 4, true);
|
var channelData = String.fromCharCode((channelType) >> 24);
|
var dataStartPoint = dataStreamBegin + channelOffset;
|
var dataEndPoint = dataStartPoint + sizeElevation;
|
|
if (channelData == 'N') { // PNG16.8
|
var result = PNG16_8Decompress(data.buffer.slice(dataStartPoint, dataEndPoint));
|
data.buffer = result;
|
postMessage(data);
|
}
|
else if (channelData == 'B') { //JPEG
|
var result = JPEGDecompress(data.buffer.slice(dataStartPoint, dataEndPoint));
|
var out = new Uint16Array(result.byteLength);
|
for (var i = 0; i < 256 * 256; i++) {
|
var value = Math.fmod(result[i], Math.pow(2, 32));
|
if (value != 65535) {
|
out[i] = value;
|
}
|
}
|
data.buffer = out;
|
postMessage(data);
|
}
|
else if (channelData == 'A') { //PNG16
|
var out = PNGDecompress(data.buffer.slice(dataStartPoint, dataEndPoint));
|
data.buffer = out;
|
postMessage(data);
|
|
} else { // debugging and other formats currently not supported
|
|
//var len = this.heightMapWidth * this.heightMapHeight;
|
//var buf = new Int16Array(len);
|
//var val = 0;
|
//for (var i = 0; i < len; i++)
|
// buf[i] = val;
|
|
//data.buffer = buf;
|
//postMessage(data/*, [data.buffer.buffer]*/);
|
}
|
}
|
|
else {
|
|
// I dont know. reject.
|
|
data.rejected = true;
|
postMessage(data);
|
}
|
|
|
});
|
|
|
function isPNG(data) {
|
|
if (data.buffer.byteLength > 2) {
|
var PNGArray = new Uint8Array(data.buffer.byteLength > 0 ? data.buffer.slice(1, 4) : 0);
|
var _isPNG = ((PNGArray.length == 0) || (PNGArray[0] == 'P'.charCodeAt() && PNGArray[1] == 'N'.charCodeAt() && PNGArray[2] == 'G'.charCodeAt()));
|
return _isPNG;
|
}
|
return false;
|
}
|
|
function isMPT(data) {
|
|
if (data.buffer.byteLength > 80) {
|
var bBoxSize = 96;
|
var dv = new DataView(data.buffer);
|
var dataBeginOffset = dv.getUint32(64, true);
|
var dataSize = dv.getUint32(68, true);
|
var extend = dv.getUint32(72, true);
|
var parts = dv.getUint32(76, true);
|
|
if (parts == 1) // There should be only one part
|
return true;
|
else
|
return false;
|
}
|
return false;
|
}
|
|
|
//fmod
|
Math.fmod = function (a, b) { return Number((a - (Math.floor(a / b) * b)).toPrecision(8)); };
|
|
//random buffer should not be used... only for debugging
|
function getRandomIntInclusive(min, max) {
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
}
|
|
//decompress JPEG - use jpglib2.js
|
function JPEGDecompress(array) {
|
|
var minval = 0;
|
var maxval = 0;
|
var m_prelist;
|
|
var byteArray = new Uint8Array(array);
|
|
var dvJPEG = new DataView(byteArray.buffer);
|
minval = dvJPEG.getFloat32(0,true);
|
maxval = dvJPEG.getFloat32(4, true);
|
|
m_prelist = byteArray.slice(8, 8 + 256); // 2* sizeof(float) + PRE_LISTSIZE
|
|
var buffer8 = byteArray.slice(256 + 8, byteArray.byteLength);
|
|
var jpegDecompressed = decode(buffer8, true, 1);
|
|
if (!isNaN(jpegDecompressed.data[0])) {
|
var jpegElev = new JPEGElevDecompress();
|
var result = jpegElev.ElevDecompress(jpegDecompressed, m_prelist, minval, maxval);
|
return result;
|
} else {
|
|
console.error("Error while JPEG Decompressing");
|
}
|
|
}
|
|
//decompress png - use png.js library
|
function PNGDecompress(array) {
|
|
var byteArray = new Uint8Array(array);
|
|
var dvPNG = new DataView(array);
|
|
var min = dvPNG.getFloat32(0, true);
|
var max = dvPNG.getFloat32(4, true);
|
var delta = max - min;
|
|
var slicedArray = byteArray.slice(8, byteArray.buffer.byteLength);
|
|
var png = new PNG(new Uint8Array(slicedArray));
|
var pixels = png.decodePixels();
|
|
|
var out = new Float32Array(pixels.length / 2);
|
|
var dvwords = new DataView(pixels.buffer);
|
|
|
for (var i = 0; i < pixels.length / 2; i++) {
|
out[i] = dvwords.getUint16(i * 2);
|
//out[i] = ( pixels[i*2]<<8 | pixels[i*2+1] );
|
if (out[i] != 65535) // -1 sint
|
out[i] = out[i] * delta/65535.0 + min;
|
}
|
|
return out;
|
}
|
|
|
|
// decompress PNG16.8
|
function PNG16_8Decompress(array) {
|
var sizeOne = 0;
|
var sizeTwo = 0;
|
|
var byteArray = new Uint8Array(array);
|
|
var dv168 = new DataView(byteArray.buffer);
|
|
sizeOne = dv168.getUint32(0,true);
|
sizeTwo = dv168.getUint32(4,true);
|
|
var channelSizeN = 8 + sizeOne + sizeTwo;
|
|
//first buffer (words)
|
var firstBuffer = byteArray.slice(8, 8 + sizeOne);
|
var firstPNG = new PNG(new Uint8Array(firstBuffer));
|
var pixels = firstPNG.decodePixels();
|
var pixels1View = new DataView(pixels.buffer);
|
|
//second buffer (bytes)
|
var secondBuffer = byteArray.slice(8 + sizeOne,channelSizeN);
|
var secondPNG = new PNG(new Uint8Array(secondBuffer));
|
var pixels2 = secondPNG.decodePixels();
|
var pixels2View = new DataView(pixels.buffer);
|
|
var floatArray = new Float32Array(256*256);
|
var feet2meter = 0.3048;
|
for (var iii = 0; iii < 256; iii++)
|
for (var jjj = 0; jjj < 256 ; jjj++) {
|
floatArray[jjj + iii * 256] = (pixels1View.getInt16((jjj + iii * 256)*2) + pixels2[jjj + iii * 256] / 256) * feet2meter;
|
}
|
return floatArray;
|
}
|