]> cat aescling's git repositories - mastodon.git/blob - app/javascript/flavours/glitch/util/resize_image.js
Merge branch 'master' into glitch-soc/merge-upstream
[mastodon.git] / app / javascript / flavours / glitch / util / resize_image.js
1 import EXIF from 'exif-js';
2
3 const MAX_IMAGE_PIXELS = 1638400; // 1280x1280px
4
5 const getImageUrl = inputFile => new Promise((resolve, reject) => {
6 if (window.URL && URL.createObjectURL) {
7 try {
8 resolve(URL.createObjectURL(inputFile));
9 } catch (error) {
10 reject(error);
11 }
12 return;
13 }
14
15 const reader = new FileReader();
16 reader.onerror = (...args) => reject(...args);
17 reader.onload = ({ target }) => resolve(target.result);
18
19 reader.readAsDataURL(inputFile);
20 });
21
22 const loadImage = inputFile => new Promise((resolve, reject) => {
23 getImageUrl(inputFile).then(url => {
24 const img = new Image();
25
26 img.onerror = (...args) => reject(...args);
27 img.onload = () => resolve(img);
28
29 img.src = url;
30 }).catch(reject);
31 });
32
33 const getOrientation = (img, type = 'image/png') => new Promise(resolve => {
34 if (type !== 'image/jpeg') {
35 resolve(1);
36 return;
37 }
38
39 EXIF.getData(img, () => {
40 const orientation = EXIF.getTag(img, 'Orientation');
41 resolve(orientation);
42 });
43 });
44
45 const processImage = (img, { width, height, orientation, type = 'image/png' }) => new Promise(resolve => {
46 const canvas = document.createElement('canvas');
47
48 if (4 < orientation && orientation < 9) {
49 canvas.width = height;
50 canvas.height = width;
51 } else {
52 canvas.width = width;
53 canvas.height = height;
54 }
55
56 const context = canvas.getContext('2d');
57
58 switch (orientation) {
59 case 2: context.transform(-1, 0, 0, 1, width, 0); break;
60 case 3: context.transform(-1, 0, 0, -1, width, height); break;
61 case 4: context.transform(1, 0, 0, -1, 0, height); break;
62 case 5: context.transform(0, 1, 1, 0, 0, 0); break;
63 case 6: context.transform(0, 1, -1, 0, height, 0); break;
64 case 7: context.transform(0, -1, -1, 0, height, width); break;
65 case 8: context.transform(0, -1, 1, 0, 0, width); break;
66 }
67
68 context.drawImage(img, 0, 0, width, height);
69
70 canvas.toBlob(resolve, type);
71 });
72
73 const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) => {
74 const { width, height } = img;
75
76 const newWidth = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (width / height)));
77 const newHeight = Math.round(Math.sqrt(MAX_IMAGE_PIXELS * (height / width)));
78
79 getOrientation(img, type)
80 .then(orientation => processImage(img, {
81 width: newWidth,
82 height: newHeight,
83 orientation,
84 type,
85 }))
86 .then(resolve)
87 .catch(reject);
88 });
89
90 export default inputFile => new Promise((resolve, reject) => {
91 if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
92 resolve(inputFile);
93 return;
94 }
95
96 loadImage(inputFile).then(img => {
97 if (img.width * img.height < MAX_IMAGE_PIXELS) {
98 resolve(inputFile);
99 return;
100 }
101
102 resizeImage(img, inputFile.type)
103 .then(resolve)
104 .catch(() => resolve(inputFile));
105 }).catch(reject);
106 });
This page took 0.09047 seconds and 4 git commands to generate.