FLOSS Manuals

 English |  Español |  Français |  Italiano |  Português |  Русский |  Shqip

Python Scripting with Scribus

scribalbum.py

This in its original state was one of the first major scripts I wrote. As I look back in my old files, I see that it began February 13, 2005 (I guess that wasn't a Friday). What I wanted to be able to do was to simply point my computer at a directory of images, and have the script then load all the images into a document or album. I made versions for putting four on a page, 6 on a page, and eventually allowed the user to choose which. For my own purposes, I would tend to use this after I had been on some trip, accumulated a number of images to be able to review without the use of a computer, and also put some notes beside certain pictures when desired. Sometimes there are some particulars about the image that you soon or eventually forget that you wish you hadn't. Four pictures on US Letter paper leaves a lot more space for these notes, but sometimes the images themselves are the whole story more or less.

I also made versions for A4 paper, but here I'll show the US letter version. The main difference has to do with the placement of the image frames, which is hardcoded into the scripts.

#!/usr/bin/env python

# File: scribalbum.py
# This version for US Letter paper
# Puts 4 or 6 pictures per page
# This version uses fileDialog to choose the directory
# Value dialog to choose file type(s)
# Filters out files ending with .jpg, .png, .tif, .gif, .pdf, and
# uppercase equivalents.
# Makes a new document, and will not fault if you already have one.

import scribus
import os

filetype = []
dicttype = {'j':'.jpg','p':'.png','t':'.tif','g':'.gif','P':'.pdf'}
Dicttype = {'j':'.JPG','p':'.PNG','t':'.TIF','g':'.GIF','P':'.PDF'}
nrimages = '0'
while ((nrimages != '4') and (nrimages != '6')):
    nrimages = scribus.valueDialog('Pictures','- US Letter Paper -\n Images per Page?\nOnly valid entries are 4 or 6','4')
nrimages = int(nrimages)

imagedir = scribus.fileDialog('Select Image Directory','Directories', isdir=True)
imagetype = scribus.valueDialog('Image Types','Enter the Image Types, where\n j=jpg,p=png,t=tif,g=gif,P=pdf\n "jptgP" selects all','jptgP')
for t in imagetype[0:]:
    filetype.append(dicttype[t])
    filetype.append(Dicttype[t])
d = os.listdir(imagedir)
D = []
for file in d:
    for format in filetype:
        if file.endswith(format):
            D.append(file)
D.sort()

# When 4 pics per page, coords are: (15, 42),(310, 187), (15, 388), (310, 533)
# When 6 pics per page: (15, 42),(310, 42), (15, 290), (310, 290),(15,533),(310,533)
if nrimages == 4:
    xpos = [15, 310, 15, 310]    
    ypos = [42, 187, 388, 533]
if nrimages == 6:
    xpos = [15, 310, 15, 310, 15, 310]
    ypos = [42, 42, 290, 290, 533, 533]
# This proportion is right for photographs (at least for my digital Nikon)
pwidth = 288
pheight = 193.33
imagecount = 0
if len(D) > 0:
    if scribus.newDocument(scribus.PAPER_LETTER, (10,10,20,20),scribus.PORTRAIT, 1, scribus.UNIT_POINTS, scribus.NOFACINGPAGES, scribus.FIRSTPAGERIGHT,1):
        while imagecount < len(D):
            if imagecount > 0:
                scribus.newPage(-1)
                framecount = 0
# L is the frame at the top of each page showing the directory name
            L = scribus.createText(15, 20, 300, 20)
            scribus.setText("Dir: " + imagedir, L)
            scribus.setTextAlignment(scribus.ALIGN_LEFT, L)
            scribus.setFont("DejaVu Sans Book", L)
            scribus.setFontSize(10, L)
# Here is where we're loading images into the page, four or six at a time, then go back up for a newPage
            for x,y in zip(xpos,ypos):
                if imagecount < len(D):
                    f = scribus.createImage(x, y, pwidth, pheight)
                    scribus.loadImage(imagedir + '/' + D[imagecount], f)
                    scribus.setScaleImageToFrame(scaletoframe=1, proportional=1, name=f)
                    lenfilename = len(D[imagecount])
                    Lpiclen = int(5.3 * lenfilename)
# Lpic is the label for each picture, with position and length adjusted
# according to the text length, so if you change the font or its size,
# you may need to adjust this only approximate calculation.
                    Lpic = scribus.createText(x, y + 195, Lpiclen, 15)
                    scribus.setText(D[imagecount], Lpic)
                    scribus.setTextAlignment(scribus.ALIGN_RIGHT, Lpic)
                    scribus.setFont("DejaVu Sans Book", Lpic)
                    scribus.setFontSize(8, Lpic)
                    scribus.setFillColor("White", Lpic)
                    imagecount += 1
                
    scribus.setRedraw(1)
    scribus.redrawAll()

else:
    result = scribus.messageBox ('Not Found','No Images found with\n this search selection',scribus.BUTTON_OK)

When I was first using this script on a directory with a large number of images, it was quite a strain on resources when you were creating a 20 or 30 page or more album. Since then Scribus uses image caching, which helps, but of course I have a computer with more memory as well.

At the beginning of the script I create a couple of Python dictionaries, dicttype{} and Dicttype{}. Later on, these allow for using the initial letter to choose a file extension, for example j for .jpg or .JPG. This minimizes the amount of typing in the valueDialog(). The default is all image types, including PDFs (if you import a PDF into an image frame, you will only get the first page).

Now look at this sequence:

nrimages = '0'
while ((nrimages != '4') and (nrimages != '6')):
    nrimages = scribus.valueDialog('Pictures','- US Letter Paper -\n Images per Page?\nOnly valid entries are 4 or 6','4')
nrimages = int(nrimages)

After initializing nrimages with '0', I then use a while loop to only allow the user to enter 4 or 6 for the number of images per page. If something else is entered, the valueDialog() appears again with its default value. Another lesson here is that the input from a valueDialog() is always a string, so you must convert if you're going to use it as an integer.

The next task is for the user to choose a directory, presumably containing images, with a fileDialog() – notice that the last element in the command, isdir=True makes sure that only directories are shown in the dialog. After the user indicates any particular filetypes to include, a list is created which contains only those extensions.

After that, we can now open the directory, and as we read it, we only append to our image list D a filename if it fits our selected extension list. The script then sorts this list alphabetically – this is a line you might want to comment out (with a # at the beginning of it).

Depending on which layout has been chosen, two lists, xpos[] and ypos[] are created for positioning the images. With some experimentation, I decided on these hardcoded values for pwidth and pheight, which are used to create the image frames. Occasionally I may have an image I have taken sideways, but adjusting those frames is something to be done after the script runs.

Finally, we're ready to actually make the document with the newDoc() command, with the first step on each page being to create a text frame L in the upper left corner which will show the directory the images came from.

Until I reviewed this script, I had forgotten about the zip command. This explains the odd look the the xpos and ypos lists. zip presents a series of tuples, xpos[0], ypos[0], then xpos[1], ypos[1] and so on, and thus we march down the page with our 4 or 6 images per page. After each image is placed into its frame, we then create a text frame underneath showing the image filename. After each image, we check with our while command whether we have exhausted the image file list. If we have exhausted what zip can do for one page, we create a new page with newPage(-1), and begin the zip process again.

At the very bottom of the script you see how we have allowed for the user to have chosen a directory containing no images. It may be difficult to see (you have to disregard all the comment lines), but this else clause lines up with if len(D) >0, so it's the alternative when the list D has no elements.

There has been error in communication with Booktype server. Not sure right now where is the problem.

You should refresh this page.