summaryrefslogtreecommitdiffstats
path: root/montage_images.py
diff options
context:
space:
mode:
Diffstat (limited to 'montage_images.py')
-rwxr-xr-xmontage_images.py90
1 files changed, 90 insertions, 0 deletions
diff --git a/montage_images.py b/montage_images.py
new file mode 100755
index 0000000..95cf390
--- /dev/null
+++ b/montage_images.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python3
+#
+# Aaron LI
+# Created: 2016-05-08
+# Updated: 2016-05-08
+#
+
+"""
+Make a montage of the input 4 images by utilizing the `montage`
+tool from `ImageMagick`.
+
+Montage:
++----------+----------+
+| | |
+| image1 | image2 |
+| | |
++----------+----------+
+| | |
+| image3 | image4 |
+| | |
++----------+----------+
+
+Note:
+The resolution/dimension of the `image1` is taken as the reference, and
+the other 3 images are re-sized to match it in order to make an compact
+and grid-aligned montage.
+
+
+Credits:
+[1] ImageMagick v6 Examples -- Montage, Arrays of Images
+ https://www.imagemagick.org/Usage/montage/
+[2] ImageMagick montage: Resizing only one input image
+ https://stackoverflow.com/a/26273173/4856091
+"""
+
+
+import subprocess
+import argparse
+
+
+def get_image_size(image):
+ """
+ Get the size (dimension) of the image by utilizing `identify`.
+ """
+ results = subprocess.run(["identify", "-ping", "-format", "%w %h", image],
+ check=True, stdout=subprocess.PIPE)
+ width, height = map(int, results.stdout.decode("utf-8").split())
+ return (width, height)
+
+
+def montage_images(infiles, outfile):
+ """
+ Combine the 4 input images to make a montage by utilizing `montage`.
+ """
+ img1, img2, img3, img4 = infiles
+ # `img1` is taken as the reference image (top-left)
+ w_ref, h_ref = get_image_size(img1)
+ w_img2, h_img2 = get_image_size(img2)
+ w_img3, h_img3 = get_image_size(img3)
+ # `img2` is re-sized to have the same height as `img1` (top-right)
+ ratio_img2 = h_ref / h_img2
+ W_img2, H_img2 = int(w_img2*ratio_img2), int(h_img2*ratio_img2)
+ # `img3` is re-sized to match the width of `img1` (bottom-left)
+ ratio_img3 = w_ref / w_img3
+ W_img3, H_img3 = int(w_img3*ratio_img3), int(h_img3*ratio_img3)
+ # `img4` is simply re-sized to fill the bottom-right area
+ W_img4, H_img4 = W_img2, H_img3
+ subprocess.run(args=[
+ "montage", img1,
+ "(", img2, "-resize", "%dx%d" % (W_img2, H_img2), ")",
+ "(", img3, "-resize", "%dx%d" % (W_img3, H_img3), ")",
+ "(", img4, "-resize", "%dx%d" % (W_img4, H_img4), ")",
+ "-geometry", "+1+1", "-tile", "2x2", outfile,
+ ])
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Make a montage of the input 4 images")
+ parser.add_argument("-o", "--outfile", dest="outfile", required=True,
+ help="output filename of the montage image")
+ parser.add_argument("images", nargs=4,
+ help="filenames of 4 input images")
+ args = parser.parse_args()
+
+ montage_images(infiles=args.images, outfile=args.outfile)
+
+
+if __name__ == "__main__":
+ main()