mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-30 17:13:19 -05:00
142 lines
5.0 KiB
JavaScript
142 lines
5.0 KiB
JavaScript
/*
|
|
* noVNC: HTML5 VNC client
|
|
* Copyright (C) 2019 The noVNC Authors
|
|
* Licensed under MPL 2.0 (see LICENSE.txt)
|
|
*
|
|
* See README.md for usage and integration instructions.
|
|
*
|
|
*/
|
|
|
|
export default class JPEGDecoder {
|
|
constructor() {
|
|
// RealVNC will reuse the quantization tables
|
|
// and Huffman tables, so we need to cache them.
|
|
this._quantTables = [];
|
|
this._huffmanTables = [];
|
|
this._cachedQuantTables = [];
|
|
this._cachedHuffmanTables = [];
|
|
|
|
this._jpegLength = 0;
|
|
this._segments = [];
|
|
}
|
|
|
|
decodeRect(x, y, width, height, sock, display, depth) {
|
|
// A rect of JPEG encodings is simply a JPEG file
|
|
if (!this._parseJPEG(sock.rQslice(0))) {
|
|
return false;
|
|
}
|
|
const data = sock.rQshiftBytes(this._jpegLength);
|
|
if (this._quantTables.length != 0 && this._huffmanTables.length != 0) {
|
|
// If there are quantization tables and Huffman tables in the JPEG
|
|
// image, we can directly render it.
|
|
display.imageRect(x, y, width, height, "image/jpeg", data);
|
|
return true;
|
|
} else {
|
|
// Otherwise we need to insert cached tables.
|
|
const sofIndex = this._segments.findIndex(
|
|
x => x[1] == 0xC0 || x[1] == 0xC2
|
|
);
|
|
if (sofIndex == -1) {
|
|
throw new Error("Illegal JPEG image without SOF");
|
|
}
|
|
let segments = this._segments.slice(0, sofIndex);
|
|
segments = segments.concat(this._quantTables.length ?
|
|
this._quantTables :
|
|
this._cachedQuantTables);
|
|
segments.push(this._segments[sofIndex]);
|
|
segments = segments.concat(this._huffmanTables.length ?
|
|
this._huffmanTables :
|
|
this._cachedHuffmanTables,
|
|
this._segments.slice(sofIndex + 1));
|
|
let length = 0;
|
|
for (let i = 0; i < segments.length; i++) {
|
|
length += segments[i].length;
|
|
}
|
|
const data = new Uint8Array(length);
|
|
length = 0;
|
|
for (let i = 0; i < segments.length; i++) {
|
|
data.set(segments[i], length);
|
|
length += segments[i].length;
|
|
}
|
|
display.imageRect(x, y, width, height, "image/jpeg", data);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
_parseJPEG(buffer) {
|
|
if (this._quantTables.length != 0) {
|
|
this._cachedQuantTables = this._quantTables;
|
|
}
|
|
if (this._huffmanTables.length != 0) {
|
|
this._cachedHuffmanTables = this._huffmanTables;
|
|
}
|
|
this._quantTables = [];
|
|
this._huffmanTables = [];
|
|
this._segments = [];
|
|
let i = 0;
|
|
let bufferLength = buffer.length;
|
|
while (true) {
|
|
let j = i;
|
|
if (j + 2 > bufferLength) {
|
|
return false;
|
|
}
|
|
if (buffer[j] != 0xFF) {
|
|
throw new Error("Illegal JPEG marker received (byte: " +
|
|
buffer[j] + ")");
|
|
}
|
|
const type = buffer[j+1];
|
|
j += 2;
|
|
if (type == 0xD9) {
|
|
this._jpegLength = j;
|
|
this._segments.push(buffer.slice(i, j));
|
|
return true;
|
|
} else if (type == 0xDA) {
|
|
// start of scan
|
|
let hasFoundEndOfScan = false;
|
|
for (let k = j + 3; k + 1 < bufferLength; k++) {
|
|
if (buffer[k] == 0xFF && buffer[k+1] != 0x00 &&
|
|
!(buffer[k+1] >= 0xD0 && buffer[k+1] <= 0xD7)) {
|
|
j = k;
|
|
hasFoundEndOfScan = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasFoundEndOfScan) {
|
|
return false;
|
|
}
|
|
this._segments.push(buffer.slice(i, j));
|
|
i = j;
|
|
continue;
|
|
} else if (type >= 0xD0 && type < 0xD9 || type == 0x01) {
|
|
// No length after marker
|
|
this._segments.push(buffer.slice(i, j));
|
|
i = j;
|
|
continue;
|
|
}
|
|
if (j + 2 > bufferLength) {
|
|
return false;
|
|
}
|
|
const length = (buffer[j] << 8) + buffer[j+1] - 2;
|
|
if (length < 0) {
|
|
throw new Error("Illegal JPEG length received (length: " +
|
|
length + ")");
|
|
}
|
|
j += 2;
|
|
if (j + length > bufferLength) {
|
|
return false;
|
|
}
|
|
j += length;
|
|
const segment = buffer.slice(i, j);
|
|
if (type == 0xC4) {
|
|
// Huffman tables
|
|
this._huffmanTables.push(segment);
|
|
} else if (type == 0xDB) {
|
|
// Quantization tables
|
|
this._quantTables.push(segment);
|
|
}
|
|
this._segments.push(segment);
|
|
i = j;
|
|
}
|
|
}
|
|
}
|