Separate paper creation from function tile().
authorPhilipp Spitzer <philipp@spitzer.priv.at>
Fri, 28 Jun 2019 20:41:30 +0000 (22:41 +0200)
committerPhilipp Spitzer <philipp@spitzer.priv.at>
Fri, 28 Jun 2019 20:52:51 +0000 (22:52 +0200)
gimp_passport.py
test_gimp_passport.py

index 2d54f60..5a6d994 100644 (file)
@@ -110,38 +110,21 @@ def cut_lines_xy(img: Image, count_x: int, count_y: int, tile_size: Tuple[int, i
     cut_lines(img, count_y, tile_size[1], margin, spacing, 0)
 
 
-def tile(img: Image, paper_width_mm: float, paper_height_mm: float, margin_mm: float,
-         spacing_mm: float) -> Image:
-    """Create and return image representing paper with specified dimensions and copy the given
-    image as often as possible to the paper.
-
-    :param img: source image that should be copied.
-    :param paper_width_mm: width of the image representing the paper
-    :param paper_height_mm: height of the image representing the paper
-    :param margin_mm: Free space from the paper borders to the edges of the tiled images.
-    :param spacing_mm: Additional space between tiled images.
+def tile(paper: Image, tile: Image, columns: int, rows: int, margin: int, spacing: int):
+    """On the given "paper" create a grid of a tile with the given number of columns and rows.
+
+    :param paper: image that should be modified
+    :param tile: image that should be duplicated
+    :param columns: number of grid columns
+    :param rows: number of grid rows
+    :param margin: space between paper border and first tile in pixel.
+    :param spacing: space between tiles in pixel.
     """
-    dpi = img.info['dpi'][0]
-    paper_width_pixel = mm_to_pixel(paper_width_mm, dpi)
-    paper_height_pixel = mm_to_pixel(paper_height_mm, dpi)
-    margin_pixel = mm_to_pixel(margin_mm, dpi)
-    spacing_pixel = mm_to_pixel(spacing_mm, dpi)
-    paper = Image.new('RGB', (paper_width_pixel, paper_height_pixel), 'white')
-    paper.info['dpi'] = (dpi, dpi)
-    top = margin_pixel
-    for iy in count():
-        bottom = top + img.height
-        if bottom > paper_height_pixel - margin_pixel:
-            break
-        left = margin_pixel
-        for ix in count():
-            right = left + img.width
-            if right > paper_width_pixel - margin_pixel:
-                break
-            paper.paste(img, (left, top))
-            left = right + spacing_pixel
-        top = bottom + spacing_pixel
-    return paper
+    for c in range(columns):
+        left = tile_edge(c, tile.width, margin, spacing)
+        for r in range(rows):
+            top = tile_edge(r, tile.height, margin, spacing)
+            paper.paste(tile, (left, top))
 
 
 def downsample_large(img: Image, max_dpi: Optional[int]) -> Image:
@@ -165,15 +148,17 @@ def main(paper_width_mm: float, paper_height_mm: float, paper_margin_mm: float,
          max_dpi: Optional[int],
          bbox: Tuple[int,int,int,int],
          source_image: str, dest_image: str):
-    img = Image.open(source_image)
-    photo = make_passport(img, bbox, 0.75, photo_width_mm, photo_height_mm)
-    paper = tile(photo, paper_width_mm, paper_height_mm, paper_margin_mm, photo_spacing_mm)
-    dpi = paper.info['dpi'][0]
+    orig_photo = Image.open(source_image)
+    passport_tile = make_passport(orig_photo, bbox, 0.75, photo_width_mm, photo_height_mm)
+    dpi = passport_tile.info['dpi'][0]
+    paper = Image.new('RGB', (mm_to_pixel(paper_width_mm, dpi), mm_to_pixel(paper_height_mm, dpi)), 'white')
+    paper.info['dpi'] = (dpi, dpi)
     margin = mm_to_pixel(paper_margin_mm, dpi)
     spacing = mm_to_pixel(photo_spacing_mm, dpi)
-    count_x = num_tiles(paper.width, photo.width, margin, spacing)
-    count_y = num_tiles(paper.height, photo.height, margin, spacing)
-    cut_lines_xy(paper, count_x, count_y, photo.size, margin, spacing)
+    columns = num_tiles(paper.width, passport_tile.width, margin, spacing)
+    rows = num_tiles(paper.height, passport_tile.height, margin, spacing)
+    tile(paper, passport_tile, columns, rows, margin, spacing)
+    cut_lines_xy(paper, columns, rows, passport_tile.size, margin, spacing)
     paper = downsample_large(paper, max_dpi)
     paper.save(dest_image, dpi=paper.info['dpi'])
 
index bb1ef47..6e73a51 100644 (file)
@@ -54,11 +54,14 @@ class TestMakePassport(unittest.TestCase):
 
     def test_tile(self):
         dpi = 90
-        img = Image.new('RGB', (mm_to_pixel(35, dpi), mm_to_pixel(45, dpi)), 'lightgray')
-        img.info['dpi'] = (dpi, dpi)
-        draw = ImageDraw.ImageDraw(img)
-        draw.rectangle((0, 0, img.width, img.height-1), outline='black')
-        paper = tile(img, 150, 100, 4, 2.)
+        passport_tile = Image.new('RGB', (mm_to_pixel(35, dpi), mm_to_pixel(45, dpi)), 'lightgray')
+        passport_tile.info['dpi'] = (dpi, dpi)
+        draw = ImageDraw.ImageDraw(passport_tile)
+        draw.rectangle((0, 0, passport_tile.width-1, passport_tile.height-1), outline='black')
+
+        paper = Image.new('RGB', (mm_to_pixel(150, dpi), mm_to_pixel(100, dpi)), 'white')
+        paper.info['dpi'] = (dpi, dpi)
+        tile(paper, passport_tile, 4, 2, 5, 3)
         self.assertIsInstance(paper, Image.Image)
 
     def test_downsample_large(self):