Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added tile command to cli #35

Closed
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ history and [GitHubs 'Contributors' feature](https://github.com/py-pdf/pdfly/gra
## Contributors to the pdfly project

* [Thoma, Martin](https://github.com/MartinThoma): Creator of pdfly. [LinkedIn](https://www.linkedin.com/in/martin-thoma/) | [StackOverflow](https://stackoverflow.com/users/562769/martin-thoma) | [Blog](https://martin-thoma.com/)
* [Ulrych, Stanislav](https://github.com/stanislavulrych)

## Adding a new contributor

Expand Down
13 changes: 13 additions & 0 deletions pdfly/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import pdfly.pagemeta
import pdfly.up2
import pdfly.x2pdf
import pdfly.tiles


def version_callback(value: bool) -> None:
Expand Down Expand Up @@ -218,10 +219,22 @@ def x2pdf(
return pdfly.x2pdf.main(x, output)


@entry_point.command(name="tiles") # type: ignore[misc]
def tiles(
output: Path = typer.Option(..., "-o", "--output"),
xcount: int = typer.Option(2, "-x", "--xcount"),
ycount: int = typer.Option(2, "-y", "--ycount"),
files: List[str] = typer.Argument( # noqa
..., help="filenames and/or page ranges"
),
) -> None:
return pdfly.tiles.main(output, xcount, ycount, files,)

up2.__doc__ = pdfly.up2.__doc__
extract_images.__doc__ = pdfly.extract_images.__doc__
cat.__doc__ = pdfly.cat.__doc__
metadata.__doc__ = pdfly.metadata.__doc__
pagemeta.__doc__ = pdfly.pagemeta.__doc__
compress.__doc__ = pdfly.compress.__doc__
x2pdf.__doc__ = pdfly.x2pdf.__doc__
tiles.__doc__ = pdfly.tiles.__doc__
91 changes: 91 additions & 0 deletions pdfly/tiles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
"""
Crope and merge PDF files into a single PDF as a layout of `xcount` x `ycount` tiles.

Especially useful when layouting on A4 printable sticker paper.

Currently only limited to A4 (portrait) input and output format.

Use '-' to omit the file.

`-x` and `-y` parameters specify the tiles size in relation to A4 format.

A5: `-x 1 -y 2` (landscape)
A6: `-x 2 -y 2` (portrait) - the default
A7: `-x 2 -y 4` (landscape)
A8: `-x 4 -y 4` (portrait)
...

Examples

pdfly tiles -o out.pdf -x 2 -y 2 A.pdf B.pdf C.pdf D.pdf

Merge the top left (A6) corners of provided PDFs (A4) as A6 tiles into a single page (A4).

A | B | C | D | A | B
--|-- --|-- --|-- --|-- ===> --|--
| | | | C | D


pdfly tiles -o out.pdf - A.pdf B.pdf C.pdf

Omitting one position by using `-` (also omitted -x 2 -y 2 as those are by default).

A | B | C | | A
--|-- --|-- --|-- ===> --|--
| | | B | C

"""

# Stanislav Ulrych <[email protected]>.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't add such comments


import os
import sys
import traceback
from pathlib import Path
from typing import List

from pypdf import PdfReader, PdfWriter, Transformation, PaperSize


def main(
output: Path, xcount: int, ycount: int, fn_pgrgs: List[str]
) -> None:
if output:
output_fh = open(output, "wb")
else:
sys.stdout.flush()
output_fh = os.fdopen(sys.stdout.fileno(), "wb")

xsize = PaperSize.A4.width
ysize = PaperSize.A4.height

writer = PdfWriter()
destPage = writer.add_blank_page(width=xsize, height=ysize)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow PEP-8:

Suggested change
destPage = writer.add_blank_page(width=xsize, height=ysize)
dest_page = writer.add_blank_page(width=xsize, height=ysize)

try:
for i in range(len(fn_pgrgs)):
f = fn_pgrgs[i]
if f == "-":
continue

reader = PdfReader(f)
for p in reader.pages:
t = {
"tx": (i % xcount)*(xsize/xcount),
"ty": -(i // xcount)*(ysize/ycount)
}
print(t)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print(t)

p.add_transformation(Transformation().translate(**t))
destPage.merge_page(p)

writer.write(output_fh)
except Exception:
print(traceback.format_exc(), file=sys.stderr)
print(f"Error while reading {f}", file=sys.stderr)
sys.exit(1)
finally:
output_fh.close()
# In 3.0, input files must stay open until output is written.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that true for Python 2.x as well ... and any programming language for that matter?

Suggested change
# In 3.0, input files must stay open until output is written.

# Not closing the in_fs because this script exits now.



Loading