Progress on thumbnailing, but not working yet.

This commit is contained in:
Simon Brooke 2020-02-10 17:39:24 +00:00
parent 719222195e
commit ad5e41c23a
No known key found for this signature in database
GPG key ID: A7A4F18D1D4DF987
3 changed files with 75 additions and 22 deletions

View file

@ -16,6 +16,7 @@
[environ "1.1.0"] [environ "1.1.0"]
[hiccup "1.0.5"] [hiccup "1.0.5"]
[im.chit/cronj "1.4.4"] [im.chit/cronj "1.4.4"]
[image-resizer "0.1.10"]
[lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]] [lib-noir "0.9.9" :exclusions [org.clojure/tools.reader]]
[markdown-clj "0.9.99" :exclusions [com.keminglabs/cljx]] [markdown-clj "0.9.99" :exclusions [com.keminglabs/cljx]]
[me.raynes/fs "1.4.6"] [me.raynes/fs "1.4.6"]

View file

@ -42,5 +42,10 @@
;; from: options are :local, :cloudflare ;; from: options are :local, :cloudflare
:passwd "resources/passwd" :passwd "resources/passwd"
;; where the password file is stored ;; where the password file is stored
:site-title "Smeagol"} ;; overall title of the site, used in :site-title "Smeagol" ;; overall title of the site, used in
;; page headings ;; page headings
:thumbnails {:small 64 ;; maximum dimension of thumbnails
;; stored in the /small directory
:med 400 ;; maximum dimension of thumbnails
;; stored in the /med directory
}}

View file

@ -1,10 +1,18 @@
(ns ^{:doc "Handle file uploads." (ns ^{:doc "Handle file uploads."
:author "Simon Brooke"} :author "Simon Brooke"}
smeagol.uploads smeagol.uploads
(:import [java.io File])
(:require [clojure.string :as cs] (:require [clojure.string :as cs]
[noir.io :as io] [clojure.java.io :as io]
[taoensso.timbre :as timbre])) [image-resizer.core :refer [resize]]
[image-resizer.util :refer :all]
[me.raynes.fs :as fs]
[smeagol.configuration :refer [config]]
[taoensso.timbre :as log])
(:import [java.io File]
[java.awt Image]
[java.awt.image RenderedImage BufferedImageOp]
[javax.imageio ImageIO ImageWriter ImageWriteParam IIOImage]
[javax.imageio.stream FileImageOutputStream]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; ;;;;
@ -29,21 +37,59 @@
;;;; ;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; No longer used as uploaded files now go into Git. (def image-file-extns
;; (defn avoid-name-collisions "Extensions of file types we will attempt to thumbnail. GIF is excluded
;; "Find a filename within this `path`, based on this `file-name`, that does not because by default the javax.imageio package can read GIF, PNG, and JPEG
;; reference an existing file. It is assumed that `path` ends with a path separator. images but can only write PNG and JPEG images."
;; Returns a filename hwich does not currently reference a file within the path." #{".jpg" ".jpeg" ".png"})
;; [path file-name]
;; (if (.exists (File. (str path file-name)))
;; (let [parts (cs/split file-name #"\.")
;; prefix (cs/join "." (butlast parts))
;; suffix (last parts)]
;; (first
;; (filter #(not (.exists (File. (str path %))))
;; (map #(str prefix "." % "." suffix) (range)))))
;; file-name))
(defn read-image
"Reads a BufferedImage from source, something that can be turned into
a file with clojure.java.io/file"
[source]
(ImageIO/read (io/file source)))
(defn write-image
"Writes img, a RenderedImage, to dest, something that can be turned into
a file with clojure.java.io/file.
Takes the following keys as options:
:format - :gif, :jpg, :png or anything supported by ImageIO
:quality - for JPEG images, a number between 0 and 100"
[^RenderedImage img dest & {:keys [format quality] :or {format :jpg}}]
(if (or (not quality) (not (contains? #{:jpg :jpeg} format)))
(ImageIO/write img (name format) (io/file dest))
(let [fmt (rest (fs/extension (cs/lower-case dest)))
iw (doto ^ImageWriter (first
(iterator-seq
(ImageIO/getImageWritersByFormatName
"jpeg")))
(.setOutput (FileImageOutputStream. (io/file dest))))
iw-param (doto ^ImageWriteParam (.getDefaultWriteParam iw)
(.setCompressionMode ImageWriteParam/MODE_EXPLICIT)
(.setCompressionQuality (float (/ quality 100))))
iio-img (IIOImage. img nil nil)]
(.write iw nil iio-img iw-param))))
(defn auto-thumbnail
"For each of the thumbnail sizes in the configuration, create a thumbnail
for the file with this `filename` on this `path`, provided that it is a
scalable image and is larger than the size."
([^String path ^String filename]
(if
(image-file-extns (fs/extension (cs/lower-case filename)))
(let [original (buffered-image (.File (str path filename)))] ;; fs/file?
(map
#(auto-thumbnail path filename % original)
(keys (config :thumbnails))))
(log/info filename " cannot be thumbnailed.")))
([^String path ^String filename size ^RenderedImage image]
(let [s (-> config :thumbnails size)
d (dimensions image)]
(if (and (integer? s) (some #(> % s) d))
(do
(write-image (resize image s s) (io/file path (name size) filename))
(log/info "Created a " size " thumbnail of " filename))
(log/info filename "is smaller than " s "x" s " and was not scaled to " size)))))
(defn store-upload (defn store-upload
"Store an upload both to the file system and to the database. "Store an upload both to the file system and to the database.
@ -56,17 +102,18 @@
(let [upload (:upload params) (let [upload (:upload params)
tmp-file (:tempfile upload) tmp-file (:tempfile upload)
filename (:filename upload)] filename (:filename upload)]
(timbre/info (log/info
(str "Storing upload file: " upload)) (str "Storing upload file: " upload))
(timbre/debug (log/debug
(str "store-upload mv file: " tmp-file " to: " path filename)) (str "store-upload mv file: " tmp-file " to: " path filename))
(if tmp-file (if tmp-file
(try (try
(do (do
(.renameTo tmp-file (.renameTo tmp-file
(File. (str path filename))) (File. (str path filename))) ;; TODO: fs/file
(auto-thumbnail path filename)
(File. (str path filename))) (File. (str path filename)))
(catch Exception x (catch Exception x
(timbre/error (str "Failed to move " tmp-file " to " path filename "; " (type x) ": " (.getMessage x))) (log/error (str "Failed to move " tmp-file " to " path filename "; " (type x) ": " (.getMessage x)))
(throw x))) (throw x)))
(throw (Exception. "No file found?"))))) (throw (Exception. "No file found?")))))