mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-14 02:24:31 +00:00
Merge pull request #5333 from jonasgeiler/staging
Improve media filtering by using OffscreenCanvas, if supported
This commit is contained in:
commit
aea5392044
1 changed files with 68 additions and 33 deletions
|
@ -1095,11 +1095,12 @@ export default {
|
|||
},
|
||||
|
||||
defineErrorMessage(errObject) {
|
||||
let msg;
|
||||
if (errObject.response) {
|
||||
let msg = errObject.response.data.message ? errObject.response.data.message : 'An unexpected error occured.';
|
||||
msg = errObject.response.data.message ? errObject.response.data.message : 'An unexpected error occured.';
|
||||
}
|
||||
else {
|
||||
let msg = errObject.message;
|
||||
msg = errObject.message;
|
||||
}
|
||||
return swal('Oops, something went wrong!', msg, 'error');
|
||||
},
|
||||
|
@ -1765,57 +1766,91 @@ export default {
|
|||
|
||||
applyFilterToMedia() {
|
||||
// this is where the magic happens
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if(ua.indexOf('firefox') == -1 && ua.indexOf('chrome') == -1) {
|
||||
this.isPosting = false;
|
||||
swal('Oops!', 'Your browser does not support the filter feature.', 'error');
|
||||
this.page = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
let count = this.media.filter(m => m.filter_class).length;
|
||||
if(count) {
|
||||
this.page = 'filteringMedia';
|
||||
this.filteringRemainingCount = count;
|
||||
this.$nextTick(() => {
|
||||
this.isFilteringMedia = true;
|
||||
this.media.forEach((media, idx) => this.applyFilterToMediaSave(media, idx));
|
||||
Promise.all(this.media.map(media => {
|
||||
return this.applyFilterToMediaSave(media);
|
||||
})).catch(err => {
|
||||
console.error(err);
|
||||
swal('Oops!', 'An error occurred while applying filters to your media. Please refresh the page and try again. If the problem persist, please try a different web browser.', 'error');
|
||||
});
|
||||
})
|
||||
} else {
|
||||
this.page = 3;
|
||||
}
|
||||
},
|
||||
|
||||
applyFilterToMediaSave(media, idx) {
|
||||
async applyFilterToMediaSave(media) {
|
||||
if(!media.filter_class) {
|
||||
return;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
let data = null;
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
let image = document.createElement('img');
|
||||
// Load image
|
||||
const image = document.createElement('img');
|
||||
image.src = media.url;
|
||||
image.addEventListener('load', e => {
|
||||
await new Promise((resolve, reject) => {
|
||||
image.addEventListener('load', () => resolve());
|
||||
image.addEventListener('error', () => {
|
||||
reject(new Error('Failed to load image'));
|
||||
});
|
||||
});
|
||||
|
||||
// Create canvas
|
||||
let canvas;
|
||||
let usingOffscreenCanvas = false;
|
||||
if('OffscreenCanvas' in window) {
|
||||
canvas = new OffscreenCanvas(image.width, image.height);
|
||||
usingOffscreenCanvas = true;
|
||||
} else {
|
||||
canvas = document.createElement('canvas');
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
ctx.filter = App.util.filterCss[media.filter_class];
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
ctx.save();
|
||||
canvas.toBlob(function(blob) {
|
||||
data = new FormData();
|
||||
data.append('file', blob);
|
||||
data.append('id', media.id);
|
||||
axios.post('/api/compose/v0/media/update', data)
|
||||
.then(res => {
|
||||
self.media[idx].is_filtered = true;
|
||||
self.updateFilteringMedia();
|
||||
}).catch(err => {
|
||||
});
|
||||
}
|
||||
|
||||
// Draw image with filter to canvas
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
throw new Error('Failed to get canvas context');
|
||||
}
|
||||
if (!('filter' in ctx)) {
|
||||
throw new Error('Canvas filter not supported');
|
||||
}
|
||||
ctx.filter = App.util.filterCss[media.filter_class];
|
||||
ctx.drawImage(image, 0, 0, image.width, image.height);
|
||||
ctx.save();
|
||||
|
||||
// Convert canvas to blob
|
||||
let blob;
|
||||
if(usingOffscreenCanvas) {
|
||||
blob = await canvas.convertToBlob({
|
||||
type: media.mime,
|
||||
quality: 1,
|
||||
});
|
||||
}, media.mime, 0.9);
|
||||
ctx.clearRect(0, 0, image.width, image.height);
|
||||
} else {
|
||||
blob = await new Promise((resolve, reject) => {
|
||||
canvas.toBlob(blob => {
|
||||
if(blob) {
|
||||
resolve(blob);
|
||||
} else {
|
||||
reject(
|
||||
new Error('Failed to convert canvas to blob'),
|
||||
);
|
||||
}
|
||||
}, media.mime, 1);
|
||||
});
|
||||
}
|
||||
|
||||
// Upload blob / Update media
|
||||
const data = new FormData();
|
||||
data.append('file', blob);
|
||||
data.append('id', media.id);
|
||||
await axios.post('/api/compose/v0/media/update', data);
|
||||
media.is_filtered = true;
|
||||
this.updateFilteringMedia();
|
||||
},
|
||||
|
||||
updateFilteringMedia() {
|
||||
|
|
Loading…
Reference in a new issue