mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2025-04-25 01:06:17 -04:00
Fix thumbnail creation on very large images or images with extreme dimensions (#332)
This commit is contained in:
parent
ab67c5858d
commit
00d2757fdc
3 changed files with 60 additions and 21 deletions
|
@ -332,6 +332,8 @@ class Peer {
|
|||
this._filesQueue = [];
|
||||
this._busy = false;
|
||||
|
||||
this.maxMessageSize = 65536; // 64 KB
|
||||
|
||||
// evaluate auto accept
|
||||
this._evaluateAutoAccept();
|
||||
}
|
||||
|
@ -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'})
|
||||
|
||||
|
@ -472,6 +467,30 @@ class Peer {
|
|||
Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'wait'})
|
||||
}
|
||||
|
||||
async getFileTransferThumbnail(image) {
|
||||
if (image.type.split('/')[0] !== 'image') {
|
||||
// file is not of type image -> abort!
|
||||
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]);
|
||||
|
@ -725,7 +744,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();
|
||||
|
@ -811,6 +831,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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue