c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud 等に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開発中です。

JPEG / PNG 畫像を可逆壓縮する Python script を Clojure (Babashka) で書き直した

先日書いた以下の記事で Python の script を貼り附けた。

c4se.hatenablog.com

しかし今は Clojure (Babashka) で書く事に決めてあるので、書き直した。Windows 版の Babashka (bb.exe) ではなく Linux 版 (bb) を呼んでゐる。WSL2 で作業するのでこれで困らないが、かうした理由は、

  1. 日本語 file 名を WSL2 上の bash から引數で與へ、java.io.shell/sh を呼ぶと encoding が bug る。file が NTFS 上に在るか WSL2 上に在るかは關はりが無い
  2. bb.exe から Linux program を、この場合は zopflipng を起動できない

どちらも解決不能ではなささうだが、普段 WSL2 上で生きてゐるから bb を使ふ事にした。

#!/usr/bin/env bb
;; Optimize JPEG images by mozjpeg & PNG images by zopflipng.
;;
;; Usage :
;; ag -0 -g '\.((jp(e?)g)|png)$' | xargs -0 -t -n2 -P$(nproc) /mnt/c/<PATH TO>/imageoptim.clj


(defn sh
  [& args]
  (println "+" (str/join " " args))
  (let [{:keys [exit out err]} (apply shell/sh args)]
    (if (not= 0 exit) (throw (Exception. err)) :ok)
    (println out)
    out))


(defn as-image
  [filename]
  {:filename filename
   :type (cond
           (or (str/ends-with? filename ".jpg") (str/ends-with? filename ".jpeg")) "JPEG"
           (str/ends-with? filename ".png") "PNG"
           :else (throw (Exception. (str "Can not detect file type: " filename))))})


(defn compress-jpeg
  [image]
  (let [input-filename (:filename image)
        output-filename (str (java.util.UUID/randomUUID) ".jpg")
        _ (sh "jpegtran.exe" "-copy" "none" "-optimize" "-outfile" output-filename input-filename)
        input-file (io/file input-filename)
        output-file (io/file output-filename)]
    (println (str input-filename " " (.length input-file) " -> " (.length output-file)))
    (.renameTo output-file input-file)))


(defn compress-png
  [image]
  (let [input-filename (:filename image)
        output-filename (str (java.util.UUID/randomUUID) ".png")
        _ (sh "/mnt/c/<PATH TO>/zopflipng" "-m" "--lossy_transparent" input-filename output-filename)
        input-file (io/file input-filename)
        output-file (io/file output-filename)]
    (println (str input-filename " " (.length input-file) " -> " (.length output-file)))
    (.renameTo output-file input-file)))


(defn compress
  [image]
  (case (:type image)
    "JPEG" (compress-jpeg image)
    "PNG" (compress-png image)
    (throw (Exception. (str "Unknown image type" (:type image))))))


(doseq [filename *command-line-args*]
  (-> filename as-image compress))

何をしてゐるか知ってゐる program は、programming 言語に或る程度關はらず讀めるものだ。