Skip to content

Commit

Permalink
Fix thumbnail creation on very large images or images with extreme di…
Browse files Browse the repository at this point in the history
…mensions (#332)
  • Loading branch information
schlagmichdoch committed Nov 11, 2024
1 parent ab67c58 commit 54e718a
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 21 deletions.
42 changes: 33 additions & 9 deletions public/scripts/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ class Peer {
this._filesQueue = [];
this._busy = false;

this.maxMessageSize = 65536; // 64 KB

// evaluate auto accept
this._evaluateAutoAccept();
}
Expand Down Expand Up @@ -450,14 +452,7 @@ class Peer {

Events.fire('set-progress', {peerId: this._peerId, progress: 0.8, status: 'prepare'})

let dataUrl = '';
if (files[0].type.split('/')[0] === 'image') {
try {
dataUrl = await getThumbnailAsDataUrl(files[0], 400, null, 0.9);
} catch (e) {
console.error(e);
}
}
let dataUrl = await this.getFileTransferThumbnail(files[0]);

Events.fire('set-progress', {peerId: this._peerId, progress: 1, status: 'prepare'})

Expand All @@ -472,6 +467,27 @@ class Peer {
Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'wait'})
}

async getFileTransferThumbnail(image) {
if (image.type.split('/')[0] !== 'image') return '';

let dataUrl = '';
try {
// Iteratively lower thumbnail quality until its size is less than maxMessageSize - 2 kB
let quality = 1;
do {
quality -= 0.1;
if (quality <= 0) {
console.error("Could not create thumbnail that fits into one message.");
return '';
}
dataUrl = await getThumbnailAsDataUrl(image, 450, 450, quality);
} while (new Blob([dataUrl]).size + 2_000 > this.maxMessageSize);
} catch (e) {
console.error(e);
}
return dataUrl;
}

async sendFiles() {
for (let i=0; i<this._filesRequested.length; i++) {
this._filesQueue.push(this._filesRequested[i]);
Expand Down Expand Up @@ -725,7 +741,8 @@ class RTCPeer extends Peer {
super(serverConnection, isCaller, peerId, roomType, roomId);

this.rtcSupported = true;
this.rtcConfig = rtcConfig
this.rtcConfig = rtcConfig;
this.maxMessageSize = 262144; // 256 KB

if (!this._isCaller) return; // we will listen for a caller
this._connect();
Expand Down Expand Up @@ -811,6 +828,13 @@ class RTCPeer extends Peer {
Events.on('beforeunload', e => this._onBeforeUnload(e));
Events.on('pagehide', _ => this._onPageHide());
Events.fire('peer-connected', {peerId: this._peerId, connectionHash: this.getConnectionHash()});
this._setMaxMessageSize();
}

_setMaxMessageSize() {
this.maxMessageSize = this._conn && this._conn.sctp
? Math.min(this._conn.sctp.maxMessageSize, 1048576) // 1 MB max
: 262144; // 256 KB
}

_onMessage(message) {
Expand Down
4 changes: 1 addition & 3 deletions public/scripts/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,8 @@ class PeersUI {

if (files[0].type.split('/')[0] === 'image') {
try {
let imageUrl = await getThumbnailAsDataUrl(files[0], 80, null, 0.9);

let imageUrl = await getThumbnailAsDataUrl(files[0], 80, 80, 0.9);
this.$shareModeImageThumb.style.backgroundImage = `url(${imageUrl})`;

this.$shareModeImageThumb.removeAttribute('hidden');
} catch (e) {
console.error(e);
Expand Down
32 changes: 23 additions & 9 deletions public/scripts/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,26 +493,40 @@ function getThumbnailAsDataUrl(file, width = undefined, height = undefined, qual

await waitUntilImageIsLoaded(imageUrl);

let imageWidth = image.width;
let imageHeight = image.height;
let canvas = document.createElement('canvas');
let heightForSpecifiedWidth;
let widthForSpecifiedHeight;

// resize the canvas and draw the image data into it
if (width) {
heightForSpecifiedWidth = Math.floor(image.height * width / image.width);
}
if (height) {
widthForSpecifiedHeight = Math.floor(image.width * height / image.height);
}

// resize the canvas and draw the image on it
if (width && height) {
canvas.width = width;
canvas.height = height;
// mode "contain": preserve aspect ratio and use arguments as boundaries
if (height > heightForSpecifiedWidth) {
canvas.width = width;
canvas.height = heightForSpecifiedWidth;
}
else {
canvas.width = widthForSpecifiedHeight;
canvas.height = height;
}
}
else if (width) {
canvas.width = width;
canvas.height = Math.floor(imageHeight * width / imageWidth)
canvas.height = heightForSpecifiedWidth;
}
else if (height) {
canvas.width = Math.floor(imageWidth * height / imageHeight);
canvas.width = widthForSpecifiedHeight;
canvas.height = height;
}
else {
canvas.width = imageWidth;
canvas.height = imageHeight
canvas.width = image.width;
canvas.height = image.height
}

let ctx = canvas.getContext("2d");
Expand Down

0 comments on commit 54e718a

Please sign in to comment.