about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/util/resize_image.js
diff options
context:
space:
mode:
authorThibG <thib@sitedethib.com>2020-04-18 15:37:03 +0200
committerThibaut Girka <thib@sitedethib.com>2020-04-18 15:48:15 +0200
commitbf9da1e7344e443f767dc1d86f564de027fe307d (patch)
tree3f6da3660c1f80b09be2b6adb1c0156a3fe132d9 /app/javascript/flavours/glitch/util/resize_image.js
parent0cbc24e3b6ad84a6ef2cc9c77a2afda3e48539c0 (diff)
[Glitch] Fix uploaded image orientation in some browsers
Port a1ce9cbb67facf705379355b9c8ec19c521b419c to glitch-soc

Signed-off-by: Thibaut Girka <thib@sitedethib.com>
Diffstat (limited to 'app/javascript/flavours/glitch/util/resize_image.js')
-rw-r--r--app/javascript/flavours/glitch/util/resize_image.js45
1 files changed, 44 insertions, 1 deletions
diff --git a/app/javascript/flavours/glitch/util/resize_image.js b/app/javascript/flavours/glitch/util/resize_image.js
index d566edb03..61f924f70 100644
--- a/app/javascript/flavours/glitch/util/resize_image.js
+++ b/app/javascript/flavours/glitch/util/resize_image.js
@@ -2,6 +2,45 @@ import EXIF from 'exif-js';
 
 const MAX_IMAGE_PIXELS = 1638400; // 1280x1280px
 
+const _browser_quirks = {};
+
+// Some browsers will automatically draw images respecting their EXIF orientation
+// while others won't, and the safest way to detect that is to examine how it
+// is done on a known image.
+// See https://github.com/w3c/csswg-drafts/issues/4666
+// and https://github.com/blueimp/JavaScript-Load-Image/commit/1e4df707821a0afcc11ea0720ee403b8759f3881
+const dropOrientationIfNeeded = (orientation) => new Promise(resolve => {
+  switch (_browser_quirks['image-orientation-automatic']) {
+  case true:
+    resolve(1);
+    break;
+  case false:
+    resolve(orientation);
+    break;
+  default:
+    // black 2x1 JPEG, with the following meta information set:
+    // - EXIF Orientation: 6 (Rotated 90° CCW)
+    const testImageURL =
+      'data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAA' +
+      'AAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA' +
+      'QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE' +
+      'BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/x' +
+      'ABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAA' +
+      'AAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==';
+    const img = new Image();
+    img.onload = () => {
+      const automatic = (img.width === 1 && img.height === 2);
+      _browser_quirks['image-orientation-automatic'] = automatic;
+      resolve(automatic ? 1 : orientation);
+    };
+    img.onerror = () => {
+      _browser_quirks['image-orientation-automatic'] = false;
+      resolve(orientation);
+    };
+    img.src = testImageURL;
+  }
+});
+
 const getImageUrl = inputFile => new Promise((resolve, reject) => {
   if (window.URL && URL.createObjectURL) {
     try {
@@ -38,7 +77,11 @@ const getOrientation = (img, type = 'image/png') => new Promise(resolve => {
 
   EXIF.getData(img, () => {
     const orientation = EXIF.getTag(img, 'Orientation');
-    resolve(orientation);
+    if (orientation !== 1) {
+      dropOrientationIfNeeded(orientation).then(resolve).catch(() => resolve(orientation));
+    } else {
+      resolve(orientation);
+    }
   });
 });