Supporte les PDF comme images à mettre en gabarit.
This commit is contained in:
@@ -3,6 +3,7 @@ FROM python:3.10-alpine
|
|||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt /app
|
COPY requirements.txt /app
|
||||||
|
RUN apk add py3-pdf2image
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||||
pip3 install -r requirements.txt
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
|
41
app/app.py
41
app/app.py
@@ -5,9 +5,23 @@ import io
|
|||||||
import zipfile
|
import zipfile
|
||||||
from werkzeug.datastructures import FileStorage
|
from werkzeug.datastructures import FileStorage
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
from pdf2image import convert_from_bytes
|
||||||
|
from PyPDF2 import PdfReader
|
||||||
|
|
||||||
VALID_KIND = ["all", "tc", "zc", "zip"]
|
VALID_KIND = ["all", "tc", "zc", "zip"]
|
||||||
ALLOWED_EXTENSIONS = ["png", "jpeg", "jpg"]
|
ALLOWED_EXTENSIONS = ["png", "jpeg", "jpg", "pdf"]
|
||||||
|
|
||||||
|
# Function to get the dimensions of the source PDF page
|
||||||
|
|
||||||
|
|
||||||
|
def get_page_dimensions(pdfData, page_number=0):
|
||||||
|
reader = PdfReader(pdfData)
|
||||||
|
page = reader.pages[page_number]
|
||||||
|
width = float(page.mediabox.width)
|
||||||
|
height = float(page.mediabox.height)
|
||||||
|
width = width * (page.user_unit / 72) * 25.4
|
||||||
|
height = height * (page.user_unit / 72) * 25.4
|
||||||
|
return width, height
|
||||||
|
|
||||||
|
|
||||||
def generateTemplate(width: int, height: int, fondPerdu: int, zoneTranquille: int, marge: int, kind: str = "all", image: FileStorage = None, aFondPerdu: bool = False) -> fpdf.FPDF:
|
def generateTemplate(width: int, height: int, fondPerdu: int, zoneTranquille: int, marge: int, kind: str = "all", image: FileStorage = None, aFondPerdu: bool = False) -> fpdf.FPDF:
|
||||||
@@ -20,15 +34,27 @@ def generateTemplate(width: int, height: int, fondPerdu: int, zoneTranquille: in
|
|||||||
pdf.set_auto_page_break(False)
|
pdf.set_auto_page_break(False)
|
||||||
pdf.add_page()
|
pdf.add_page()
|
||||||
|
|
||||||
if (image):
|
xy, w, h = margeDuContenue, width, height
|
||||||
|
if (aFondPerdu == True):
|
||||||
|
xy = xy - fondPerdu
|
||||||
|
w = w + fondPerdu*2
|
||||||
|
h = h + fondPerdu*2
|
||||||
|
|
||||||
|
if (image and image.mimetype in ["image/jpeg", "image/png"]):
|
||||||
if 'inMemoryImage' not in flask.g:
|
if 'inMemoryImage' not in flask.g:
|
||||||
flask.g.inMemoryImage = io.BytesIO()
|
flask.g.inMemoryImage = io.BytesIO()
|
||||||
image.save(flask.g.inMemoryImage)
|
image.save(flask.g.inMemoryImage)
|
||||||
xy, w, h = margeDuContenue, width, height
|
|
||||||
if (aFondPerdu == True):
|
if (image and image.mimetype in ["application/pdf", "application/x-pdf"]):
|
||||||
xy = xy - fondPerdu
|
if 'inMemoryImage' not in flask.g:
|
||||||
w = w + fondPerdu*2
|
pdfData = image.stream.read()
|
||||||
h = h + fondPerdu*2
|
pdfW, pdfH = get_page_dimensions(io.BytesIO(pdfData))
|
||||||
|
scale = min(pdfW/w, pdfH/h)
|
||||||
|
imageFromPDF = convert_from_bytes(
|
||||||
|
pdfData, dpi=600, size=(w*scale, h*scale), single_file=True)
|
||||||
|
flask.g.inMemoryImage = imageFromPDF[0]
|
||||||
|
|
||||||
|
if ('inMemoryImage' in flask.g):
|
||||||
pdf.image(flask.g.inMemoryImage, xy, xy, w, h, keep_aspect_ratio=True)
|
pdf.image(flask.g.inMemoryImage, xy, xy, w, h, keep_aspect_ratio=True)
|
||||||
|
|
||||||
if (kind in ["all", "zc"]):
|
if (kind in ["all", "zc"]):
|
||||||
@@ -151,4 +177,3 @@ def generate():
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0', port=8000)
|
app.run(host='0.0.0.0', port=8000)
|
||||||
|
|
||||||
|
@@ -1,2 +1,4 @@
|
|||||||
flask
|
flask
|
||||||
fpdf2
|
fpdf2
|
||||||
|
PyPDF2
|
||||||
|
pdf2image
|
@@ -86,14 +86,16 @@
|
|||||||
<label for="rb_tc">Traits de coupe</label><input required type="radio" value="tc" name="kind" id="rb_tc">
|
<label for="rb_tc">Traits de coupe</label><input required type="radio" value="tc" name="kind" id="rb_tc">
|
||||||
<label for="rb_zc">Zone de construction</label><input required type="radio" value="zc" name="kind"
|
<label for="rb_zc">Zone de construction</label><input required type="radio" value="zc" name="kind"
|
||||||
id="rb_zc">
|
id="rb_zc">
|
||||||
<label for="rb_all">Zone de construction & traits de coupe</label><input required type="radio" value="all" name="kind" id="rb_all">
|
<label for="rb_all">Zone de construction & traits de coupe</label><input required type="radio" value="all"
|
||||||
<label for="rb_zip">ZIP (3 PDF en 1 clique)</label><input required type="radio" value="zip" name="kind" id="rb_zip" checked>
|
name="kind" id="rb_all">
|
||||||
|
<label for="rb_zip">ZIP (3 PDF en 1 clique)</label><input required type="radio" value="zip" name="kind"
|
||||||
|
id="rb_zip" checked>
|
||||||
</div>
|
</div>
|
||||||
<div class="two-col">
|
<div class="two-col">
|
||||||
<span>
|
<span>
|
||||||
<span class="sectionTitle">Mettre en gabarit</span>
|
<span class="sectionTitle">Mettre en gabarit</span>
|
||||||
<span><br />PNG ou JPEG uniquement</span></span>
|
<span><br />PNG, JPEG ou PDF uniquement</span></span>
|
||||||
<input type="file" name="file" accept="image/png, image/jpeg">
|
<input type="file" name="file" accept="image/png, image/jpeg, application/pdf, application/x-pdf">
|
||||||
<label for="cb_fp">Fond perdu</label><input type="checkbox" name="ffp">
|
<label for="cb_fp">Fond perdu</label><input type="checkbox" name="ffp">
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" value="Générer">
|
<input type="submit" value="Générer">
|
||||||
|
@@ -7,6 +7,8 @@ services:
|
|||||||
# flask requires SIGINT to stop gracefully
|
# flask requires SIGINT to stop gracefully
|
||||||
# (default stop signal from Compose is SIGTERM)
|
# (default stop signal from Compose is SIGTERM)
|
||||||
stop_signal: SIGINT
|
stop_signal: SIGINT
|
||||||
|
ports:
|
||||||
|
- 5000:8000
|
||||||
labels:
|
labels:
|
||||||
traefik.enable: true
|
traefik.enable: true
|
||||||
traefik.http.routers.templatepdf.rule: Host(`template.ar2000.me`)
|
traefik.http.routers.templatepdf.rule: Host(`template.ar2000.me`)>
|
Reference in New Issue
Block a user