web-apps/apps/common/mobile/utils/CThumbnailLoader.js
2022-06-20 21:59:40 +03:00

174 lines
6.1 KiB
JavaScript

class CThumbnailLoader {
constructor() {
this.image = null;
this.binaryFormat = null;
this.data = null;
this.width = 0;
this.heightOne = 0;
this.offsets = null;
}
load(url, callback) {
if (!callback)
return;
let xhr = new XMLHttpRequest();
xhr.open('GET', url + ".bin", true);
xhr.responseType = 'arraybuffer';
if (xhr.overrideMimeType)
xhr.overrideMimeType('text/plain; charset=x-user-defined');
else xhr.setRequestHeader('Accept-Charset', 'x-user-defined');
xhr.onload = e => {
// TODO: check errors
this.binaryFormat = new Uint8Array(e.target.response);
callback();
};
xhr.send(null);
}
_openBinary(arrayBuffer) {
//var t1 = performance.now();
const binaryAlpha = this.binaryFormat;
this.width = (binaryAlpha[0] << 24) | (binaryAlpha[1] << 16) | (binaryAlpha[2] << 8) | (binaryAlpha[3] << 0);
this.heightOne = (binaryAlpha[4] << 24) | (binaryAlpha[5] << 16) | (binaryAlpha[6] << 8) | (binaryAlpha[7] << 0);
const count = (binaryAlpha[8] << 24) | (binaryAlpha[9] << 16) | (binaryAlpha[10] << 8) | (binaryAlpha[11] << 0);
const height = count * this.heightOne;
const MAX_MEMORY_SIZE = 100000000;
const memorySize = 4 * this.width * height;
const isOffsets = memorySize > MAX_MEMORY_SIZE;
if (!isOffsets)
this.data = new Uint8ClampedArray(memorySize);
else this.offsets = new Array(count);
var binaryIndex = 12;
var binaryLen = binaryAlpha.length;
var index = 0;
var len0 = 0;
var tmpValue = 0;
if (!isOffsets) {
var imagePixels = this.data;
while (binaryIndex < binaryLen) {
tmpValue = binaryAlpha[binaryIndex++];
if (0 == tmpValue) {
len0 = binaryAlpha[binaryIndex++];
while (len0 > 0) {
len0--;
imagePixels[index] = imagePixels[index + 1] = imagePixels[index + 2] = 255;
imagePixels[index + 3] = 0; // this value is already 0.
index += 4;
}
} else {
imagePixels[index] = imagePixels[index + 1] = imagePixels[index + 2] = 255 - tmpValue;
imagePixels[index + 3] = tmpValue;
index += 4;
}
}
} else {
var module = this.width * this.heightOne;
var moduleCur = module - 1;
while (binaryIndex < binaryLen) {
tmpValue = binaryAlpha[binaryIndex++];
if (0 == tmpValue) {
len0 = binaryAlpha[binaryIndex++];
while (len0 > 0) {
len0--;
moduleCur++;
if (moduleCur === module) {
this.offsets[index++] = { pos : binaryIndex, len : len0 + 1 };
moduleCur = 0;
}
}
} else {
moduleCur++;
if (moduleCur === module) {
this.offsets[index++] = { pos : binaryIndex - 1, len : -1 };
moduleCur = 0;
}
}
}
}
if ( !this.offsets )
delete this.binaryFormat;
//var t2 = performance.now();
//console.log(t2 - t1);
};
getImage = function(index, canvas, ctx) {
if (!canvas) {
canvas = document.createElement("canvas");
canvas.width = this.width;
canvas.height = this.heightOne;
canvas.style.width = iconWidth + "px";
canvas.style.height = iconHeight + "px";
ctx = canvas.getContext("2d");
}
if (!this.data && !this.offsets) {
this._openBinary(this.binaryFormat);
}
let dataTmp = ctx.createImageData(this.width, this.heightOne);
const sizeImage = 4 * this.width * this.heightOne;
if (!this.offsets) {
dataTmp.data.set(new Uint8ClampedArray(this.data.buffer, index * sizeImage, sizeImage));
} else {
const binaryAlpha = this.binaryFormat;
var binaryIndex = this.offsets[index].pos;
var alphaChannel = 0;
var pixelsCount = this.width * this.heightOne;
var tmpValue = 0, len0 = 0;
let imagePixels = dataTmp.data;
if (-1 != this.offsets[index].len) {
/*
// this values is already 0.
for (var i = 0; i < this.offsets[index].len; i++) {
pixels[alphaChannel] = 0;
alphaChannel += 4;
}
*/
alphaChannel += 4 * this.offsets[index].len;
}
while (pixelsCount > 0) {
tmpValue = binaryAlpha[binaryIndex++];
if (0 == tmpValue) {
len0 = binaryAlpha[binaryIndex++];
if (len0 > pixelsCount)
len0 = pixelsCount;
while (len0 > 0) {
len0--;
imagePixels[alphaChannel] = imagePixels[alphaChannel + 1] = imagePixels[alphaChannel + 2] = 255;
imagePixels[alphaChannel + 3] = 0; // this value is already 0.
alphaChannel += 4;
pixelsCount--;
}
} else {
imagePixels[alphaChannel] = imagePixels[alphaChannel + 1] = imagePixels[alphaChannel + 2] = 255 - tmpValue;
imagePixels[alphaChannel + 3] = tmpValue;
alphaChannel += 4;
pixelsCount--;
}
}
}
ctx.putImageData(dataTmp, 0, 0);
//var t2 = performance.now();
//console.log(t2 - t1);
return canvas;
};
};
export default CThumbnailLoader;