Compare commits

...

10 Commits
V0.9 ... master

10 changed files with 259 additions and 120 deletions

29
.gitignore vendored Normal file
View File

@ -0,0 +1,29 @@
example/build
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

104
example/album.py Normal file
View File

@ -0,0 +1,104 @@
from photobook import Photobook
from pathlib import Path
name = "album"
pagesize = (250, 200)
src_fig = Path("./fig/")
output = Path("./build/")
dest = output / (name + ".pdf")
out_fig = output / "fig"
photobook = Photobook(name, pdf_size=pagesize, base_fig=src_fig, margin=5, img_px=2)
photobook.set_font("Arial", "B", 20)
photobook.set_auto_page_break(False)
photobook.set_fig_folder("textures")
photobook.one_centered("eugene.jpg", "one_centered default")
photobook.one_centered("eugene.jpg", "")
photobook.one_centered(
"eugene.jpg", "one_centered text_ratio=1, img_ratio=1", text_ratio=1, img_ratio=1
)
photobook.one_side("eugene.jpg", "one_side default")
photobook.one_side(
"eugene.jpg", "one_side text_ratio=1, img_ratio=1", text_ratio=1, img_ratio=1
)
photobook.one_side(
"eugene.jpg", "one_side text_ratio=1, img_ratio=1", text_ratio=1, img_ratio=1
)
photobook.grid_row(
[
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
["eugene.jpg", "grid_row default", "eugene.jpg"],
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
],
)
photobook.grid_row(
[
["eugene.jpg", "eugene.jpg"],
[
"eugene.jpg",
"grid_row\nlayout = \n[[1, 2], [1, 1, 1], [2, 1]]",
"eugene.jpg",
],
["eugene.jpg", "eugene.jpg"],
],
layout=[[1, 2], [1, 1, 1], [2, 1]],
)
photobook.grid_row(
[
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
["eugene.jpg", "grid_row ratios=[1, 3, 1]", "eugene.jpg"],
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
],
ratios=[1, 3, 1],
)
photobook.grid_row(
[
["eugene.jpg"],
["eugene.jpg", "grid_row ratios=[1, 3, 1]", "eugene.jpg"],
["eugene.jpg", "eugene.jpg"],
],
ratios=[1, 3, 1],
)
photobook.grid_column(
[
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
["eugene.jpg", "grid_column default", "eugene.jpg"],
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
],
)
photobook.grid_column(
[
["eugene.jpg", "eugene.jpg"],
[
"eugene.jpg",
"grid_column\nlayout = \n[[1, 2], [1, 1, 1], [2, 1]]",
"eugene.jpg",
],
["eugene.jpg", "eugene.jpg"],
],
layout=[[1, 2], [1, 1, 1], [2, 1]],
)
photobook.grid_column(
[
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
["eugene.jpg", "grid_column ratios=[1, 3, 1]", "eugene.jpg"],
["eugene.jpg", "eugene.jpg", "eugene.jpg"],
],
ratios=[1, 3, 1],
)
photobook.grid_column(
[
["eugene.jpg"],
["eugene.jpg", "grid_column ratios=[1, 3, 1]", "eugene.jpg"],
["eugene.jpg", "eugene.jpg"],
],
ratios=[1, 3, 1],
)
photobook.output(dest)

BIN
example/fig/food/crepe.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
example/fig/food/glass.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
example/fig/food/muffle.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

View File

@ -1,12 +1,17 @@
from fpdf import FPDF
from .cropping import cut_save
from pathlib import Path from pathlib import Path
from fpdf import FPDF
from .cropping import cut_save
class Photobook(FPDF): class Photobook(FPDF):
FIG = Path("./fig/") FIG = Path("./fig/")
OUT = Path("./build/") OUT = Path("./build/")
def __init__(self, name, def __init__(
self,
name,
bg_color=(0, 0, 0), bg_color=(0, 0, 0),
txt_color=(255, 255, 255), txt_color=(255, 255, 255),
sep=3, sep=3,
@ -36,7 +41,7 @@ class Photobook(FPDF):
self.l_margin_ori = self.l_margin self.l_margin_ori = self.l_margin
self.r_margin_ori = self.r_margin self.r_margin_ori = self.r_margin
self._fig_folder = Path('') self._fig_folder = Path("")
self._base_fig = Path(base_fig) self._base_fig = Path(base_fig)
self.img_px = img_px self.img_px = img_px
@ -83,7 +88,7 @@ class Photobook(FPDF):
"""Effective page height""" """Effective page height"""
return self.h - 2 * self.t_margin return self.h - 2 * self.t_margin
def add_page(self, orientation='P'): def add_page(self, orientation="P"):
super().add_page(orientation) super().add_page(orientation)
self.rect(0, 0, self.w, self.h, style="F") self.rect(0, 0, self.w, self.h, style="F")
@ -96,20 +101,27 @@ class Photobook(FPDF):
return img_dest return img_dest
def one_fullpage(self, img): def one_fullpage(self, img):
""" Display the picture fullpage """ """Display the picture fullpage with no margin around"""
self.add_page() self.add_page()
self.append_content(img, 0, 0, *self.size) self.append_content(img, 0, 0, *self.size)
# img_dest = self.img_process(img, self.size) # img_dest = self.img_process(img, self.size)
# self.image(img_dest, 0, 0, *self.size) # self.image(img_dest, 0, 0, *self.size)
def one_centered(self, img, text=""): def one_centered(
""" Display the picture centered with text """ self,
img,
text="",
img_ratio=5,
text_ratio=1,
):
"""Display the picture centered with text below"""
self.add_page() self.add_page()
if text == "": total_ratio = img_ratio + text_ratio
text_size = (0, 0) text_size = (
else: self.epw,
text_size = (self.epw, (self.eph-self.sep)/6-self.sep) (self.eph - self.sep) * text_ratio / total_ratio - self.sep,
)
img_size = (self.epw, self.eph - text_size[1]) img_size = (self.epw, self.eph - text_size[1])
img_dest = self.img_process(img, img_size) img_dest = self.img_process(img, img_size)
@ -117,31 +129,45 @@ class Photobook(FPDF):
self.image(img_dest, self.l_margin, self.t_margin, *img_size) self.image(img_dest, self.l_margin, self.t_margin, *img_size)
self.set_xy(self.l_margin, self.t_margin + img_size[1] + self.sep) self.set_xy(self.l_margin, self.t_margin + img_size[1] + self.sep)
if '\n' in text:
self.multi_cell(text_size[0], self.font_size, text, align='J', border=1)
else:
self.cell(text_size[0], text_size[1]-self.sep, text, align='C', border=1)
def one_side(self, img, txt=""): if "\n" in text:
self.multi_cell(text_size[0], self.font_size, text, align="J", border=1)
else:
self.cell(text_size[0], text_size[1] - self.sep, text, align="C", border=1)
def one_side(
self,
img,
txt="",
img_ratio=5,
text_ratio=1,
):
"""Display the image on the outside of the page """Display the image on the outside of the page
along with text on the other side along with text on the other side
""" """
self.add_page() self.add_page()
p_no = self.page_no() p_no = self.page_no()
win_dim = (self.size[0]*2/3, self.size[1])
total_ratio = img_ratio + text_ratio
win_dim = (self.size[0] * img_ratio / total_ratio, self.size[1])
img_dest = self.img_process(img, win_dim) img_dest = self.img_process(img, win_dim)
if p_no % 2 == 1: if p_no % 2 == 1:
self.set_xy(win_dim[0], self.size[1] / 2) self.set_xy(win_dim[0], self.size[1] / 2)
self.multi_cell(self.size[0]/3, self.font_size, txt, align="C") self.multi_cell(
self.size[0] * text_ratio / total_ratio, self.font_size, txt, align="C"
)
self.image(img_dest, 0, 0, *win_dim) self.image(img_dest, 0, 0, *win_dim)
else: else:
self.set_xy(0, self.size[1] / 2) self.set_xy(0, self.size[1] / 2)
self.multi_cell(self.size[0]/3, self.font_size, txt, align="C") self.multi_cell(
self.image(img_dest, self.size[0]/3, 0, *win_dim) self.size[0] * text_ratio / total_ratio, self.font_size, txt, align="C"
)
self.image(img_dest, self.size[0] * text_ratio / total_ratio, 0, *win_dim)
def one_side_nocut(self, img, txt=""): def one_side_nocut(self, img, txt=""):
""" Display the image on the outside of the page without resize it """Display the image on the outside of the page without resize it"""
"""
self.add_page() self.add_page()
p_no = self.page_no() p_no = self.page_no()
win_dim = (self.size[0], self.size[1]) win_dim = (self.size[0], self.size[1])
@ -172,8 +198,7 @@ class Photobook(FPDF):
sep = 0 sep = 0
img_number = len(imgs) img_number = len(imgs)
win_dim = (pg_size[0], win_dim = (pg_size[0], (pg_size[1] - (img_number - 1) * sep) / img_number)
(pg_size[1] - (img_number - 1) * sep) / img_number)
for img in imgs: for img in imgs:
self.append_content(img, left, top, *win_dim) self.append_content(img, left, top, *win_dim)
@ -181,11 +206,12 @@ class Photobook(FPDF):
# self.image(img_dest, left, top, *win_dim) # self.image(img_dest, left, top, *win_dim)
top += win_dim[1] + sep top += win_dim[1] + sep
def grid_row(self, content, layout=[], with_margin=True, with_sep=True): def grid_row(self, content, layout=[], ratios=[], with_margin=True, with_sep=True):
"""Custom layout define by rows """Custom layout define by rows
:param content: img or text to display in layout's cells :param content: img or text to display in layout's cells
:param layout: cell layout with weight (need same shape than content) :param layout: cell layout with weight (need same shape than content)
:param ratios: row's ratio
:param with_margin: Put margins around pictures :param with_margin: Put margins around pictures
:param with_sep: Put separation between pictures :param with_sep: Put separation between pictures
""" """
@ -210,30 +236,43 @@ class Photobook(FPDF):
else: else:
if len(content) != len(layout): if len(content) != len(layout):
raise ValueError("Content and Layout need to have same number of rows") raise ValueError("Content and Layout need to have same number of rows")
for (r, row) in enumerate(content): for r, row in enumerate(content):
if len(row) != len(layout[r]): if len(row) != len(layout[r]):
raise ValueError(f"Content and Layout need to have same number of columns at row {r}") raise ValueError(
f"Content and Layout need to have same number of columns at row {r}"
)
if ratios == []:
ratios = [1 for row in content]
else:
if len(content) != len(ratios):
raise ValueError("Content and ratios need to have same number of rows")
total_ratio = sum(ratios)
top = ori_top top = ori_top
left = ori_left left = ori_left
height_unit = (pg_size[1] - (len(layout) - 1) * sep) / len(layout) height_unit = (pg_size[1] - (len(layout) - 1) * sep) / total_ratio
for (r, row) in enumerate(layout): for r, row in enumerate(layout):
width_unit = (pg_size[0] - (len(row) - 1) * sep) / sum(row) width_unit = (pg_size[0] - (sum(row) - 1) * sep) / sum(row)
row_height = height_unit * ratios[r]
for (c, weight) in enumerate(row): for c, weight in enumerate(row):
dim = (width_unit * weight, height_unit) dim = (width_unit * weight + sep * (weight - 1), row_height)
self.append_content(content[r][c], left, top, *dim) self.append_content(content[r][c], left, top, *dim)
left += dim[0] + sep left += dim[0] + sep
top += height_unit + sep top += row_height + sep
left = ori_left left = ori_left
def grid_column(self, content, layout=[], with_margin=True, with_sep=True): def grid_column(
self, content, layout=[], ratios=[], with_margin=True, with_sep=True
):
"""Custom layout define by column """Custom layout define by column
:param content: img or text to display in layout's cells :param content: img or text to display in layout's cells
:param layout: cell layout with weight (need same shape than content) :param layout: cell layout with weight (need same shape than content)
:param ratios: column's ratio
:param with_margin: Put margins around pictures :param with_margin: Put margins around pictures
:param with_sep: Put separation between pictures :param with_sep: Put separation between pictures
""" """
@ -257,24 +296,38 @@ class Photobook(FPDF):
layout = [[1 for r in column] for column in content] layout = [[1 for r in column] for column in content]
else: else:
if len(content) != len(layout): if len(content) != len(layout):
raise ValueError("Content and Layout need to have same number of columns") raise ValueError(
for (r, column) in enumerate(content): "Content and Layout need to have same number of columns"
)
for r, column in enumerate(content):
if len(column) != len(layout[r]): if len(column) != len(layout[r]):
raise ValueError(f"Content and Layout need to have same number of columns at column {r}") raise ValueError(
f"Content and Layout need to have same number of columns at column {r}"
)
if ratios == []:
ratios = [1 for c in content]
else:
if len(content) != len(ratios):
raise ValueError(
"Content and ratios need to have same number of columns"
)
total_ratio = sum(ratios)
top = ori_top top = ori_top
left = ori_left left = ori_left
width_unit = (pg_size[0] - (len(layout) - 1) * sep) / len(layout) width_unit = (pg_size[0] - (len(layout) - 1) * sep) / total_ratio
for (c, column) in enumerate(layout): for c, column in enumerate(layout):
height_unit = (pg_size[1] - (len(column) - 1) * sep) / sum(column) height_unit = (pg_size[1] - (sum(column) - 1) * sep) / sum(column)
column_width = width_unit * ratios[c]
for (r, weight) in enumerate(column): for r, weight in enumerate(column):
dim = (width_unit, height_unit * weight) dim = (column_width, height_unit * weight + sep * (weight - 1))
self.append_content(content[c][r], left, top, *dim) self.append_content(content[c][r], left, top, *dim)
top += dim[1] + sep top += dim[1] + sep
left += width_unit + sep left += column_width + sep
top = ori_top top = ori_top
def append_content(self, content, left, top, width, height): def append_content(self, content, left, top, width, height):
@ -283,54 +336,7 @@ class Photobook(FPDF):
self.image(img_dest, left, top, width, height) self.image(img_dest, left, top, width, height)
except (FileNotFoundError, IsADirectoryError): except (FileNotFoundError, IsADirectoryError):
self.set_xy(left, top) self.set_xy(left, top)
if '\n' in content: if "\n" in content:
self.multi_cell(width, self.font_size, content, align='J', border=1) self.multi_cell(width, self.font_size, content, align="J", border=1)
else: else:
self.cell(width, height, content, align='C', border=1) self.cell(width, height, content, align="C", border=1)
if __name__ == "__main__":
name = "annee3"
pagesize = (250, 200)
src_fig = Path("./fig/")
output = Path("./build/")
dest = output / (name + ".pdf")
out_fig = output / "fig"
photobook = Photobook(name, pdf_size=pagesize)
photobook.set_font('Arial', 'B', 20)
photobook.set_auto_page_break(False)
photobook.rows(["chronologie/annee3/1-DD/DD-01.jpg"])
photobook.rows(["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"])
photobook.rows(["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"], with_margin=False)
photobook.rows(["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"], with_sep=False)
photobook.rows(["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"], with_margin=False, with_sep=False)
photobook.rows(["chronologie/annee3/1-DD/DD-01.jpg",
"Tralalala",
"chronologie/annee3/1-DD/DD-02.jpg",
"chronologie/annee3/1-DD/DD-02.jpg"])
photobook.grid_row([["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"],
["Coucou c'est moi!!", "chronologie/annee3/1-DD/DD-04.jpg"]],
[[1, 2], [3, 1]],
)
photobook.grid_row([["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"],
["Coucou c'est moi!! \ncjfkldsq", "chronologie/annee3/1-DD/DD-04.jpg"]],
[[1, 2], [3, 1]])
photobook.grid_row([["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"],
["chronologie/annee3/1-DD/DD-03.jpg", "chronologie/annee3/1-DD/DD-04.jpg"]],
[[1, 2], [3, 1]])
photobook.set_top_margin(40)
photobook.grid_row([["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"],
["chronologie/annee3/1-DD/DD-03.jpg", "chronologie/annee3/1-DD/DD-04.jpg"]],
[[1, 2], [3, 1]],)
photobook.restore_margin()
photobook.grid_row([["chronologie/annee3/1-DD/DD-01.jpg", "chronologie/annee3/1-DD/DD-02.jpg"],
["chronologie/annee3/1-DD/DD-03.jpg", "chronologie/annee3/1-DD/DD-04.jpg"]],
[[1, 1], [1, 1]],
with_margin=False, with_sep=False
)
photobook.output(dest)