Image Wizard: Scale and Align an Image
You may have seen these scripts that Scale an Image to Fill a Frame Proportionally and Align an Image in its Frame. The following script brings up a dialog that allows you to perform both functions, as well as two other scaling functions.
- Scale to Fill Frame (proportional scaling with cropping)
- Scale to Fit Frame (standard Scribus "Scale to Frame Size: Proportional" - no cropping)
- Scale Image to: x % (proportional scaling by the given percentage)
- Align (9 possible alignments)
Each button click performs a separate action on all the currently selected images. So if you need to scale the image and then align it, you should first click the scaling button, then select your alignment and press the Align button.
I hope you'll find this script useful. This script has been immensely helpful to me in laying out the pictures for a photo album. More functions may be forthcoming if I find some that are useful. Maybe this additional alignment and scaling functionality could be incorporated into Scribus at some point.
The script has been tested in Scribus 1.3.3.9 and 1.3.4. It requires Tkinter to be properly installed.
"Warning: You can leave the script dialog open, and continue to scale and align more images that you select. However, due to a multi-threading bug with Python scripts in Scribus, if you attempt to launch another script while this one is running, Scribus will probably crash and you'll lose your document. So be careful, and save often! Also, when the script is running, it may interfere with other Scribus actions such as using the Properties toolbar."""
Save this script with a filename of Image_Wizard.py, for example.
from scribus import * try: # I wish PyQt installed everywhere :-/ from Tkinter import * from tkFont import Font except ImportError: print "This script requires Python's Tkinter properly installed." messageBox('Script failed', 'This script requires Python\'s Tkinter properly installed.', ICON_CRITICAL) sys.exit(1) class TkImageAlignmentWizard(Frame): """ GUI interface for aligning an image in a frame""" def __init__(self, master=None): """ Setup the dialog """ # refernce to the localization dictionary self.key = 'English' Frame.__init__(self, master) self.master.resizable(0, 0) self.master.title('Image Wizard') #define widgets #define framed areas self.grid() self.align_frame = Frame(self, bd=1, relief=RIDGE) self.scale_frame = Frame(self, bd=1, relief=RIDGE) # alignment options self.alignLabel = Label(self.align_frame, text='Align Image') self.alignVar = StringVar() self.alignRadio1 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="TL") self.alignRadio2 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="TC") self.alignRadio3 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="TR") self.alignRadio4 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="ML") self.alignRadio5 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="MC") self.alignRadio6 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="MR") self.alignRadio7 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="BL") self.alignRadio8 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="BC") self.alignRadio9 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="BR") self.alignButton = Button(self.align_frame, text='Align', command=self.alignImage) # scaling options self.scaleLabel = Label(self.scale_frame, text='Scale Image:') self.scaleToFillButton = Button(self.scale_frame, text='Scale to Fill Frame', command=self.scaleImageToFill) self.scaleToFitButton = Button(self.scale_frame, text='Scale to Fit Frame', command=self.scaleImageToFit) self.scalePercentVar = StringVar() self.scalePercentLabel1 = Label(self.scale_frame, text='Scale Image to:') self.scalePercentLabel2 = Label(self.scale_frame, text='%') self.scalePercentEntry = Entry(self.scale_frame, textvariable=self.scalePercentVar, width=8) self.scalePercentButton = Button(self.scale_frame, text='Scale', command=self.scaleImageToPercent) # closing/running self.doneButton = Button(self, text="Done", command=self.quit) #status label self.statusVar = StringVar() self.statusLabel = Label(self, textvariable=self.statusVar) self.statusVar.set('Status:') # setup values self.alignRadio5.select() # make align layout currRow = 0 self.alignLabel.grid(column=0, row=currRow, columnspan=3) currRow += 1 self.alignRadio1.grid(column=0, row=currRow) self.alignRadio2.grid(column=1, row=currRow) self.alignRadio3.grid(column=2, row=currRow) currRow += 1 self.alignRadio4.grid(column=0, row=currRow) self.alignRadio5.grid(column=1, row=currRow) self.alignRadio6.grid(column=2, row=currRow) currRow += 1 self.alignRadio7.grid(column=0, row=currRow) self.alignRadio8.grid(column=1, row=currRow) self.alignRadio9.grid(column=2, row=currRow) currRow += 1 self.alignButton.grid(column=0, row=currRow, columnspan=3) self.doneButton.grid(column=3, row=currRow, columnspan=3) #make scale layout currRow = 0 self.scaleLabel.grid(column=0, row=currRow, columnspan=3) currRow += 1 self.scaleToFillButton.grid(column=0, row=currRow, columnspan=3) currRow += 1 self.scaleToFitButton.grid(column=0, row=currRow, columnspan=3) currRow += 1 self.scalePercentLabel1.grid(column=0, row=currRow, columnspan=3, sticky=W) currRow += 1 self.scalePercentEntry.grid(column=0, row=currRow) self.scalePercentLabel2.grid(column=1, row=currRow) self.scalePercentButton.grid(column=2, row=currRow) #make overall layout self.grid() self.align_frame.grid(row=0, column=0, sticky=N) self.scale_frame.grid(row=0, column=1, sticky=N) self.doneButton.grid(row=1, column=0, columnspan=2) #self.statusLabel.grid(row=2, column=0, columnspan=2, stick=W) def alignImage(self): if haveDoc(): nbrSelected = selectionCount() objList = [] for i in range(nbrSelected): objList.append(getSelectedObject(i)) for i in range(nbrSelected): try: obj = objList[i] frameW = getProperty(obj, "width") frameH = getProperty(obj, "height") saveScaleX = getProperty(obj, "imageXScale") saveScaleY = getProperty(obj, "imageYScale") setScaleImageToFrame(True, False, obj) fullScaleX = getProperty(obj, "imageXScale") fullScaleY = getProperty(obj, "imageYScale") setScaleImageToFrame(False, False, obj) scaleImage(saveScaleX, saveScaleY, obj) imageW = frameW * (saveScaleX / fullScaleX) imageH = frameH * (saveScaleY / fullScaleY) imageX = 0.0 imageY = 0.0 if self.alignVar.get()[0] == "T": imageY = 0.0 elif self.alignVar.get()[0] == "M": imageY = (frameH - imageH) / 2.0 / saveScaleY elif self.alignVar.get()[0] == "B": imageY = (frameH - imageH) / saveScaleY if self.alignVar.get()[1] == "L": imageX = 0.0 elif self.alignVar.get()[1] == "C": imageX = (frameW - imageW) / 2.0 / saveScaleX elif self.alignVar.get()[1] == "R": imageX = (frameW - imageW) / saveScaleX setProperty(obj, "imageXOffset", imageX) setProperty(obj, "imageYOffset", imageY) docChanged(1) setRedraw(True) except: nothing = "nothing" def scaleImageToFill(self): if haveDoc(): nbrSelected = selectionCount() objList = [] for i in range(nbrSelected): objList.append(getSelectedObject(i)) for i in range(nbrSelected): try: obj = objList[i] setScaleImageToFrame(True, False, obj) scaleX, scaleY = getImageScale(obj) setScaleImageToFrame(False, False, obj) if scaleX > scaleY: scale = scaleX scaleImage(scale, scale, obj) elif scaleY > scaleX: scale = scaleY scaleImage(scale, scale, obj) docChanged(1) setRedraw(True) except: nothing = "nothing" def scaleImageToFit(self): if haveDoc(): nbrSelected = selectionCount() objList = [] for i in range(nbrSelected): objList.append(getSelectedObject(i)) for i in range(nbrSelected): try: obj = objList[i] setScaleImageToFrame(True, True, obj) docChanged(1) setRedraw(True) except: nothing = "nothing" def scaleImageToPercent(self): if haveDoc(): nbrSelected = selectionCount() objList = [] for i in range(nbrSelected): objList.append(getSelectedObject(i)) for i in range(nbrSelected): try: tempScale = float(self.scalePercentVar.get()) tempScale = tempScale / 100.0 obj = objList[i] scaleImage(tempScale, tempScale, obj) setRedraw(True) docChanged(1) except: nothing = "nothing" def quit(self): self.master.destroy() def main(): """ Application/Dialog loop with Scribus sauce around """ try: root = Tk() app = TkImageAlignmentWizard(root) root.mainloop() finally: if haveDoc(): redrawAll() if __name__ == '__main__': main()