mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-03-09 15:40:18 +00:00
update noVNC to 1.5.0
Signed-off-by: si458 <simonsmith5521@gmail.com>
This commit is contained in:
parent
b20e51561a
commit
1139a37338
34 changed files with 1730 additions and 1036 deletions
|
@ -11,131 +11,136 @@ 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) {
|
||||
let segment = this._readSegment(sock);
|
||||
if (segment === null) {
|
||||
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;
|
||||
// End of image?
|
||||
if (segment[1] === 0xD9) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let huffmanTables = [];
|
||||
let quantTables = [];
|
||||
for (let segment of this._segments) {
|
||||
let type = segment[1];
|
||||
if (type === 0xC4) {
|
||||
// Huffman tables
|
||||
huffmanTables.push(segment);
|
||||
} else if (type === 0xDB) {
|
||||
// Quantization tables
|
||||
quantTables.push(segment);
|
||||
}
|
||||
}
|
||||
|
||||
const sofIndex = this._segments.findIndex(
|
||||
x => x[1] == 0xC0 || x[1] == 0xC2
|
||||
);
|
||||
if (sofIndex == -1) {
|
||||
throw new Error("Illegal JPEG image without SOF");
|
||||
}
|
||||
|
||||
if (quantTables.length === 0) {
|
||||
this._segments.splice(sofIndex+1, 0,
|
||||
...this._cachedQuantTables);
|
||||
}
|
||||
if (huffmanTables.length === 0) {
|
||||
this._segments.splice(sofIndex+1, 0,
|
||||
...this._cachedHuffmanTables);
|
||||
}
|
||||
|
||||
let length = 0;
|
||||
for (let segment of this._segments) {
|
||||
length += segment.length;
|
||||
}
|
||||
|
||||
let data = new Uint8Array(length);
|
||||
length = 0;
|
||||
for (let segment of this._segments) {
|
||||
data.set(segment, length);
|
||||
length += segment.length;
|
||||
}
|
||||
|
||||
display.imageRect(x, y, width, height, "image/jpeg", data);
|
||||
|
||||
if (huffmanTables.length !== 0) {
|
||||
this._cachedHuffmanTables = huffmanTables;
|
||||
}
|
||||
if (quantTables.length !== 0) {
|
||||
this._cachedQuantTables = quantTables;
|
||||
}
|
||||
|
||||
this._segments = [];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_readSegment(sock) {
|
||||
if (sock.rQwait("JPEG", 2)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let marker = sock.rQshift8();
|
||||
if (marker != 0xFF) {
|
||||
throw new Error("Illegal JPEG marker received (byte: " +
|
||||
marker + ")");
|
||||
}
|
||||
let type = sock.rQshift8();
|
||||
if (type >= 0xD0 && type <= 0xD9 || type == 0x01) {
|
||||
// No length after marker
|
||||
return new Uint8Array([marker, type]);
|
||||
}
|
||||
|
||||
if (sock.rQwait("JPEG", 2, 2)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let length = sock.rQshift16();
|
||||
if (length < 2) {
|
||||
throw new Error("Illegal JPEG length received (length: " +
|
||||
length + ")");
|
||||
}
|
||||
|
||||
if (sock.rQwait("JPEG", length-2, 4)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let extra = 0;
|
||||
if (type === 0xDA) {
|
||||
// start of scan
|
||||
extra += 2;
|
||||
while (true) {
|
||||
if (sock.rQwait("JPEG", length-2+extra, 4)) {
|
||||
return null;
|
||||
}
|
||||
let data = sock.rQpeekBytes(length-2+extra, false);
|
||||
if (data.at(-2) === 0xFF && data.at(-1) !== 0x00 &&
|
||||
!(data.at(-1) >= 0xD0 && data.at(-1) <= 0xD7)) {
|
||||
extra -= 2;
|
||||
break;
|
||||
}
|
||||
extra++;
|
||||
}
|
||||
}
|
||||
|
||||
let segment = new Uint8Array(2 + length + extra);
|
||||
segment[0] = marker;
|
||||
segment[1] = type;
|
||||
segment[2] = length >> 8;
|
||||
segment[3] = length;
|
||||
segment.set(sock.rQshiftBytes(length-2+extra, false), 4);
|
||||
|
||||
return segment;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue