Making a photobook from a directory of images using a script: Difference between revisions

From Scribus Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 4: Line 4:


It's intended to produce a book in the same format as Adobe Photoshop Album: US Letter, landscape orientation.
It's intended to produce a book in the same format as Adobe Photoshop Album: US Letter, landscape orientation.
Caveat: I learned Python for the sole purpose of writing this script. It's a little rough in places.


== Usage ==
== Usage ==
Line 258: Line 260:
pb_create_album()
pb_create_album()


</nowiki</pre>
</nowiki></pre>
== pb_flip_h.py ==
<pre><nowiki>
#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_flip_h.py
# Created: 25th May 2007 by Chris Crouch
 
# flip the images on the current page horizontally
 
import photobook_layout
try:
from scribus import *
except ImportError:
print "This script only runs from within Scribus."
sys.exit(1)
 
######
def pb_flip_h():
# flip the images on the current page horizontally
deselectAll()
page_margins = photobook_layout.get_page_margins()
page_width = photobook_layout.page_size[0] - page_margins[0] - page_margins[2]
page_height = photobook_layout.page_size[1] - page_margins[1] - page_margins[3]
objs = photobook_layout.get_images_on_page()
for obj in objs:
obj_size = getSize(obj)
obj_pos = getPosition(obj)
obj_h_mid = obj_pos[0] + obj_size[0]/2
new_h_mid = page_width - (obj_h_mid - page_margins[0]) + page_margins[0]
selectObject(obj)
moveObjectAbs(new_h_mid - obj_size[0]/2, obj_pos[1], obj)
deselectAll()
docChanged(True)
 
######
if __name__ == '__main__':
pb_flip_h()
</nowiki></pre>
== pb_flip_v.py ==
<pre><nowiki>
#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_flip_v.py
# Created: 25th May 2007 by Chris Crouch
 
import photobook_layout
try:
from scribus import *
except ImportError:
print "This script only runs from within Scribus."
sys.exit(1)
 
######
def pb_flip_v():
# flip the images on the current vertically
deselectAll()
page_margins = get_page_margins()
page_width = page_size[0] - page_margins[0] - page_margins[2]
page_height = page_size[1] - page_margins[1] - page_margins[3]
objs = get_images_on_page()
for obj in objs:
obj_size = getSize(obj)
obj_pos = getPosition(obj)
obj_v_mid = obj_pos[1] + obj_size[1]/2
new_v_mid = page_height - (obj_v_mid - page_margins[1]) + page_margins[1]
selectObject(obj)
moveObjectAbs(obj_pos[0], new_v_mid - obj_size[1]/2, obj)
deselectAll()
docChanged(True)
 
 
######
if __name__ == '__main__':
photobook_layout.pb_flip_v()
</nowiki></pre>
== pb_layout_current.py ==
<pre><nowiki>
#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_layout_current.py
# Created: 25th May 2007 by Chris Crouch
 
import photobook_layout
 
######
if __name__ == '__main__':
photobook_layout.pb_layout_page()
</nowiki></pre>
== pb_layout_from_current.py ==
<pre><nowiki>
#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_layout_from_current.py
# Created: 25th May 2007 by Chris Crouch
 
import photobook_layout
 
######
if __name__ == '__main__':
photobook_layout.pb_layout_all_pages()
</nowiki></pre>

Revision as of 03:50, 26 May 2007

This article is part of the Scripts series.

This is yet another script to layout photos in a book. It differs from Automatic import of images: Versions not requiring Tkinter and Automatic import of images from a directory using a script in that it is not meant to be fuly automatic, and it allows for a variable number of images per page in mixtures of landscape and portrait orientation.

It's intended to produce a book in the same format as Adobe Photoshop Album: US Letter, landscape orientation.

Caveat: I learned Python for the sole purpose of writing this script. It's a little rough in places.

Usage

Running photobook_layout.py without an open document will bring up a dialog to select a directory. The script will then add all JPEG files (*.jpg) to a new document, 3 to a page. It will then go through each page, re-orienting and resizing the photos to nicely fit the page.

You can then re-arrange the photos, dragging them from page to page to get a nice layout. Re-running the photobook_layout.py script will go through all of the pages, re-laying them out.

The script can handle 1-4 photos per page, in any combination of portrait and landscape.

There are some auxilliary scripts. pb_layout_current.py will lay out only the current page. pb_layout_from_current.py will lay out all pages from the current one to the end of the document. pb_flip_h.py and pb_flip_v.py will flip arrangement of images on the current page.

photobook_layout.py

#!/usr/bin/env python
# -*- coding: ascii -*-
# File: photobook_layout.py
# Created: 25th May 2007 by Chris Crouch

# This script will create a photobook. It can both create a photobook from a folder full of images,
# and lay images out on the pages in a nice way. You can move the images from page to page, and have
# the script re-layout them for you. It lays out landscape and portrait images neatly.

# Requires the Python Image Library from http://www.pythonware.com/products/pil/ (to work out image orientation)
# Developed on a Windows machine running Scribus 1.3.3.9

# This is designed for Letter pages in Landscape orientation, with images that are 3:2 aspect ratio (DSLR)
# To change these, change the constants at the top for the paper size, then you'll need to just fiddle
# with the size & positions in pb_layout_page() so that (a) the image frames are the correct aspect ratio,
# and (b) the sizes and positions look good on the page. Trial and error is how I got these.

# There are some auxilliary scripts that just allow you to directly invoke some of the functions in this script.

import glob
try:
	import Image
except ImportError:
	print "This script requires the Python Image Library"
	sys.exit(1)
try:
	from scribus import *
except ImportError:
	print "This script only runs from within Scribus."
	sys.exit(1)

###### Constants
page_size = (279.4, 215.9) #Letter, mm
page_margins_left = (5, 5, 20, 5) #mm
page_margins_right = (20, 5, 5, 5) #mm
page_margins_points = (56.69, 14.17, 14.17, 14.17) #margins_right as points

######
def cmpObj(obj1, obj2):
	# compare 2 image objects to sort by horizontal loc
	# (if ==, the vert. pos; then by name
	pos1 = getPosition(obj1)
	pos2 = getPosition(obj2)
	if pos1[0] > pos2[0]:
		return 1
	if pos1[0] < pos2[0]:
		return -1
	if pos1[1] > pos2[1]:
		return 1
	if pos1[1] < pos2[1]:
		return -1
	return obj1 > obj2

######
def get_page_margins():
	if (currentPage() % 2) == 1:
		return page_margins_right;
	else:
		return page_margins_left;
	

######
def placeobj(obj_size, x_place, y_place, obj):
	# move obj to specified position and specified size
	# obj_size - (w, h)
	# x_place, y_place: 0.0 - 1.0 normalized
	page_margins = get_page_margins()
	page_width = page_size[0] - page_margins[0] - page_margins[2]
	page_height = page_size[1] - page_margins[1] - page_margins[3]
	xpos = (page_width * x_place) + page_margins[0] - obj_size[0]/2
	ypos = (page_height * y_place) + page_margins[1] - obj_size[1]/2
	selectObject(obj)
	sizeObject(obj_size[0], obj_size[1], obj)
	moveObjectAbs(xpos, ypos, obj)
	deselectAll()
	return


######
def get_images_on_page():
	# returns a list of the image objects on the current page
	# get all the items on the page
	item_list = getPageItems()
	# refine it to a list of only image objects
	objs = [];
	for item in item_list:
		if item[1] == 2: #type 2 == image
			objs.append(item[0])
	return objs


######
def pb_layout_page():
	# Nicely layout all of the images on the current page
	deselectAll()
	# get all of the images on this page and sort them by position
	objs = get_images_on_page()
	if len(objs) == 0:
		return
	objs.sort(cmpObj)
	# refine it to lists of landscape & portrait images
	port = []
	land = []
	for obj in objs:
		file = getImageFile(obj)
		im = Image.open(file)
		sz = im.size
		if sz[0] > sz[1]:
			land.append(obj)
		else:
			port.append(obj)
	np = len(port) # number of portrait images
	nl = len(land) # number of landscape images
	# layouts for different numbers of portrait and landscape images
	if np==0 and nl==1:
		placeobj((240, 160), 0.5, 0.5, land[0])
	elif np==0 and nl==2:
		placeobj((150, 100), 0.4, 0.25, land[0])
		placeobj((150, 100), 0.6, 0.75, land[1])
	elif np==0 and nl==3:
		placeobj((120, 80), 0.25, 0.21, land[0])
		placeobj((165, 110), 0.5, 0.7, land[1])
		placeobj((120, 80), 0.75, 0.21, land[2])
	elif np==0 and nl==4:
		placeobj((120, 80), 0.25, 0.25, land[0])
		placeobj((120, 80), 0.75, 0.25, land[1])
		placeobj((120, 80), 0.25, 0.75, land[2])
		placeobj((120, 80), 0.75, 0.75, land[3])
	elif np==1 and nl==0:
		placeobj((144, 216), 0.74, 0.5, port[0])
	elif np==1 and nl==1:
		placeobj((90, 135), 0.205, 0.5, port[0])
		placeobj((150, 100), 0.7, 0.5, land[0])
	elif np==1 and nl==2:
		placeobj((120, 180), 0.25, 0.5, port[0])
		placeobj((120, 80), 0.75, 0.27, land[0])
		placeobj((120, 80), 0.75, 0.73, land[1])
	elif np==1 and nl==3:
		placeobj((130, 195), 0.27, 0.5, port[0])
		placeobj((90, 60), 0.75, 0.18, land[0])
		placeobj((90, 60), 0.75, 0.5, land[1])
		placeobj((90, 60), 0.75, 0.82, land[2])
	elif np==2 and nl==0:
		placeobj((120, 180), 0.25, 0.5, port[0])
		placeobj((120, 180), 0.75, 0.5, port[1])
	elif np==2 and nl==1:
		placeobj((60, 90), 0.14, 0.25, port[0])
		placeobj((60, 90), 0.14, 0.75, port[1])
		placeobj((180, 120), 0.63, 0.5, land[0])
	elif np==2 and nl==2:
		placeobj((70, 105), 0.22, 0.27, port[0])
		placeobj((70, 105), 0.78, 0.73, port[1])
		placeobj((135, 90), 0.65, 0.24, land[0])
		placeobj((135, 90), 0.35, 0.76, land[1])
	elif np==3 and nl==0:
		placeobj((80, 120), 0.17, 0.5, port[0])
		placeobj((80, 120), 0.5, 0.5, port[1])
		placeobj((80, 120), 0.83, 0.5, port[2])
	elif np==3 and nl==1:
		placeobj((120, 180), 0.25, 0.5, port[0])
		placeobj((60, 90), 0.62, 0.72, port[1])
		placeobj((60, 90), 0.87, 0.72, port[2])
		placeobj((120, 80), 0.745, 0.26, land[0])
	elif np==4 and nl==0:
		placeobj((90, 135), 0.19, 0.5, port[0])
		placeobj((60, 90), 0.5, 0.25, port[1])
		placeobj((60, 90), 0.5, 0.75, port[2])
		placeobj((90, 135), 0.81, 0.5, port[3])
	docChanged(True)
	deselectAll()
	return


######
def pb_layout_all_pages():
	# re-layout all pages from the current page to the end of the document
	progressReset()
	progressTotal(pageCount()+1)
	messagebarText("Arranging pictures");
	for i in range(currentPage(), pageCount()+1):
		gotoPage(i)
		progressSet(i)
		messagebarText("Page "+str(i))
		pb_layout_page()
	progressReset()
	messagebarText("");


######
def pb_create_album():
	# Prompt the user for a directory to process.
	# Create a new document with all jpg files from the selected directory added as images
	# to the document, 3 to the page.
	# When finished, process the document to layout the images in a "nice" manner
	dirname = fileDialog("Select Directory","","",False,False,True)
	files = glob.glob(dirname + "*.jpg")
	if len(files) == 0:
		return
	# it seems that you _have_ to specify page margins in points
	newDocument(PAPER_LETTER, page_margins_points, LANDSCAPE, 1, UNIT_POINTS, PAGE_2, FACINGPAGES, FIRSTPAGERIGHT)
	zoomDocument(50)
	setUnit(UNIT_MILLIMETERS)
	setMargins(page_margins_right[0], page_margins_right[1], page_margins_right[2], page_margins_right[3])
	progressReset()
	progressTotal(len(files))
	messagebarText("Creating pages...");
	progress = 0;
	num_on_page = 0;
	for file in files:
		messagebarText("Adding "+file)
		progressSet(progress)
		progress = progress + 1
		num_on_page = num_on_page + 1
		if num_on_page == 4:
			newPage(-1)
			num_on_page = 1
		im = Image.open(file)
		sz = im.size
		if sz[0] > sz[1]:
			f = createImage(num_on_page*90-80, 60, 90, 60)
		else:
			f = createImage(num_on_page*90-80, 10, 80, 120)
		loadImage(file, f)
		setScaleImageToFrame(scaletoframe=1, proportional=1, name=f)
	progressReset()
	messagebarText("");
	deselectAll()
	# now layout the pages nicely
	gotoPage(1)
	pb_layout_all_pages()
	deselectAll()

######
if __name__ == '__main__':
	# either create a new album document, or re-layout the entire existing document
	if haveDoc():
		gotoPage(1)
		pb_layout_all_pages()
	else:
		pb_create_album()

pb_flip_h.py

#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_flip_h.py
# Created: 25th May 2007 by Chris Crouch

# flip the images on the current page horizontally

import photobook_layout
try:
	from scribus import *
except ImportError:
	print "This script only runs from within Scribus."
	sys.exit(1)

######
def pb_flip_h():
	# flip the images on the current page horizontally
	deselectAll()
	page_margins = photobook_layout.get_page_margins()
	page_width = photobook_layout.page_size[0] - page_margins[0] - page_margins[2]
	page_height = photobook_layout.page_size[1] - page_margins[1] - page_margins[3]
	objs = photobook_layout.get_images_on_page()
	for obj in objs:
		obj_size = getSize(obj)
		obj_pos = getPosition(obj)
		obj_h_mid = obj_pos[0] + obj_size[0]/2
		new_h_mid = page_width - (obj_h_mid - page_margins[0]) + page_margins[0]
		selectObject(obj)
		moveObjectAbs(new_h_mid - obj_size[0]/2, obj_pos[1], obj)
		deselectAll()
	docChanged(True)

######
if __name__ == '__main__':
	pb_flip_h()

pb_flip_v.py

#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_flip_v.py
# Created: 25th May 2007 by Chris Crouch

import photobook_layout
try:
	from scribus import *
except ImportError:
	print "This script only runs from within Scribus."
	sys.exit(1)

######
def pb_flip_v():
	# flip the images on the current vertically
	deselectAll()
	page_margins = get_page_margins()
	page_width = page_size[0] - page_margins[0] - page_margins[2]
	page_height = page_size[1] - page_margins[1] - page_margins[3]
	objs = get_images_on_page()
	for obj in objs:
		obj_size = getSize(obj)
		obj_pos = getPosition(obj)
		obj_v_mid = obj_pos[1] + obj_size[1]/2
		new_v_mid = page_height - (obj_v_mid - page_margins[1]) + page_margins[1]
		selectObject(obj)
		moveObjectAbs(obj_pos[0], new_v_mid - obj_size[1]/2, obj)
		deselectAll()
	docChanged(True)


######
if __name__ == '__main__':
	photobook_layout.pb_flip_v()

pb_layout_current.py

#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_layout_current.py
# Created: 25th May 2007 by Chris Crouch

import photobook_layout

######
if __name__ == '__main__':
	photobook_layout.pb_layout_page()

pb_layout_from_current.py

#!/usr/bin/env python
# -*- coding: ascii -*-
# File: pb_layout_from_current.py
# Created: 25th May 2007 by Chris Crouch

import photobook_layout

######
if __name__ == '__main__':
	photobook_layout.pb_layout_all_pages()