diff --git a/package-lock.json b/package-lock.json index 2cd2075..b91c7a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1787,6 +1787,32 @@ "setimmediate": "^1.0.4" } }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "tmp-promise": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.2.tgz", + "integrity": "sha512-OyCLAKU1HzBjL6Ev3gxUeraJNlbNingmi8IrHHEsYH8LTmEuhvYfqvhn2F/je+mjf4N58UmZ96OMEy1JanSCpA==", + "requires": { + "tmp": "^0.2.0" + } + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", diff --git a/package.json b/package.json index cad71b7..4b9934c 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "request": "^2.88.0", "request-promise-native": "^1.0.8", "sqlite": "^3.0.3", + "tmp-promise": "^3.0.2", "twit": "^2.2.11", "winston": "^3.2.1" } diff --git a/src/main/lemondronor/advisorycircular.cljs b/src/main/lemondronor/advisorycircular.cljs index 6ad1093..5e8df2f 100644 --- a/src/main/lemondronor/advisorycircular.cljs +++ b/src/main/lemondronor/advisorycircular.cljs @@ -3,6 +3,7 @@ ["canvas" :as canvas] ["commander" :as commander] ["fs" :as fs] + ["tmp-promise" :as tmp] [cljs.pprint :as pprint] [clojure.set :as set] [clojure.string :as string] @@ -245,6 +246,31 @@ (:normalized-curviness ac))) +(defn add-attribution-to-image [path attribution] + (log-info "Adding attribution to %s: %s" path attribution) + (p/let [image (canvas/loadImage path) + canvas (canvas/createCanvas (.-width image) (.-height image)) + ctx (.getContext canvas "2d")] + (.drawImage ctx image 0 0) + (set! (.-font ctx) "12px Impact") + (p/let [tmp-file (tmp/file) + text-metrics (.measureText ctx attribution) + w (.-width text-metrics) + h 12 + [mw mh] [1 1] + [pw ph] [2 2] + text-x (- (.-width image) w pw mw) + text-y (- (.-height image) h ph mh)] + (.beginPath ctx) + (set! (.-fillStyle ctx) "rgba(128,128,128,0.7)") + (.rect ctx (- text-x pw) (- text-y ph) (+ w pw pw) (+ h ph ph)) + (.fill ctx) + (set! (.-fillStyle ctx) "black") + (.fillText ctx attribution text-x (+ text-y h)) + (util/write-stream-to-file (.createPNGStream canvas) (.-path tmp-file)) + (fs/renameSync (.-path tmp-file) path)))) + + (defn map-screenshot ([icao lat lon now] (map-screenshot icao lat lon now {})) @@ -260,6 +286,8 @@ ;; :viewport {:width 1600 :height 800} ;; :clip {:width 1600 :height 800 :x 0 :y 0} })] + (if-let [attribution (:attribution options)] + (add-attribution-to-image image-path attribution)) (log-verbose "%s: Got screenshot" icao) image-path))) @@ -745,17 +773,8 @@ (def default-config-path "config.yaml") -(defn write-stream-to-file [stream path] - (p/promise - [resolve] - (let [out (fs/createWriteStream path)] - (.pipe stream out) - (.on out "finish" #(do (println "resolving") (resolve nil))) - (.on out "error" #(throw %))))) - - (defn main [& args] - (-> commander + (-> commander (.option "--lat " "Latitude of the circle of region of interest" parse-number) (.option "--lon " "Longitude of the circle of the region of interest" parse-number) (.option "--adsbx-url " "ADSBX API url") @@ -770,38 +789,10 @@ (.option "--log-prefix " "Log prefix to use") (.option "--airport-geojson" "Generate airport GEOJSON and exit") (.option "--create-aircraft-info-db-from-json " "Generate aircraft info DB and exit") - - (.option "--test") - (.option "--icao ") - (.option "--reg ") (.parse (.-argv js/process))) (logging/set-log-prefix! (or (.-logPrefix commander) "")) (reset! log-prefix (or (.-logPrefix commander) "")) (p/try - (p/let [path (nth (.-argv js/process) 2) - _ (println path) - image (canvas/loadImage path) - canvas (canvas/createCanvas (.-width image) (.-height image)) - ctx (.getContext canvas "2d")] - (.drawImage ctx image 0 0) - (set! (.-font ctx) "12px Impact") - (let [attribution "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community" ;; "© OpenStreetMap contributors" - text-metrics (.measureText ctx attribution) - w (.-width text-metrics) - h 12 - [mw mh] [1 1] - [pw ph] [2 2] - text-x (- (.-width image) w pw mw) - text-y (- (.-height image) h ph mh )] - (.beginPath ctx) - (set! (.-fillStyle ctx) "rgba(128,128,128,0.7)") - (.rect ctx (- text-x pw) (- text-y ph) (+ w pw pw) (+ h ph ph)) - (.fill ctx) - (set! (.-fillStyle ctx) "black") - (.fillText ctx attribution text-x (+ text-y h))) - (write-stream-to-file (.createPNGStream canvas) "out.png") - (println "DONE!") - (.exit js/process 0)) (cond (.-createAircraftInfoDbFromJson commander) (create-aircraft-info-db (.-createAircraftInfoDbFromJson commander) (.-aircraftInfoDb commander)) @@ -815,9 +806,6 @@ config (build-config base-config cli-config {}) geojson (airport-geojson config)] (println (.stringify js/JSON (clj->js geojson) nil " "))) - (.-test commander) - (p/let [photo (airport-data-aircraft-photo (.-icao commander) (.-reg commander))] - (fs/writeFileSync "photo.jpg" photo)) :else (let [start-time (current-time)] ;; If --config-path is specified, definitely try to read that diff --git a/src/main/lemondronor/advisorycircular/util.cljs b/src/main/lemondronor/advisorycircular/util.cljs index 54a0ae4..af3a781 100644 --- a/src/main/lemondronor/advisorycircular/util.cljs +++ b/src/main/lemondronor/advisorycircular/util.cljs @@ -113,3 +113,12 @@ ([ms v] (p/promise [resolve] (js/setTimeout #(resolve v) ms)))) + + +(defn write-stream-to-file [stream path] + (p/promise + [resolve reject] + (let [out (fs/createWriteStream path)] + (.pipe stream out) + (.on out "finish" #(resolve nil)) + (.on out "error" #(reject %)))))