diff --git a/PyPDF2/__init__.py b/PyPDF2/__init__.py index 07f211c2b..0d21401ff 100644 --- a/PyPDF2/__init__.py +++ b/PyPDF2/__init__.py @@ -1,11 +1,14 @@ -from ._version import __version__ -from .merger import PdfFileMerger -from .pagerange import PageRange, parse_filename_page_ranges -from .pdf import PdfFileReader, PdfFileWriter +from PyPDF2._version import __version__ +from PyPDF2.merger import PdfFileMerger +from PyPDF2.pagerange import PageRange, parse_filename_page_ranges +from PyPDF2.papersizes import PaperSize +from PyPDF2.pdf import PdfFileReader, PdfFileWriter +from PyPDF2 import pdf __all__ = [ "__version__", "PageRange", + "PaperSize", "parse_filename_page_ranges", "pdf", "PdfFileMerger", diff --git a/PyPDF2/papersizes.py b/PyPDF2/papersizes.py new file mode 100644 index 000000000..c3c0819ab --- /dev/null +++ b/PyPDF2/papersizes.py @@ -0,0 +1,48 @@ +"""Helper to get paper sizes.""" + +from collections import namedtuple + +Dimensions = namedtuple("Dimensions", ["width", "height"]) + + +class PaperSize(object): + """(width, height) of the paper in portrait mode in pixels at 72 ppi.""" + + # Notes how to calculate it: + # 1. Get the size of the paper in mm + # 2. Convert it to inches (25.4 millimeters are equal to 1 inches) + # 3. Convert it to pixels ad 72dpi (1 inch is equal to 72 pixels) + + # All Din-A paper sizes follow this pattern: + # 2xA(n-1) = A(n) + # So the height of the next bigger one is the width of the smaller one + # The ratio is always approximately the ratio 1:2**0.5 + # Additionally, A0 is defined to have an area of 1 m**2 + # Be aware of rounding issues! + A0 = Dimensions(2384, 3370) # 841mm x 1189mm + A1 = Dimensions(1684, 2384) + A2 = Dimensions(1191, 1684) + A3 = Dimensions(842, 1191) + A4 = Dimensions( + 595, 842 + ) # Printer paper, documents - this is by far the most common + A5 = Dimensions(420, 595) # Paperback books + A6 = Dimensions(298, 420) # Post cards + A7 = Dimensions(210, 298) + A8 = Dimensions(147, 210) + + # Envelopes + C4 = Dimensions(649, 918) + + +_din_a = [ + PaperSize.A0, + PaperSize.A1, + PaperSize.A2, + PaperSize.A3, + PaperSize.A4, + PaperSize.A5, + PaperSize.A6, + PaperSize.A7, + PaperSize.A8, +] diff --git a/Tests/test_papersizes.py b/Tests/test_papersizes.py new file mode 100644 index 000000000..b198fbe49 --- /dev/null +++ b/Tests/test_papersizes.py @@ -0,0 +1,30 @@ +from PyPDF2 import papersizes +import pytest + + +def test_din_a0(): + dim = papersizes.PaperSize.A0 + area_square_pixels = float(dim.width) * dim.height + + # 72 pixels is 1 inch + area_square_inch = area_square_pixels / 72**2 + + # 25.4 millimeter is equal to 1 inches + area_square_mm = area_square_inch * (25.4)**2 + assert abs(area_square_mm - 999949) < 100 + conversion_factor = 72 / 25.4 + assert (dim.width - 841 * conversion_factor) < 1 + assert (dim.width - 1189 * conversion_factor) < 1 + + + +@pytest.mark.parametrize("dimensions", papersizes._din_a) +def test_din_a_ratio(dimensions): + assert abs(dimensions.height - dimensions.width * 2**0.5) <= 2.5 + + +@pytest.mark.parametrize( + "dimensions_a, dimensions_b", list(zip(papersizes._din_a, papersizes._din_a[1:])) +) +def test_din_a_doubling(dimensions_a, dimensions_b): + assert abs(dimensions_a.height - 2 * dimensions_b.width) <= 4