mirror of
https://github.com/whippyshou/mastodon
synced 2024-12-15 07:08:58 +09:00
0fb0037ca7
To improve the way super tall or super ride images are treated, the numbers remain the same, 1280x1280 and 400x400, but if an image is less in one dimension than the other, the other can become larger Thanks to @WAHa_06x36@mastodon.social for the tip
107 lines
2.8 KiB
JavaScript
107 lines
2.8 KiB
JavaScript
import EXIF from 'exif-js';
|
|
|
|
const MAX_IMAGE_PIXELS = 1638400; // 1280x1280px
|
|
|
|
const getImageUrl = inputFile => new Promise((resolve, reject) => {
|
|
if (window.URL && URL.createObjectURL) {
|
|
try {
|
|
resolve(URL.createObjectURL(inputFile));
|
|
} catch (error) {
|
|
reject(error);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const reader = new FileReader();
|
|
reader.onerror = (...args) => reject(...args);
|
|
reader.onload = ({ target }) => resolve(target.result);
|
|
|
|
reader.readAsDataURL(inputFile);
|
|
});
|
|
|
|
const loadImage = inputFile => new Promise((resolve, reject) => {
|
|
getImageUrl(inputFile).then(url => {
|
|
const img = new Image();
|
|
|
|
img.onerror = (...args) => reject(...args);
|
|
img.onload = () => resolve(img);
|
|
|
|
img.src = url;
|
|
}).catch(reject);
|
|
});
|
|
|
|
const getOrientation = (img, type = 'image/png') => new Promise(resolve => {
|
|
if (type !== 'image/jpeg') {
|
|
resolve(1);
|
|
return;
|
|
}
|
|
|
|
EXIF.getData(img, () => {
|
|
const orientation = EXIF.getTag(img, 'Orientation');
|
|
resolve(orientation);
|
|
});
|
|
});
|
|
|
|
const processImage = (img, { width, height, orientation, type = 'image/png' }) => new Promise(resolve => {
|
|
const canvas = document.createElement('canvas');
|
|
|
|
if (4 < orientation && orientation < 9) {
|
|
canvas.width = height;
|
|
canvas.height = width;
|
|
} else {
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
}
|
|
|
|
const context = canvas.getContext('2d');
|
|
|
|
switch (orientation) {
|
|
case 2: context.transform(-1, 0, 0, 1, width, 0); break;
|
|
case 3: context.transform(-1, 0, 0, -1, width, height); break;
|
|
case 4: context.transform(1, 0, 0, -1, 0, height); break;
|
|
case 5: context.transform(0, 1, 1, 0, 0, 0); break;
|
|
case 6: context.transform(0, 1, -1, 0, height, 0); break;
|
|
case 7: context.transform(0, -1, -1, 0, height, width); break;
|
|
case 8: context.transform(0, -1, 1, 0, 0, width); break;
|
|
}
|
|
|
|
context.drawImage(img, 0, 0, width, height);
|
|
|
|
canvas.toBlob(resolve, type);
|
|
});
|
|
|
|
const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => {
|
|
const { width, height } = img;
|
|
|
|
const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height)));
|
|
const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));
|
|
|
|
getOrientation(img, type)
|
|
.then(orientation => processImage(img, {
|
|
width: newWidth,
|
|
height: newHeight,
|
|
orientation,
|
|
type,
|
|
}))
|
|
.then(resolve)
|
|
.catch(reject);
|
|
});
|
|
|
|
export default inputFile => new Promise((resolve, reject) => {
|
|
if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
|
|
resolve(inputFile);
|
|
return;
|
|
}
|
|
|
|
loadImage(inputFile).then(img => {
|
|
if (img.width * img.height < MAX_IMAGE_PIXELS) {
|
|
resolve(inputFile);
|
|
return;
|
|
}
|
|
|
|
resizeImage(img, inputFile.type)
|
|
.then(resolve)
|
|
.catch(() => resolve(inputFile));
|
|
}).catch(reject);
|
|
});
|