Automatic import of images: Multiple image directories

As an amateur photographer, I take a lot of pictures and in general I post them to a web site with one or more galleries being generated most days. For general purposes, that's enough. Occasionally, however, I've found it useful to have a printed version of my images, to be used more as like the contact sheet of old than as publication quality images. I'd like these documents to have small versions of all the images in each gallery, labeled with the file name and an option title that identified the subject of the photograph. Since the display of images on the web site is driven by text files with file names, titles, and descriptions, I it made sense to reuse that text file for labeling the pictures on the contact sheets.

Starting with the script found on the page Automatic import of images: Versions not requiring Tkinter, 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 27 and 31. The file that I use to list the images is index.txt but this file name may also be changed on line 42. Finally, the font to use is set on line 45. While there are many other settings that may be adjusted, the script should work well enough with just those four items set. 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, open the index.txt file, and generate a document with the images listed 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 31. 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 couple dozen 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.

For publication to my web site I use a script that creates thumbnail, small, and large versions of each photo. Since the small size images are 467 by 700 pixels, I use those when generating contact sheets with this script. That works quite well and I've created documents with 1,500 images without any problem. Note that images are the same size whether they are vertical or horizontal. Even with this precaution, 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.


 * 1) !/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 DATE: December 2, 2010 (original version) MODIFICATIONS: June 28, 2011 - Added support for reading file information from index.txt

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

You will probably need to edit the following:

""" sourceDirectory = "C:/temp/photo/"
 * 1) The directory that contains images or subdirectories with images.
 * 2) All subdirectories under this location will be used to create
 * 3) separate output files

outputDirectory = "C:/temp/photo/"
 * 1) The directory, which should already exist, where you want your output files
 * 2) to be written

sourceFileList = 'index.txt'
 * 1) The name of a file that contains one line per image. Each line should consist of
 * 2) a tab delimited string with the following file information:
 * 3)   0 - count       -- Actually, anything can be here except a blank space or a hash
 * 4)                      mark (#), which will cause the line to be ignored.
 * 5)   1 - file name   -- The name of the file without the .jpg extension
 * 6)   2 - image title -- The title to use in labeling the file (optional)
 * 7)   3 - description -- A longer description (optional) (currently not used)
 * 1)   3 - description -- A longer description (optional) (currently not used)

labelFont = 'Garamond Regular'
 * 1) The font to use for documents


 * 1) While you might want to edit setting below here, you
 * 2) shouldn't need to in order to run the script
 * 1) shouldn't need to in order to run the script

import scribus import os


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

firstPageNumber = '1'

marginX  = 36 marginY  = 36

iHorW  = 152 iVerW  = 101 iVerH = iHorW iHorH = iVerW
 * 1) Image height and width

gapW     = 24 gapH     = 21 xOffset  = 36 yOffset  = 24
 * 1) Gap sizes and page offsets

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

labelGap = 0 labelFS  = 6 labelH   = labelFS * 4
 * 1) Image label text frame
 * 2) Height is enough to allow a second line of text if desired.

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

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

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 = ""
 * 1) It's quite likely that these longs lists could be replaced by a formula.
 * 2) If anyone has the time to do that, it would probably make this script easier
 * 3) to maintain. Still, this works.

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


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

for imagedir in DIR: # Open the index.txt file f = open(sourceDirectory+imagedir+'/'+sourceFileList, 'r') D = [] D = f.readlines 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): if not D[imageCount].startswith("#") and not D[imageCount].startswith(" "): Img = [] Img = D[imageCount].split("\t") scribus.statusMessage("Placing image " + Img[1] + " 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 + '/' + Img[1]+'.jpg', 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 + '/' + Img[1]+'.jpg', 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 a text frame for the picture caption Lpic = scribus.createText(xPosH[i] + pOffset - int(gapW/2)-1, yPosV[i] + iVerH + labelGap, iHorW + gapW-2, labelH) # populate with the file name and title (Img[2]) if len(Img[2]) > 0: scribus.setText('File: '+Img[1]+', '+Img[2], Lpic) else: scribus.setText('File: '+Img[1], Lpic) # and format as desired scribus.setTextAlignment(scribus.ALIGN_CENTERED, Lpic) scribus.setFont(labelFont, Lpic) scribus.setFontSize(labelFS, Lpic) scribus.setLineSpacing(labelFS, Lpic) #scribus.setFillColor("White", Lpic) # End of If/Then -- startswith # 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+".sla") #result = scribus.messageBox("Save", "Saving SLA File as: "+outputDirectory+imagedir+".sla") scribus.saveDocAs(outputDirectory+imagedir+".sla") scribus.statusMessage("Saving PDF File as "+outputDirectory+imagedir+".pdf") 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