Automatic import of images: Multiple image directories

From Scribus Wiki
Revision as of 21:13, 2 December 2010 by Hhartley (talk | contribs) (Add crash notice info)
Jump to navigation Jump to search

Starting with the script found on the page Automatic import of images: Versions not requiring Tkinter#album_letter_2.py, I have created a new script that will take a collection of image directories and create 12-images-per-page documents from each of them in turn, save the documents and generate PDF files from each.

The initial input and output directories are specified in the code and will need to be changed based on your own configuration. They are defined on lines 21 and 22. There are many other settings that may be adjusted but this should work well enough as a starting point. Note that the script will not create the output directory so you'll need to make sure it exists before you start.

The basic idea here is to go through the source directory and gather all the sub-directory names. Then, go through each of those sub-directories and generate a document with the images found there, 12 per page. The document places the sub-directory name at the top of each page, arranges the images in four rows of three images with the file names centered under each. Page numbers are added. Since I print these documents double sided, the page numbers move from side to side and the entire page contents are shifted a little to the right (odd numbered pages) or the left (even numbered pages). Each gallery gets its own file.

Once generated, an SLA file is saved in the outputDirectory specified on line 22. Then, a PDF is generated with all pages and saved to the same location. Both files are named the same as the image sub-directory but with .sla and .pdf extensions respectively.

Caution: if you have directories with too many or very large image files, this can take a long while to run. Documents for directories with a dozen or two images of the appropriate size are created, saved, and exported to PDF in a matter of seconds. Documents for directories with images much larger than necessary or with more than a couple hundred images can take many minutes to be created. Since the images are printed at just over 1.4 by 2.1 inches, even at 300 dpi they will only need to be 420 by 633 pixels and you can probably get away with less. I would be cautious running this script on directories with lots of images or those copied directly from your digital camera. I've successfully produced documents with 640 images this way but it took a good while.

When I run this on a large number of directories, I often, eventually, get a Scribus Crash with the message: Scribus crashes due to the following exception : EXCEPTION_ACCESS_VIOLATION. I just close Scribus, move the image directories that have already been processed and start again. If anyone knows what's causing that and can fix it, that would be wonderful.

Considerable credit and thanks to Gregory Pittman, who wrote the original script on which this is based.

#!/usr/bin/env python

"""
This is contact-sheet.py. This script will load the images from any number
of directories, creating a new document of US Letter size from each directory.

AUTHOR: Henry Hartley, December 2, 2010, with thanks to Gregory Pittman

LICENSE: This program is free software; you can redistribute it and/or modify 
it under the terms of the GNU General Public License as published by the Free 
Software Foundation; either version 2 of the License, or (at your option) any 
later version.

http://wiki.scribus.net/index.php/Automatic_import_of_images:_Multiple_image_directories

"""

import scribus
import os

sourceDirectory = "C:/temp/photographs/images/"
outputDirectory = "C:/temp/photographs/contact_sheets/"

filetype = []
dicttype = {'j':'.jpg','p':'.png','t':'.tif','g':'.gif','P':'.pdf'}
Dicttype = {'j':'.JPG','p':'.PNG','t':'.TIF','g':'.GIF','P':'.PDF'}

firstPageNumber = '1'
imagetype = 'jptgP'
labelFont = 'Garamond Regular'

for t in imagetype[0:]:
	filetype.append(dicttype[t])
	filetype.append(Dicttype[t])

# All of these numbers can be adjusted but what is here seems to work pretty well

marginX   = 36
marginY   = 36

# Image height and width
iHorW   = 152
iVerW   = 101
iVerH  = iHorW
iHorH  = iVerW

# Gap sizes and page offsets
gapW      = 24
gapH      = 21
xOffset   = 36
yOffset   = 24

# Page title text frame
titleFS   = 12
titleX    = marginX
titleY    = marginY
titleW    = iHorW + iHorW + gapW + iHorW + gapW
titleH    = titleFS * 2

# Image label text frame
# Height is enough to allow a second line of text if desired.
labelGap  = 0
labelFS   = 7
labelH    = labelFS * 3

# Page number text frame
pNumFS    = 8
pNumY     = 759
pNumXt    = 2
pNumW     = 18
pNumH     = pNumFS * 1.5

H2V = int((iHorW-iHorH)/2)
V2H = int((iVerH-iVerW)/2)

# It's quite likely that these longs lists could be replaced by a formula.
# If anyone has the time to do that, it would probably make this script easier
# to maintain.
xPosH = [marginX, marginX + iHorW + gapW, marginX + (2 * iHorW) + (2 * gapW), marginX, marginX + iHorW + gapW, marginX + (2 * iHorW) + (2 * gapW), marginX, marginX + iHorW + gapW, marginX + (2 * iHorW) + (2 * gapW), marginX, marginX + iHorW + gapW, marginX + (2 * iHorW) + (2 * gapW)]
yPosH = [marginY + yOffset + V2H, marginY + yOffset + V2H, marginY + yOffset + V2H, marginY + yOffset + iVerH + gapH + V2H, marginY + yOffset + iVerH + gapH + V2H, marginY + yOffset + iVerH + gapH + V2H, marginY + yOffset + (2 * iVerH) + (2 * gapH) + V2H, marginY + yOffset + (2 * iVerH) + (2 * gapH) + V2H, marginY + yOffset + (2 * iVerH) + (2 * gapH) + V2H, marginY + yOffset + (3 * iVerH) + (3 * gapH) + V2H, marginY + yOffset + (3 * iVerH) + (3 * gapH) + V2H, marginY + yOffset + (3 * iVerH) + (3 * gapH) + V2H]
xPosV = [marginX + H2V, marginX + iHorW + gapW + H2V, marginX + (2 * iHorW) + (2 * gapW) + H2V, marginX + H2V, marginX + iHorW + gapW + H2V, marginX + (2 * iHorW) + (2 * gapW) + H2V, marginX + H2V, marginX + iHorW + gapW + H2V, marginX + (2 * iHorW) + (2 * gapW) + H2V, marginX + H2V, marginX + iHorW + gapW + H2V, marginX + (2 * iHorW) + (2 * gapW) + H2V]
yPosV = [marginY + yOffset, marginY + yOffset, marginY + yOffset, marginY + yOffset + iVerH + gapH, marginY + yOffset + iVerH + gapH, marginY + yOffset + iVerH + gapH, marginY + yOffset + (2 * iVerH) + (2 * gapH), marginY + yOffset + (2 * iVerH) + (2 * gapH), marginY + yOffset + (2 * iVerH) + (2 * gapH), marginY + yOffset + (3 * iVerH) + (3 * gapH), marginY + yOffset + (3 * iVerH) + (3 * gapH), marginY + yOffset + (3 * iVerH) + (3 * gapH)]
imgID = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
imgRow = 3
imagedir = ""

dirCount = 0
dir = os.listdir(sourceDirectory)
DIR = []
for file in dir:
	#result = scribus.messageBox("Directory", "File: "+file)
	if os.path.isdir(sourceDirectory+file):
		DIR.append(file)
		dirCount += 1
DIR.sort()

#result = scribus.messageBox("Directory Count", "There were "+str(dirCount)+" directories added to the array")

for imagedir in DIR:
	#result = scribus.messageBox("Directory", "The directory about to be processed is: "+imagedir)
	d = os.listdir(sourceDirectory+imagedir)
	D = []
	for file in d:
		for format in filetype:
			if file.endswith(format):
				D.append(file)
	D.sort()
	
	gallerytitle = imagedir
	
	imageCount = 0
	pageNumber = 1
	scribus.progressTotal(len(D))
	if len(D) > 0:
		if scribus.newDoc(scribus.PAPER_LETTER, (marginX, marginX, marginY, marginY),scribus.PORTRAIT, 1, scribus.UNIT_POINTS, scribus.NOFACINGPAGES, scribus.FIRSTPAGERIGHT):
			while imageCount < len(D):
				if imageCount > 0:
					scribus.newPage(-1)
				
				# Here is where we're loading images into the page, four, six, or twelve at a time, then go back up for a newPage
				if pageNumber % 2 == 0:
					pOffset = 0
					pNumX = xPosH[0]
				else:
					pOffset = xOffset
					pNumX = xPosH[pNumXt] + iHorW + pOffset - pNumW
	
				# L is the frame at the top of each page showing the gallery title (read in above)
				L = scribus.createText(titleX + pOffset, titleY, titleW, titleH)
				scribus.setText(gallerytitle, L)
				scribus.setTextAlignment(scribus.ALIGN_CENTERED, L)
				scribus.setFont(labelFont, L)
				scribus.setFontSize(titleFS, L)
				
				for i in imgID:
					if imageCount < len(D):
	
						scribus.statusMessage("Placing image " + D[imageCount] + " in document (" + `imageCount` + " of " + `len(D)` + ")")
						scribus.progressSet(imageCount)
	
						# Create a temporary image object. Size and location are irrelivant
						tempImage = scribus.createImage(10, 10, 10, 10)
	
						# Populate that object with your image
						scribus.loadImage(sourceDirectory+imagedir + '/' + D[imageCount], tempImage)
	
						# Scale the image but NOT proportionally
						scribus.setScaleImageToFrame(scaletoframe=1, proportional=0, name=tempImage)
	
						# Use getImageScale to get the relative scaling in the x and y directions
						imgx,imgy = scribus.getImageScale(tempImage)
	
						# If imgx < imgy, you have an horizontal image, otherwise, 
						# a vertical (or square) image. 
						if imgx < imgy:
							x = xPosH[i] + pOffset
							y = yPosH[i]
							pWidth = iHorW
							pHeight = iHorH
						else:
							x = xPosV[i] + pOffset
							y = yPosV[i]
							pWidth = iVerW
							pHeight = iVerH
	
						# Can't have these cluttering up the page
						scribus.deleteObject(tempImage)
						
						# Now we create the REAL image object placed appropriately
						f = scribus.createImage(x, y, pWidth, pHeight)
						
						# and load the image
						scribus.loadImage(sourceDirectory+imagedir + '/' + D[imageCount], f)
						
						# this time when we scale the image, we do it proportionally
						scribus.setScaleImageToFrame(scaletoframe=1, proportional=1, name=f)
						
						# Lpic is the label for each picture, the position is the same for all 
						#	image orientations and the labels are centered under the pictures.
						
						# Create the text frame.
						Lpic = scribus.createText(xPosH[i] + pOffset, yPosV[i] + iVerH + labelGap, iHorW, labelH)
						
						# populate with the file name
						scribus.setText(D[imageCount], Lpic)
						
						# and format as desired
						scribus.setTextAlignment(scribus.ALIGN_CENTERED, Lpic)
						scribus.setFont(labelFont, Lpic)
						scribus.setFontSize(labelFS, Lpic)
						#scribus.setFillColor("White", Lpic)
						
						# increment the image count
						imageCount += 1
				
				# Now the page number
				
				# Create a text frame
				pNum = scribus.createText(pNumX, pNumY, pNumW, pNumH)
				
				# Put the page number in it and format
				pageNumberPrint = pageNumber + (int(firstPageNumber)-1)
				scribus.setText(`pageNumberPrint`, pNum)
				if imageCount < len(D):
					scribus.setTextAlignment(scribus.ALIGN_RIGHT, pNum)
				else:
					scribus.setTextAlignment(scribus.ALIGN_LEFT, pNum)
				scribus.setFont(labelFont, pNum)
				scribus.setFontSize(pNumFS, pNum)
				#scribus.setFillColor("White", pNum)
				
				# Finally, we increment the page number
				pageNumber += 1
		scribus.setRedraw(1)
		scribus.redrawAll()
	
	else:
		result = scribus.messageBox ('Not Found','No Images found with\n this search selection',scribus.BUTTON_OK)
	
	scribus.setRedraw(1)
	scribus.redrawAll()
	
	scribus.statusMessage("Saving File as "+outputDirectory+imagedir)
	#result = scribus.messageBox("Save", "Saving SLA File as: "+outputDirectory+imagedir+".sla")
	scribus.saveDocAs(outputDirectory+imagedir+".sla")
	
	scribus.statusMessage("Saving PDF File as "+outputDirectory+imagedir)
	pdfExport = scribus.PDFfile()
	pdfExport.info = outputDirectory+imagedir+".pdf"
	pNum = 1
	PDFPages = []
	while pNum < pageNumber:
		PDFPages.append(pNum)
		pNum += 1
	pdfExport.pages = PDFPages
	pdfExport.file = outputDirectory+imagedir+".pdf"
	pdfExport.save()
	
	scribus.closeDoc()
	
	scribus.statusMessage("")
	scribus.progressReset()