Skip to content

Commit

Permalink
Merge pull request #68 from sampoto/pdfa-perf-params
Browse files Browse the repository at this point in the history
Pdf/a conversion performance parameters
  • Loading branch information
erno authored Aug 15, 2023
2 parents c0fc5df + 8719896 commit a34addb
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 9 deletions.
40 changes: 39 additions & 1 deletion programs/pdf2pdfa
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,44 @@ set -u

INPUT=$1
OUTPUT=$2
DPI=$3
MAXBITMAP=$4
PDFSETTINGS=$5

if [ -z "$DPI" ]; then
DPI=720
fi
re='^[0-9]+$'
if ! [[ $DPI =~ $re ]] ; then
echo "error: DPI is not a number"
exit 2
fi


if [ -n "$PDFSETTINGS" ]; then
valid_settings=("/screen" "/ebook" "/printer" "/prepress" "/default")
for i in "${valid_settings[@]}"
do
if [ "$i" = "$PDFSETTINGS" ] ; then
found=true
fi
done
if [ "$found" != true ]; then
echo "error: Invalid PDFSETTINGS value"
exit 2
fi
PDFSETTINGS="-dPDFSETTINGS=$PDFSETTINGS"
else
PDFSETTINGS="-dPDFSETTINGS=/default"
fi

if [ -z "$MAXBITMAP" ]; then
MAXBITMAP=0
fi
if ! [[ $MAXBITMAP =~ $re ]] ; then
echo "error: MAXBITMAP is not a number"
exit 2
fi

docker run \
--runtime="${LAUNDRY_DOCKER_RUNTIME:-runsc}" \
Expand All @@ -15,5 +53,5 @@ docker run \
--rm \
laundry-programs \
/bin/bash -c 'cat > /home/docconv/document.pdf && \
gs -q -dPDFA -dBATCH -dNOPAUSE -sProcessColorModel=DeviceCMYK -sDEVICE=pdfwrite -dPDFACompatibilityPolicy=1 -sOutputFile=- /home/docconv/document.pdf' \
gs -q -dPDFA -dBATCH -dNOPAUSE -r'$DPI' -dMaxBitmap='$MAXBITMAP' '$PDFSETTINGS' -sProcessColorModel=DeviceCMYK -sDEVICE=pdfwrite -dPDFACompatibilityPolicy=1 -sOutputFile=- /home/docconv/document.pdf' \
< "$INPUT" > "$OUTPUT"
38 changes: 33 additions & 5 deletions resources/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,28 @@
a:hover { color: #098809; text-decoration: underline }
</style>
<script>
var pdfParameters = [
{"type": "pdf/pdf2pdfa", key: "dpi", dtype: "number", wrapper: "pdf_dpi_elem", elem: "pdf_dpi" },
{"type": "pdf/pdf2pdfa", key: "maxbitmap", dtype: "number", wrapper: "pdf_maxbitmap_elem", elem: "pdf_maxbitmap" },
{"type": "pdf/pdf2pdfa", key: "pdfsettings", wrapper: "pdf_pdfsettings_elem", elem: "pdf_pdfsettings" }
]

function updateConversionParameters() {
var seln = document.getElementById("pdfOperation");
for (const param of pdfParameters) {
document.getElementById(param.wrapper).hidden = (param.type !== seln.value);
}
}

function pdfConverter() {
var form = document.getElementById("pdfop");
var seln = document.getElementById("pdfOperation");
converter(form, seln)
var args = pdfParameters.filter(item => item.type == seln.value)
.map(arg => ({
key: arg.key,
value: arg.dtype === "number" ? parseInt(document.getElementById(arg.elem).value).toString() : document.getElementById(arg.elem).value
}));
converter(form, seln, args)
}

function imageConverter() {
Expand Down Expand Up @@ -44,14 +62,15 @@
xhr.send(formData);
}

function converter(form, seln) {
function converter(form, seln, args) {
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
if (form[0].files.length != 1) {
alert("Select a file first");
return;
}
xhr.open("POST", seln.value, true);
var argsString = args && args.length ? "?" + args.map(function(arg) { return arg.key + "=" + encodeURIComponent(arg.value) }).join("&") : ""
xhr.open("POST", seln.value + argsString, true);
xhr.responseType = "blob";
xhr.onload = function(e) {
var urlsource= window.URL || window.webkitURL;
Expand All @@ -63,19 +82,28 @@
</script>
<title>Laundry</title>
</head>
<body>
<body onload="updateConversionParameters()">
<h1>Laundry</h1>
<a href="api-docs">Swagger API</a>

<hr>

<p>PDF
<select id="pdfOperation">
<select id="pdfOperation" onchange="updateConversionParameters()">
<option value="pdf/pdf-preview">preview</option>
<option value="pdf/pdf2pdfa">to PDF/A</option>
<option value="pdf/pdf2txt">to text
</select>
</p>
<div id="pdf_dpi_elem">
<input type="number" id="pdf_dpi" name="dpi" value="720"> DPI
</div>
<div id="pdf_maxbitmap_elem">
<input type="number" id="pdf_maxbitmap" name="maxbitmap" value="0"> Maxbitmap
</div>
<div id="pdf_pdfsettings_elem">
<input type="text" id="pdf_pdfsettings" name="pdfsettings" value="/default"> Pdfsettings
</div>
<form id="pdfop">
<input type="file" name="file">
<input type="button" value="Convert" onclick="pdfConverter()">
Expand Down
10 changes: 7 additions & 3 deletions src/laundry/pdf.clj
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
(io/delete-file path)))))

;; pdf/a converter
(s/defn api-pdf2pdfa [env, tempfile :- java.io.File]
(s/defn api-pdf2pdfa [env, tempfile :- java.io.File, dpinum :- s/Int, maxbitmapnum :- s/Int, pdfsettings :- s/Str]
(let [in-path (.getAbsolutePath tempfile)
out-path (str (.getAbsolutePath tempfile) ".pdf")
dpi (str dpinum)
maxbitmap (str maxbitmapnum)
pdfsettings (str pdfsettings)
res (shell-out! (str (:tools env) "/pdf2pdfa")
in-path out-path)]
in-path out-path dpi maxbitmap pdfsettings)]
(.delete tempfile)
(if (= (:exit res) 0)
(htresp/content-type
Expand Down Expand Up @@ -77,10 +80,11 @@
(api-pdf2txt env tempfile)))
(POST "/pdf2pdfa" []
:summary "attempt to convert a PDF file to PDF/A"
:query-params [{dpi :- s/Int 720} {maxbitmap :- s/Int 0} {pdfsettings :- s/Str "/default"}]
:multipart-params [file :- upload/TempFileUpload]
:middleware [wrap-multipart-params]
(let [tempfile (:tempfile file)
filename (:filename file)]
(info "PDF converter received " filename "(" (:size file) "b)")
(.deleteOnExit tempfile) ;; cleanup if VM is terminated
(api-pdf2pdfa env tempfile))))))
(api-pdf2pdfa env tempfile dpi maxbitmap pdfsettings))))))
15 changes: 15 additions & 0 deletions test/laundry/pdf_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,21 @@
(is (= "application/pdf" (get-in response [:headers "Content-Type"])))
(is (clojure.string/starts-with? body "%PDF-"))))

(deftest ^:integration api-pdf-pdf2pdfa-with-opt-args
(let [app (fixture/get-app)
file (io/file (io/resource "hypno.pdf"))
_ (assert file)
request (-> (mock/request :post "/pdf/pdf2pdfa")
(assoc-in [:query-params :dpi] 720)
(assoc-in [:query-params :maxbitmap] 0)
(assoc-in [:query-params :pdfsettings] "/default")
(merge (peridot.multipart/build {:file file})))
response (app request)
body (ring.util.request/body-string response)]
(is (= 200 (:status response)))
(is (= "application/pdf" (get-in response [:headers "Content-Type"])))
(is (clojure.string/starts-with? body "%PDF-"))))

(deftest ^:integration api-pdf-pdf2txt
(let [app (fixture/get-app)
file (io/file (io/resource "hypno.pdf"))
Expand Down

0 comments on commit a34addb

Please sign in to comment.