diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index 710275a542..51649db3d5 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -10,6 +10,7 @@ [app.common.data :as d] [app.common.data.macros :as dm] [app.common.exceptions :as ex] + [app.common.logging :as l] [app.common.media :as cm] [app.common.schema :as sm] [app.common.schema.openapi :as-alias oapi] @@ -21,6 +22,7 @@ [buddy.core.bytes :as bb] [buddy.core.codecs :as bc] [clojure.java.shell :as sh] + [clojure.string] [clojure.xml :as xml] [cuerdas.core :as str] [datoteka.fs :as fs] @@ -215,6 +217,23 @@ {:width (int width) :height (int height)})))])) +(defn- get-dimensions-with-orientation [^String path] + ;; Image magick doesn't give info about exif rotation so we use the identify command + ;; If we are processing an animated gif we use the first frame with -scene 0 + (let [dim-result (sh/sh "identify" "-format" "%w %h\n" path) + orient-result (sh/sh "identify" "-format" "%[EXIF:Orientation]\n" path)] + (if (and (= 0 (:exit dim-result)) + (= 0 (:exit orient-result))) + (let [[w h] (-> (:out dim-result) + str/trim + (clojure.string/split #"\s+") + (->> (mapv #(Integer/parseInt %)))) + orientation (-> orient-result :out str/trim)] + (case orientation + ("6" "8") {:width h :height w} ; Rotated 90 or 270 degrees + {:width w :height h})) ; Normal or unknown orientation + nil))) + (defmethod process :info [{:keys [input] :as params}] (let [{:keys [path mtype] :as input} (check-input input)] @@ -234,13 +253,17 @@ :code :media-type-mismatch :hint (str "Seems like you are uploading a file whose content does not match the extension." "Expected: " mtype ". Got: " mtype'))) - ;; For an animated GIF, getImageWidth/Height returns the delta size of one frame (if no frame given - ;; it returns size of the last one), whereas getPageWidth/Height always return the full size of - ;; any frame. - (assoc input - :width (.getPageWidth instance) - :height (.getPageHeight instance) - :ts (dt/now)))))) + (let [{:keys [width height]} + (or (get-dimensions-with-orientation (str path)) + (do + (l/warn "Failed to read image dimensions with orientation; falling back to im4java" + {:path path}) + {:width (.getPageWidth instance) + :height (.getPageHeight instance)}))] + (assoc input + :width width + :height height + :ts (dt/now))))))) (defmethod process-error org.im4java.core.InfoException [error]