Work in progress...
authorPhilipp Spitzer <philipp@spitzer.priv.at>
Tue, 11 Jun 2019 07:19:22 +0000 (09:19 +0200)
committerPhilipp Spitzer <philipp@spitzer.priv.at>
Tue, 11 Jun 2019 07:19:22 +0000 (09:19 +0200)
gimp_passport.py
test_gimp_passport.py

index 11a6a8d..db0ff24 100644 (file)
@@ -2,7 +2,7 @@ import argparse
 from itertools import count
 from numbers import Integral
 from typing import Tuple
-from PIL import Image
+from PIL import Image, ImageDraw
 
 
 MM_PER_INCH = 25.4
@@ -69,7 +69,57 @@ def num_tiles_xy(paper_size: Tuple[float, float], tile_size: Tuple[float, float]
     return tuple(num_tiles(ps, ts, margin, spacing) for ps, ts in zip(paper_size, tile_size))
 
 
+def line(img: Image, pos: int, axis: int) -> Image:
+    """Creates a horizontal (axis == 0) or vertical (axis == 1) line over the whole
+    width or height of the image.
+
+    :param img: Image that is modified inline.
+    :param pos: Position in pixel from left or top (0 based)
+    :param axis: 0 means horizontal, 1 means vertical
+    """
+    draw = ImageDraw.ImageDraw(img)
+    color = 'black'
+    if axis == 0:
+        draw.line(((0, pos), (img.width, pos)), color=color)
+    else:
+        draw.line(((pos, 0), (pos, img.height)), color=color)
+
+
 def make_cut_lines(img: Image, count_x: int, count_y: int, width: int, margin: int, spacing: int, 
+                   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.
+    """
+    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
+
+
 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
index eccce43..582c308 100644 (file)
@@ -1,7 +1,7 @@
 import os
 import unittest
 from PIL import Image, ImageDraw
-from gimp_passport import mm_to_pixel, num_tiles, num_tiles_xy, make_passport, tile, main
+from gimp_passport import mm_to_pixel, num_tiles, num_tiles_xy, line, make_passport, tile, main
 
 
 class TestMakePassport(unittest.TestCase):
@@ -36,6 +36,11 @@ class TestMakePassport(unittest.TestCase):
         self.assertEqual((2, 2), num_tiles_xy((45., 10.), (15., 4.), 0., 2.))
         self.assertEqual((2, 1), num_tiles_xy((45., 10.), (15., 5.), 1., 1.))
 
+    def test_line(self):
+        img = Image.new('RGB', (100, 60))
+        line(img, 30, 0)
+        line(img, 40, 1)
+
     def test_tile(self):
         dpi = 90
         img = Image.new('RGB', (mm_to_pixel(35, dpi), mm_to_pixel(45, dpi)), 'lightgray')