From b83de09f9e7bddfff5d5fefba600d26fcd6f3a64 Mon Sep 17 00:00:00 2001 From: gered Date: Wed, 16 Aug 2017 19:57:55 -0400 Subject: [PATCH] add image watermark rendering support --- src/clj_htmltopdf/watermark.clj | 75 ++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/src/clj_htmltopdf/watermark.clj b/src/clj_htmltopdf/watermark.clj index ef46dae..941b27f 100644 --- a/src/clj_htmltopdf/watermark.clj +++ b/src/clj_htmltopdf/watermark.clj @@ -1,9 +1,12 @@ (ns clj-htmltopdf.watermark + (:require + [clojure.java.io :as io]) (:import [java.io InputStream OutputStream] [org.apache.pdfbox.pdmodel PDDocument PDPage PDPageContentStream PDPageContentStream$AppendMode] [org.apache.pdfbox.pdmodel.common PDRectangle] [org.apache.pdfbox.pdmodel.font PDType1Font PDFont] + [org.apache.pdfbox.pdmodel.graphics.image PDImageXObject PDImage] [org.apache.pdfbox.pdmodel.graphics.state PDExtendedGraphicsState] [org.apache.pdfbox.util Matrix])) @@ -24,25 +27,25 @@ "courier-oblique" PDType1Font/COURIER_OBLIQUE "courier-boldoblique" PDType1Font/COURIER_BOLD_OBLIQUE}) -(defn render-watermark! - [^PDPage page ^PDPageContentStream cs options] - (let [font (or (get watermark-fonts (:font options)) - (get watermark-fonts "helvetica-bold")) - font-size (float (or (:font-size options) 36.0)) - font-color (or (:color options) [0 0 0]) - text (:text options) - text-width (/ (* (.getStringWidth font text) font-size) 1000.0) - text-height (/ (* (.getHeight (.getFontBoundingBox (.getFontDescriptor ^PDFont font))) font-size) 1000.0) - rotation (float (or (:rotation options) 0)) - page-size (.getMediaBox page) - page-width (.getWidth page-size) - page-height (.getHeight page-size) - x (if (= :center (:x options)) (/ page-width 2) (float (:x options))) - y (if (= :center (:y options)) (/ page-height 2) (float (:y options))) - transform (doto (Matrix.) - (.translate x y) - (.rotate (Math/toRadians rotation)) - (.translate (- (/ text-width 2)) (- (/ text-height 2))))] +(defn render-text-watermark! + [^PDDocument doc ^PDPage page ^PDPageContentStream cs options] + (let [font (or (get watermark-fonts (:font options)) + (get watermark-fonts "helvetica-bold")) + font-size (float (or (:font-size options) 36.0)) + font-color (or (:color options) [0 0 0]) + text (:text options) + text-width (/ (* (.getStringWidth font text) font-size) 1000.0) + text-height (/ (* (.getHeight (.getFontBoundingBox (.getFontDescriptor ^PDFont font))) font-size) 1000.0) + rotation (float (or (:rotation options) 0)) + page-size (.getMediaBox page) + page-width (.getWidth page-size) + page-height (.getHeight page-size) + x (if (= :center (:x options)) (/ page-width 2) (float (:x options))) + y (if (= :center (:y options)) (/ page-height 2) (float (:y options))) + transform (doto (Matrix.) + (.translate x y) + (.rotate (Math/toRadians rotation)) + (.translate (- (/ text-width 2)) (- (/ text-height 2))))] (when (:opacity options) (let [r0 (PDExtendedGraphicsState.)] (.setNonStrokingAlphaConstant r0 (float (:opacity options))) @@ -54,6 +57,36 @@ (.showText cs text) (.endText cs))) +(defn render-image-watermark! + [^PDDocument doc ^PDPage page ^PDPageContentStream cs options] + (let [image (PDImageXObject/createFromFileByContent (io/file (:image options)) doc) + image-width (.getWidth image) + image-height (.getHeight image) + rotation (float (or (:rotation options) 0)) + page-size (.getMediaBox page) + page-width (.getWidth page-size) + page-height (.getHeight page-size) + x (if (= :center (:x options)) (/ page-width 2) (float (:x options))) + y (if (= :center (:y options)) (/ page-height 2) (float (:y options))) + transform (doto (Matrix.) + (.translate x y) + (.scale (or (:scale-x options) 1.0) (or (:scale-y options) 1.0)) + (.rotate (Math/toRadians rotation)) + (.translate (- (/ image-width 2)) (- (/ image-height 2))))] + (when (:opacity options) + (let [r0 (PDExtendedGraphicsState.)] + (.setNonStrokingAlphaConstant r0 (float (:opacity options))) + (.setGraphicsStateParameters cs r0))) + (.transform cs transform) + (.drawImage cs image (float 0) (float 0)))) + +(defn render-watermark! + [^PDDocument doc ^PDPage page ^PDPageContentStream cs options] + (cond + (:text options) (render-text-watermark! doc page cs options) + (:image options) (render-image-watermark! doc page cs options) + :else (throw (Exception. "Unknown type of watermark. Either :text or :image should be specified.")))) + (defn write-watermark! [^InputStream pdf ^OutputStream out {:keys [watermark] :as options}] (with-open [doc (PDDocument/load pdf)] @@ -61,7 +94,7 @@ (let [cs (PDPageContentStream. doc page PDPageContentStream$AppendMode/APPEND true true)] (with-open [cs cs] (if (map? watermark) - (render-watermark! page cs watermark) - (watermark page cs))))) + (render-watermark! doc page cs watermark) + (watermark doc page cs))))) (.save doc out) out))