001  (ns proomp.domain.image.resolution
002    (:import (clojure.lang MapEntry)))
003  
004  (def ^:private orientations [::landscape ::portrait ::square])
005  (defprotocol Oriented (orientation [this]))
006  
007  (defrecord Resolution [name w h aspect]
008    Oriented (orientation [this] (cond (> w h) ::landscape (< w h) ::portrait :else ::square)))
009  
010  (defn- swap-keyword [kw]
011    "Swaps the orientation of resolution keywords. Eg. :16:9 into :9:16."
012    (->> (-> (name kw) (clojure.string/split #":") reverse) (clojure.string/join ":") keyword))
013  (defn change-keyword-orientation [kw]
014    (let [parts (clojure.string/split (name kw) #"-")]
015      (if (= "landscape" (last parts))
016        (keyword (apply str (interpose "-" (concat (butlast parts) ["portrait"]))))
017        (keyword (apply str (interpose "-" (concat (butlast parts) ["landscape"])))))))
018  
019  (defn- flip-orientation [^Resolution res]
020    (->Resolution (:name res) (:h res) (:w res) (swap-keyword (:aspect res))))
021  
022  (def ^:private square-resolutions
023    {:highest (->Resolution "Highest" 1440 1440 :1:1)         ;requires more than 10GB VRAM
024     :higher  (->Resolution "Higher" 1280 1280 :1:1)          ;may require more than 10GB VRAM
025     :high    (->Resolution "High" 1080 1080 :1:1)
026     :default (->Resolution "Default" 960 960 :1:1)
027     :reduced (->Resolution "Reduced" 768 768 :1:1)
028     :low     (->Resolution "Low" 720 720 :1:1)
029     :lower   (->Resolution "Lower" 512 512 :1:1)             ;may work with 6GB VRAM
030     :lowest  (->Resolution "Lowest" 360 360 :1:1)})          ;should work with 6GB VRAM
031  
032  (def ^:private sixteen-to-nine-resolutions
033    "See https://en.wikipedia.org/wiki/Graphics_display_resolution"
034    ;VRAM requirements do not apply with xformers memory efficient attention enabled,
035    ;but for potentially better results, it's suggested generate the original images with a
036    ;resolution closer to that of the used model (ie :WSVGA-landscape)
037    ;and then use the upscaler to generate higher resolution images im a second step.
038    ;higher resolutions tend to generate multiple objects while lower resolutions may generate more patterns.
039    {:4K-UHD-landscape  (->Resolution "4K UHD" 3840 2160 :16:9) ;requires more than 10GB VRAM
040     :QHD-landscape     (->Resolution "QHD" 2560 1440 :16:9)  ;may require more than 10GB VRAM
041     :Full-HD-landscape (->Resolution "Full HD" 1920 1080 :16:9) ;may not work with 10GB VRAM
042     :HD-landscape      (->Resolution "HD" 1280 720 :16:9)
043     :WSVGA-landscape   (->Resolution "WSVGA" 1024 576 :16:9)
044     :NHD-landscape     (->Resolution "nHD" 640 360 :16:9)})  ;may work with 6GB VRAM
045  
046  (def ^:private switch-orientation (fn [[k v]] (MapEntry. (change-keyword-orientation k) (flip-orientation v))))
047  (def resolutions
048    (let [nine-to-sixteen-resolutions (into {} (map switch-orientation sixteen-to-nine-resolutions))]
049      (merge square-resolutions sixteen-to-nine-resolutions nine-to-sixteen-resolutions)))
050  
051  (defonce ^Resolution active-image-resolution (resolutions :WSVGA-portrait))
052  (defonce ^Resolution active-animation-resolution (resolutions :WSVGA-portrait))