1
0
Fork 0
forked from josch/plakativ

refactor member variables

This commit is contained in:
Johannes 'josch' Schauer 2019-07-02 11:55:27 +02:00
parent 7c43609e92
commit d0f91abf6f
Signed by untrusted user: josch
GPG key ID: F2CBA5C78FBD83E1

View file

@ -37,47 +37,50 @@ def pt_to_mm(length):
return (25.4 * length) / 72.0 return (25.4 * length) / 72.0
class Plakativ: class PlakativException(Exception):
def __init__(self, infile=None): pass
self.doc = None
if infile is not None:
self.open(infile)
def open(self, infile):
class PageNrOutOfRangeException(PlakativException):
pass
class LayoutNotComputedException(PlakativException):
pass
class Plakativ:
def __init__(self, infile, pagenr=1):
self.doc = fitz.open(infile) self.doc = fitz.open(infile)
# only allow pdf documents with exactly a single page self.pagenr = pagenr
assert len(self.doc) == 1
self.dlist = self.doc[0].getDisplayList()
self.border_left = 20 self.border_left = 20
self.border_right = 20 self.border_right = 20
self.border_top = 20 self.border_top = 20
self.border_bottom = 20 self.border_bottom = 20
self.config = {
"input_pagesize": ( def set_input_pagenr(self, pagenr):
pt_to_mm(self.dlist.rect.width), if pagenr < 1 or pagenr >= len(self.doc):
pt_to_mm(self.dlist.rect.height), raise PageNrOutOfRangeException()
),
"postersize": PAGE_SIZES["A1 (59.4 cm × 84.1 cm)"], self.pagenr = pagenr
}
self.layout = {"output_pagesize": PAGE_SIZES["A4 (21.0 cm × 29.7 cm)"]} def get_input_page_size(self):
width = self.doc[self.pagenr - 1].getDisplayList().rect.width
height = self.doc[self.pagenr - 1].getDisplayList().rect.height
return (width, height)
def get_image(self, zoom):
mat_0 = fitz.Matrix(zoom, zoom)
pix = (
self.doc[self.pagenr - 1]
.getDisplayList()
.getPixmap(matrix=mat_0, alpha=False)
)
return pix.getImageData("ppm")
def compute_layout(self, mode, size=None, mult=None, npages=None): def compute_layout(self, mode, size=None, mult=None, npages=None):
if self.doc is None: self.layout = {"output_pagesize": PAGE_SIZES["A4 (21.0 cm × 29.7 cm)"]}
return
self.config["mode"] = mode
self.config["postersize"] = None
self.config["mult"] = None
self.config["npages"] = None
if mode == "size":
self.config["postersize"] = size
elif mode == "mult":
self.config["mult"] = mult
elif mode == "npages":
self.config["npages"] = npages
else:
raise Exception("unsupported mode: %s" % mode)
printable_width = self.layout["output_pagesize"][0] - ( printable_width = self.layout["output_pagesize"][0] - (
self.border_left + self.border_right self.border_left + self.border_right
@ -85,27 +88,21 @@ class Plakativ:
printable_height = self.layout["output_pagesize"][1] - ( printable_height = self.layout["output_pagesize"][1] - (
self.border_top + self.border_bottom self.border_top + self.border_bottom
) )
inpage_width = pt_to_mm(self.doc[self.pagenr - 1].getDisplayList().rect.width)
inpage_height = pt_to_mm(self.doc[self.pagenr - 1].getDisplayList().rect.height)
if mode in ["size", "mult"]: if mode in ["size", "mult"]:
if mode == "size": if mode == "size":
# fit the input page size into the selected postersize # fit the input page size into the selected postersize
poster_width = self.config["postersize"][0] poster_width = size[0]
poster_height = ( poster_height = (poster_width * inpage_height) / inpage_width
poster_width * self.config["input_pagesize"][1] if poster_height > size[1]:
) / self.config["input_pagesize"][0] poster_height = size[1]
if poster_height > self.config["postersize"][1]: poster_width = (poster_height * inpage_width) / inpage_height
poster_height = self.config["postersize"][1]
poster_width = (
poster_height * self.config["input_pagesize"][0]
) / self.config["input_pagesize"][1]
elif mode == "mult": elif mode == "mult":
area = self.config["input_pagesize"][0] * self.config["input_pagesize"][1] * mult area = inpage_width * inpage_height * mult
poster_width = math.sqrt( poster_width = math.sqrt(area * inpage_width / inpage_height)
area * self.config["input_pagesize"][0] / self.config["input_pagesize"][1] poster_height = math.sqrt(area * inpage_height / inpage_width)
)
poster_height = math.sqrt(
area * self.config["input_pagesize"][1] / self.config["input_pagesize"][0]
)
else: else:
raise Exception("unsupported mode: %s" % mode) raise Exception("unsupported mode: %s" % mode)
@ -143,22 +140,18 @@ class Plakativ:
# postersize with N pages # postersize with N pages
best_area = 0 best_area = 0
best = None best = None
for x in range(1, self.config["npages"] + 1): for x in range(1, npages + 1):
for y in range(1, self.config["npages"] + 1): for y in range(1, npages + 1):
if x * y > self.config["npages"]: if x * y > npages:
continue continue
width_portrait = x * printable_width width_portrait = x * printable_width
height_portrait = y * printable_height height_portrait = y * printable_height
poster_width = width_portrait poster_width = width_portrait
poster_height = ( poster_height = (poster_width * inpage_height) / inpage_width
poster_width * self.config["input_pagesize"][1]
) / self.config["input_pagesize"][0]
if poster_height > height_portrait: if poster_height > height_portrait:
poster_height = height_portrait poster_height = height_portrait
poster_width = ( poster_width = (poster_height * inpage_width) / inpage_height
poster_height * self.config["input_pagesize"][0]
) / self.config["input_pagesize"][1]
area_portrait = poster_width * poster_height area_portrait = poster_width * poster_height
@ -170,14 +163,10 @@ class Plakativ:
height_landscape = y * printable_width height_landscape = y * printable_width
poster_width = width_landscape poster_width = width_landscape
poster_height = ( poster_height = (poster_width * inpage_height) / inpage_width
poster_width * self.config["input_pagesize"][1]
) / self.config["input_pagesize"][0]
if poster_height > height_landscape: if poster_height > height_landscape:
poster_height = height_landscape poster_height = height_landscape
poster_width = ( poster_width = (poster_height * inpage_width) / inpage_height
poster_height * self.config["input_pagesize"][0]
) / self.config["input_pagesize"][1]
area_landscape = poster_width * poster_height area_landscape = poster_width * poster_height
@ -211,43 +200,38 @@ class Plakativ:
posy = y * printable_width posy = y * printable_width
self.layout["positions"].append((posx, posy, portrait)) self.layout["positions"].append((posx, posy, portrait))
# return (self.postersize, (poster_width*poster_height)/(pt_to_mm(self.dlist.rect.width)*pt_to_mm(self.dlist.rect.height)), pages_x*pages_y)
if mode == "size": if mode == "size":
self.config["mult"] = (poster_width * poster_height) / ( mult = (poster_width * poster_height) / (inpage_width * inpage_height)
self.config["input_pagesize"][0] * self.config["input_pagesize"][1] npages = pages_x * pages_y
)
self.config["npages"] = pages_x * pages_y
elif mode == "mult": elif mode == "mult":
self.config["postersize"] = poster_width, poster_height size = poster_width, poster_height
self.config["npages"] = pages_x * pages_y npages = pages_x * pages_y
elif mode == "npages": elif mode == "npages":
self.config["postersize"] = poster_width, poster_height size = poster_width, poster_height
self.config["mult"] = (poster_width * poster_height) / ( mult = (poster_width * poster_height) / (inpage_width * inpage_height)
self.config["input_pagesize"][0] * self.config["input_pagesize"][1]
)
else: else:
raise Exception("unsupported mode: %s" % mode) raise Exception("unsupported mode: %s" % mode)
return self.config["postersize"], self.config["mult"], self.config["npages"] return size, mult, npages
def render(self, outfile): def render(self, outfile):
outdoc = fitz.open() if not hasattr(self, "layout"):
raise LayoutNotComputedException()
xref = 0 inpage_width = pt_to_mm(self.doc[self.pagenr - 1].getDisplayList().rect.width)
r = self.dlist.rect
outdoc = fitz.open()
for (x, y, portrait) in self.layout["positions"]: for (x, y, portrait) in self.layout["positions"]:
if portrait: if portrait:
page_width=mm_to_pt(self.layout["output_pagesize"][0]) page_width = mm_to_pt(self.layout["output_pagesize"][0])
page_height=mm_to_pt(self.layout["output_pagesize"][1]) page_height = mm_to_pt(self.layout["output_pagesize"][1])
else: else:
page_width=mm_to_pt(self.layout["output_pagesize"][1]) page_width = mm_to_pt(self.layout["output_pagesize"][1])
page_height=mm_to_pt(self.layout["output_pagesize"][0]) page_height = mm_to_pt(self.layout["output_pagesize"][0])
page = outdoc.newPage( page = outdoc.newPage(
-1, # insert after last page -1, width=page_width, height=page_height # insert after last page
width=page_width, )
height=page_height,
)
target_x = ( target_x = (
x - self.layout["overallsize"][0] / 2 + self.layout["postersize"][0] / 2 x - self.layout["overallsize"][0] / 2 + self.layout["postersize"][0] / 2
@ -283,7 +267,7 @@ class Plakativ:
mm_to_pt(target_yoffset + target_height), mm_to_pt(target_yoffset + target_height),
) )
factor = self.config["input_pagesize"][0] / self.layout["postersize"][0] factor = inpage_width / self.layout["postersize"][0]
sourcerect = fitz.Rect( sourcerect = fitz.Rect(
mm_to_pt(factor * target_x), mm_to_pt(factor * target_x),
mm_to_pt(factor * target_y), mm_to_pt(factor * target_y),
@ -291,13 +275,11 @@ class Plakativ:
mm_to_pt(factor * (target_y + target_height)), mm_to_pt(factor * (target_y + target_height)),
) )
# update xref page.showPDFpage(
xref = page.showPDFpage(
targetrect, # fill the whole page targetrect, # fill the whole page
self.doc, # input document self.doc, # input document
0, # input page number self.pagenr - 1, # input page number
clip=sourcerect, # part of the input page to use clip=sourcerect, # part of the input page to use
#rotate=0 if portrait else 90,
) )
outdoc.save(outfile, garbage=4, deflate=True) outdoc.save(outfile, garbage=4, deflate=True)
@ -418,9 +400,7 @@ class Application(tkinter.Frame):
self.pack(fill=tkinter.BOTH, expand=tkinter.TRUE) self.pack(fill=tkinter.BOTH, expand=tkinter.TRUE)
if plakativ is None: if plakativ is not None:
self.plakativ = Plakativ()
else:
self.plakativ = plakativ self.plakativ = plakativ
self.border_left = tkinter.DoubleVar(value=20.0) self.border_left = tkinter.DoubleVar(value=20.0)
@ -471,7 +451,7 @@ class Application(tkinter.Frame):
pagesize_group.pack(fill=tkinter.X) pagesize_group.pack(fill=tkinter.X)
pagesize_fixed = tkinter.StringVar() pagesize_fixed = tkinter.StringVar()
if self.plakativ.doc is None: if not hasattr(self, "plakativ"):
pagesize_fixed.set("") pagesize_fixed.set("")
else: else:
pagesize_fixed.set( pagesize_fixed.set(
@ -484,7 +464,7 @@ class Application(tkinter.Frame):
pagesize_fixed, pagesize_fixed,
*PAGE_SIZES.keys(), *PAGE_SIZES.keys(),
command=self.on_select_pagesize, command=self.on_select_pagesize,
state=tkinter.DISABLED if self.plakativ.doc is None else tkinter.NORMAL state=tkinter.DISABLED if not hasattr(self, "plakativ") else tkinter.NORMAL
) )
pagesize_options.grid(row=1, column=0, columnspan=3, sticky=tkinter.W) pagesize_options.grid(row=1, column=0, columnspan=3, sticky=tkinter.W)
@ -595,7 +575,7 @@ class Application(tkinter.Frame):
self.postersize = PostersizeWidget(frame1.interior) self.postersize = PostersizeWidget(frame1.interior)
self.postersize.pack(fill=tkinter.X) self.postersize.pack(fill=tkinter.X)
self.postersize.set("size", (False, (594, 841)), 1.0, 1) self.postersize.set("size", (False, (594, 841)), 1.0, 1)
if self.plakativ.doc is not None: if hasattr(self, "plakativ"):
self.postersize.callback = self.on_postersize self.postersize.callback = self.on_postersize
layouter_group = tkinter.LabelFrame(frame1.interior, text="Layouter") layouter_group = tkinter.LabelFrame(frame1.interior, text="Layouter")
@ -654,12 +634,7 @@ class Application(tkinter.Frame):
mode, (custom_size, size), mult, npages = value mode, (custom_size, size), mult, npages = value
size, mult, npages = self.plakativ.compute_layout(mode, size, mult, npages) size, mult, npages = self.plakativ.compute_layout(mode, size, mult, npages)
self.draw() self.draw()
return ( return (mode, (custom_size, size), mult, npages)
mode,
(custom_size, size),
mult,
npages,
)
def on_border(self): def on_border(self):
self.posterizer.border_left = self.border_left.get() self.posterizer.border_left = self.border_left.get()
@ -682,19 +657,20 @@ class Application(tkinter.Frame):
# clean canvas # clean canvas
self.canvas.delete(tkinter.ALL) self.canvas.delete(tkinter.ALL)
if self.plakativ.doc is None: if not hasattr(self, "plakativ"):
return return
canvas_padding = 10 canvas_padding = 10
r = self.plakativ.dlist.rect width, height = self.plakativ.get_input_page_size()
zoom_0 = min( zoom_0 = min(
self.canvas_size[0] self.canvas_size[0]
/ r.width / width
* self.plakativ.layout["postersize"][0] * self.plakativ.layout["postersize"][0]
/ (self.plakativ.layout["overallsize"][0] + canvas_padding), / (self.plakativ.layout["overallsize"][0] + canvas_padding),
self.canvas_size[1] self.canvas_size[1]
/ r.height / height
* self.plakativ.layout["postersize"][1] * self.plakativ.layout["postersize"][1]
/ (self.plakativ.layout["overallsize"][1] + canvas_padding), / (self.plakativ.layout["overallsize"][1] + canvas_padding),
) )
@ -706,15 +682,13 @@ class Application(tkinter.Frame):
/ (self.plakativ.layout["overallsize"][1] + canvas_padding), / (self.plakativ.layout["overallsize"][1] + canvas_padding),
) )
mat_0 = fitz.Matrix(zoom_0, zoom_0) img = self.plakativ.get_image(zoom_0)
pix = self.plakativ.dlist.getPixmap(matrix=mat_0, alpha=False)
img = pix.getImageData("ppm")
tkimg = tkinter.PhotoImage(data=img) tkimg = tkinter.PhotoImage(data=img)
# draw image # draw image
self.canvas.create_image( self.canvas.create_image(
(self.canvas_size[0] - zoom_0 * r.width) / 2, (self.canvas_size[0] - zoom_0 * width) / 2,
(self.canvas_size[1] - zoom_0 * r.height) / 2, (self.canvas_size[1] - zoom_0 * height) / 2,
anchor=tkinter.NW, anchor=tkinter.NW,
image=tkimg, image=tkimg,
) )
@ -758,18 +732,13 @@ class Application(tkinter.Frame):
if filename == (): if filename == ():
return return
self.filename = filename self.filename = filename
self.plakativ.open(self.filename) self.plakativ = Plakativ(self.filename)
# compute the splitting with the current values # compute the splitting with the current values
mode, (_, size), mult, npages = self.postersize.value mode, (_, size), mult, npages = self.postersize.value
size, mult, npages = self.plakativ.compute_layout(mode, size, mult, npages) size, mult, npages = self.plakativ.compute_layout(mode, size, mult, npages)
# copy computed values to postersize widget # copy computed values to postersize widget
mode, (custom_size, _), _, _ = self.postersize.value mode, (custom_size, _), _, _ = self.postersize.value
self.postersize.value = ( self.postersize.value = (mode, (custom_size, size), mult, npages)
mode,
(custom_size, size),
mult,
npages,
)
# update postersize widget # update postersize widget
self.postersize.set(*self.postersize.value) self.postersize.set(*self.postersize.value)
# draw preview in canvas # draw preview in canvas
@ -1058,6 +1027,7 @@ def main():
compute_layout(args.input, args.output, mode="size", size=(297, 420)) compute_layout(args.input, args.output, mode="size", size=(297, 420))
if __name__ == "__main__": if __name__ == "__main__":
main() main()