Image Wizard: Scale and Align an Image: Difference between revisions

From Scribus Wiki
Jump to navigation Jump to search
(New page: {{Scripting Index}} 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 tha...)
 
(Changed license to GPL2 per cbradney's request)
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{Scripting Index}}
{{Scripting Index}}


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.
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, and flipping and manual alignment functions.


* Scale to Fill Frame (proportional scaling with cropping)
* Scale to Fill Frame (proportional scaling with cropping)
* Scale to Fit Frame (standard Scribus "Scale to Frame Size: Proportional" - no cropping)
* Scale to Fit Frame (standard Scribus "Scale to Frame Size: Proportional" - no cropping)
* Scale Image to: x % (proportional scaling by the given percentage)
* Scale Image to: x % (proportional scaling by the given percentage)
* Align (9 possible alignments)
* Automatic alignment (9 possible alignments)
* Click arrow buttons to align the image in the frame
* Click arrow buttons to align the frame on the canvas
* Flip the image horizontally or vertically


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.
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.
Line 14: Line 17:
The script has been tested in Scribus 1.3.3.9 and 1.3.4. It requires Tkinter to be properly installed.
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."""
'''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.'''
 
Here is a screenshot of the script:
 
[[Image:ImageWizard3.png]]


Save this script with a filename of Image_Wizard.py, for example.
Save this script with a filename of Image_Wizard.py, for example.


<pre><nowiki>
<pre><nowiki>
# License
# Copyright 2007, Jeremy Brown (TrnsltLife)
# This script 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.
from scribus import *
from scribus import *


Line 50: Line 64:
         self.align_frame = Frame(self, bd=1, relief=RIDGE)
         self.align_frame = Frame(self, bd=1, relief=RIDGE)
         self.scale_frame = Frame(self, bd=1, relief=RIDGE)
         self.scale_frame = Frame(self, bd=1, relief=RIDGE)
        self.flip_frame = Frame(self, bd=1, relief=RIDGE)
        self.move_frame = Frame(self, bd=1, relief=RIDGE)
          
          
         # alignment options
         # alignment options
Line 64: Line 80:
         self.alignRadio9 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="BR")
         self.alignRadio9 = Radiobutton(self.align_frame, text='', variable=self.alignVar, value="BR")
         self.alignButton = Button(self.align_frame, text='Align', command=self.alignImage)
         self.alignButton = Button(self.align_frame, text='Align', command=self.alignImage)
        self.alignRadio5.select()
          
          
         # scaling options
         # scaling options
Line 74: Line 91:
         self.scalePercentEntry = Entry(self.scale_frame, textvariable=self.scalePercentVar, width=8)
         self.scalePercentEntry = Entry(self.scale_frame, textvariable=self.scalePercentVar, width=8)
         self.scalePercentButton = Button(self.scale_frame, text='Scale', command=self.scaleImageToPercent)
         self.scalePercentButton = Button(self.scale_frame, text='Scale', command=self.scaleImageToPercent)
       
        #flip options
        self.flipLabel = Label(self.flip_frame, text='Flip Image:')
        self.flipHorizontallyButton = Button(self.flip_frame, text='< Flip Horizontally >', command=self.flipHorizontally)
        self.flipVerticallyButton = Button(self.flip_frame, text='^\nFlip Vertically\nv', command=self.flipVertically)
        self.flipUndoButton = Button(self.flip_frame, text='No Flipping', command=self.flipUndo)
       
        #move options
        self.moveVar = StringVar()
        self.moveRadio1 = Radiobutton(self.move_frame, variable=self.moveVar, value="Image", text='Move Image')
        self.moveRadio2 = Radiobutton(self.move_frame, variable=self.moveVar, value="Frame", text='Move Frame')
        self.moveUpButton = Button(self.move_frame, text='^', command=self.moveUp)
        self.moveUpLotsButton = Button(self.move_frame, text='^^', command=self.moveUpLots)
        self.moveDownButton = Button(self.move_frame, text='v', command=self.moveDown)
        self.moveDownLotsButton = Button(self.move_frame, text='vv', command=self.moveDownLots)
        self.moveLeftButton = Button(self.move_frame, text='<', command=self.moveLeft)
        self.moveLeftLotsButton = Button(self.move_frame, text='<<', command=self.moveLeftLots)
        self.moveRightButton = Button(self.move_frame, text='>', command=self.moveRight)
        self.moveRightLotsButton = Button(self.move_frame, text='>>', command=self.moveRightLots)
        self.moveRadio1.select()
          
          
         # closing/running
         # closing/running
Line 82: Line 119:
         self.statusLabel = Label(self, textvariable=self.statusVar)
         self.statusLabel = Label(self, textvariable=self.statusVar)
         self.statusVar.set('Status:')
         self.statusVar.set('Status:')
       
        # setup values
        self.alignRadio5.select()
          
          
         # make align layout
         # make align layout
Line 113: Line 147:
         self.scaleToFitButton.grid(column=0, row=currRow, columnspan=3)
         self.scaleToFitButton.grid(column=0, row=currRow, columnspan=3)
         currRow += 1
         currRow += 1
         self.scalePercentLabel1.grid(column=0, row=currRow, columnspan=3, sticky=W)
         self.scalePercentLabel1.grid(column=0, row=currRow, columnspan=3)
         currRow += 1
         currRow += 1
         self.scalePercentEntry.grid(column=0, row=currRow)
         self.scalePercentEntry.grid(column=0, row=currRow)
         self.scalePercentLabel2.grid(column=1, row=currRow)
         self.scalePercentLabel2.grid(column=1, row=currRow)
         self.scalePercentButton.grid(column=2, row=currRow)
         self.scalePercentButton.grid(column=2, row=currRow)
       
        #make flip layout
        currRow = 0
        self.flipLabel.grid(column=0, row=currRow)
        currRow += 1
        self.flipHorizontallyButton.grid(column=0, row=currRow)
        currRow += 1
        self.flipVerticallyButton.grid(column=0, row=currRow)
        currRow += 1
        self.flipUndoButton.grid(column=0, row=currRow)
       
        #make move layout
        currRow = 0
        self.moveRadio1.grid(column=0, row=currRow, columnspan=5)
        currRow += 1
        self.moveRadio2.grid(column=0, row=currRow, columnspan=5)
        currRow += 1
        self.moveUpLotsButton.grid(column=2, row=currRow)
        currRow += 1
        self.moveUpButton.grid(column=2, row=currRow)
        currRow += 1
        self.moveLeftLotsButton.grid(column=0, row=currRow)
        self.moveLeftButton.grid(column=1, row=currRow)
        self.moveRightButton.grid(column=3, row=currRow)
        self.moveRightLotsButton.grid(column=4, row=currRow)
        currRow += 1
        self.moveDownButton.grid(column=2, row=currRow)
        currRow += 1
        self.moveDownLotsButton.grid(column=2, row=currRow)
          
          
         #make overall layout
         #make overall layout
         self.grid()
         self.grid()
         self.align_frame.grid(row=0, column=0, sticky=N)
         self.scale_frame.grid(row=0, column=0, sticky=NSEW)
         self.scale_frame.grid(row=0, column=1, sticky=N)
         self.flip_frame.grid(row=0, column=1, sticky=NSEW)
         self.doneButton.grid(row=1, column=0, columnspan=2)
        self.align_frame.grid(row=1, column=0, sticky=NSEW)
         #self.statusLabel.grid(row=2, column=0, columnspan=2, stick=W)
        self.move_frame.grid(row=1, column=1, sticky=NSEW)
         self.doneButton.grid(row=2, column=0, columnspan=2)
         #self.statusLabel.grid(row=2, column=0, columnspan=3, stick=W)




Line 136: Line 201:
                 try:
                 try:
                     obj = objList[i]
                     obj = objList[i]
                     frameW = getProperty(obj, "width")
                     if getProperty(obj, "itemType") == 2:
                    frameH = getProperty(obj, "height")
                        frameW = getProperty(obj, "width")
                    saveScaleX = getProperty(obj, "imageXScale")
                        frameH = getProperty(obj, "height")
                    saveScaleY = getProperty(obj, "imageYScale")
                        saveScaleX = getProperty(obj, "imageXScale")
                    setScaleImageToFrame(True, False, obj)
                        saveScaleY = getProperty(obj, "imageYScale")
                    fullScaleX = getProperty(obj, "imageXScale")
                        setScaleImageToFrame(True, False, obj)
                    fullScaleY = getProperty(obj, "imageYScale")
                        fullScaleX = getProperty(obj, "imageXScale")
                    setScaleImageToFrame(False, False, obj)
                        fullScaleY = getProperty(obj, "imageYScale")
                    scaleImage(saveScaleX, saveScaleY, obj)
                        setScaleImageToFrame(False, False, obj)
                    imageW = frameW * (saveScaleX / fullScaleX)
                        scaleImage(saveScaleX, saveScaleY, obj)
                    imageH = frameH * (saveScaleY / fullScaleY)
                        imageW = frameW * (saveScaleX / fullScaleX)
                    imageX = 0.0
                        imageH = frameH * (saveScaleY / fullScaleY)
                    imageY = 0.0
                        imageX = 0.0
                   
                    if self.alignVar.get()[0] == "T":
                         imageY = 0.0
                         imageY = 0.0
                    elif self.alignVar.get()[0] == "M":
                       
                        imageY = (frameH - imageH) / 2.0 / saveScaleY
                        if self.alignVar.get()[0] == "T":
                    elif self.alignVar.get()[0] == "B":
                            imageY = 0.0
                        imageY = (frameH - imageH) / saveScaleY
                        elif self.alignVar.get()[0] == "M":
                    if self.alignVar.get()[1] == "L":
                            imageY = (frameH - imageH) / 2.0 / saveScaleY
                        imageX = 0.0
                        elif self.alignVar.get()[0] == "B":
                    elif self.alignVar.get()[1] == "C":
                            imageY = (frameH - imageH) / saveScaleY
                        imageX = (frameW - imageW) / 2.0 / saveScaleX
                        if self.alignVar.get()[1] == "L":
                    elif self.alignVar.get()[1] == "R":
                            imageX = 0.0
                        imageX = (frameW - imageW) / saveScaleX
                        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, "imageXOffset", imageX)
                    setProperty(obj, "imageYOffset", imageY)
                        setProperty(obj, "imageYOffset", imageY)
                    docChanged(1)
                        docChanged(1)
                    setRedraw(True)
                        setRedraw(True)
                 except:
                 except:
                     nothing = "nothing"
                     nothing = "nothing"
Line 179: Line 245:
             try:
             try:
                 obj = objList[i]
                 obj = objList[i]
                 setScaleImageToFrame(True, False, obj)
                 if getProperty(obj, "itemType") == 2:
                scaleX, scaleY = getImageScale(obj)
                    setScaleImageToFrame(True, False, obj)
                setScaleImageToFrame(False, False, obj)
                    scaleX, scaleY = getImageScale(obj)
                if scaleX > scaleY:
                    setScaleImageToFrame(False, False, obj)
                    scale = scaleX
                    if scaleX > scaleY:
                    scaleImage(scale, scale, obj)
                        scale = scaleX
                elif scaleY > scaleX:
                        scaleImage(scale, scale, obj)
                    scale = scaleY
                    elif scaleY > scaleX:
                    scaleImage(scale, scale, obj)
                        scale = scaleY
                docChanged(1)
                        scaleImage(scale, scale, obj)
                setRedraw(True)
                    docChanged(1)
                    setRedraw(True)
             except:
             except:
             nothing = "nothing"
             nothing = "nothing"
Line 202: Line 269:
             try:
             try:
                 obj = objList[i]
                 obj = objList[i]
                 setScaleImageToFrame(True, True, obj)
                 if getProperty(obj, "itemType") == 2:
                docChanged(1)
                    setScaleImageToFrame(True, True, obj)
                setRedraw(True)
                    docChanged(1)
                    setRedraw(True)
             except:
             except:
             nothing = "nothing"
             nothing = "nothing"
Line 224: Line 292:
             except:
             except:
                 nothing = "nothing"
                 nothing = "nothing"
    def flipHorizontally(self):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    setProperty(obj, "m_ImageIsFlippedH", not getProperty(obj, "m_ImageIsFlippedH"))
                    self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
                nothing = "nothing"
               
    def flipVertically(self):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    setProperty(obj, "m_ImageIsFlippedV", not getProperty(obj, "m_ImageIsFlippedV"))
                    self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
            nothing = "nothing"
               
    def flipUndo(self):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    setProperty(obj, "m_ImageIsFlippedH", False)
                    setProperty(obj, "m_ImageIsFlippedV", False)
                    self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
            nothing = "nothing"
               
    def moveUp(self):
        self.moveImage(0, -10.0)
   
    def moveUpLots(self):
        self.moveImage(0, -100.0)
       
    def moveDown(self):
        self.moveImage(0, 10.0)
       
    def moveDownLots(self):
        self.moveImage(0, 100.0)
       
    def moveLeft(self):
        self.moveImage(-10.0, 0)
       
    def moveLeftLots(self):
        self.moveImage(-100.0, 0)
       
    def moveRight(self):
        self.moveImage(10.0, 0)
   
    def moveRightLots(self):
        self.moveImage(100.0, 0)
       
    def moveImage(self, dx, dy):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    #based on which radio button is selected, we either move the image frame on the canvas, or move the image in its frame
                    if str(self.moveVar.get()) == "Frame":
                        #moveObject(dx, dy, obj)
                        setProperty(obj, "xPos", getProperty(obj, "xPos") + dx)
                        setProperty(obj, "yPos", getProperty(obj, "yPos") + dy)
                        self.forceRefresh(obj)
                    else:
                        #if the image is flipped, we need to reverse the delta-X or delta-Y in order to keep moving
                        #the image in the direction that the user expects
                        if getProperty(obj, "m_ImageIsFlippedH"):
                            dx = dx * -1
                        if getProperty(obj, "m_ImageIsFlippedV"):
                            dy = dy * -1
                        setProperty(obj, "imageXOffset", getProperty(obj, "imageXOffset") + dx)
                        setProperty(obj, "imageYOffset", getProperty(obj, "imageYOffset") + dy)
                        self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
            nothing = "nothing"
               
    def forceRefresh(self, obj):
        #changing the certain properties doesn't actually redraw the image until the script is terminated
        #to fix this, we move the image and then move it back to the same spot, thus triggering a refresh of the image
        moveObject(1, 0, obj)
        moveObject(-1, 0, obj)
        docChanged(1)
        setRedraw(True)


     def quit(self):
     def quit(self):

Latest revision as of 22:59, 10 February 2014

This article is part of the Scripts series.

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, and flipping and manual alignment 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)
  • Automatic alignment (9 possible alignments)
  • Click arrow buttons to align the image in the frame
  • Click arrow buttons to align the frame on the canvas
  • Flip the image horizontally or vertically

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.

Here is a screenshot of the script:

ImageWizard3.png

Save this script with a filename of Image_Wizard.py, for example.

# License
# Copyright 2007, Jeremy Brown (TrnsltLife)
# This script 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.

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)
        self.flip_frame = Frame(self, bd=1, relief=RIDGE)
        self.move_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)
        self.alignRadio5.select()
        
        # 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)
        
        #flip options
        self.flipLabel = Label(self.flip_frame, text='Flip Image:')
        self.flipHorizontallyButton = Button(self.flip_frame, text='< Flip Horizontally >', command=self.flipHorizontally)
        self.flipVerticallyButton = Button(self.flip_frame, text='^\nFlip Vertically\nv', command=self.flipVertically)
        self.flipUndoButton = Button(self.flip_frame, text='No Flipping', command=self.flipUndo)
        
        #move options
        self.moveVar = StringVar()
        self.moveRadio1 = Radiobutton(self.move_frame, variable=self.moveVar, value="Image", text='Move Image')
        self.moveRadio2 = Radiobutton(self.move_frame, variable=self.moveVar, value="Frame", text='Move Frame')
        self.moveUpButton = Button(self.move_frame, text='^', command=self.moveUp)
        self.moveUpLotsButton = Button(self.move_frame, text='^^', command=self.moveUpLots)
        self.moveDownButton = Button(self.move_frame, text='v', command=self.moveDown)
        self.moveDownLotsButton = Button(self.move_frame, text='vv', command=self.moveDownLots)
        self.moveLeftButton = Button(self.move_frame, text='<', command=self.moveLeft)
        self.moveLeftLotsButton = Button(self.move_frame, text='<<', command=self.moveLeftLots)
        self.moveRightButton = Button(self.move_frame, text='>', command=self.moveRight)
        self.moveRightLotsButton = Button(self.move_frame, text='>>', command=self.moveRightLots)
        self.moveRadio1.select()
        
        # 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:')
        
        # 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)
        currRow += 1
        self.scalePercentEntry.grid(column=0, row=currRow)
        self.scalePercentLabel2.grid(column=1, row=currRow)
        self.scalePercentButton.grid(column=2, row=currRow)
        
        #make flip layout
        currRow = 0
        self.flipLabel.grid(column=0, row=currRow)
        currRow += 1
        self.flipHorizontallyButton.grid(column=0, row=currRow)
        currRow += 1
        self.flipVerticallyButton.grid(column=0, row=currRow)
        currRow += 1
        self.flipUndoButton.grid(column=0, row=currRow)
        
        #make move layout
        currRow = 0
        self.moveRadio1.grid(column=0, row=currRow, columnspan=5)
        currRow += 1
        self.moveRadio2.grid(column=0, row=currRow, columnspan=5)
        currRow += 1
        self.moveUpLotsButton.grid(column=2, row=currRow)
        currRow += 1
        self.moveUpButton.grid(column=2, row=currRow)
        currRow += 1
        self.moveLeftLotsButton.grid(column=0, row=currRow)
        self.moveLeftButton.grid(column=1, row=currRow)
        self.moveRightButton.grid(column=3, row=currRow)
        self.moveRightLotsButton.grid(column=4, row=currRow)
        currRow += 1
        self.moveDownButton.grid(column=2, row=currRow)
        currRow += 1
        self.moveDownLotsButton.grid(column=2, row=currRow)
        
        #make overall layout
        self.grid()
        self.scale_frame.grid(row=0, column=0, sticky=NSEW)
        self.flip_frame.grid(row=0, column=1, sticky=NSEW)
        self.align_frame.grid(row=1, column=0, sticky=NSEW)
        self.move_frame.grid(row=1, column=1, sticky=NSEW)
        self.doneButton.grid(row=2, column=0, columnspan=2)
        #self.statusLabel.grid(row=2, column=0, columnspan=3, 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]
                    if getProperty(obj, "itemType") == 2:
                        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]
                if getProperty(obj, "itemType") == 2:
                    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]
                if getProperty(obj, "itemType") == 2:
                    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 flipHorizontally(self):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    setProperty(obj, "m_ImageIsFlippedH", not getProperty(obj, "m_ImageIsFlippedH"))
                    self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
                nothing = "nothing"
                
    def flipVertically(self):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    setProperty(obj, "m_ImageIsFlippedV", not getProperty(obj, "m_ImageIsFlippedV"))
                    self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
        	    nothing = "nothing"
                
    def flipUndo(self):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    setProperty(obj, "m_ImageIsFlippedH", False)
                    setProperty(obj, "m_ImageIsFlippedV", False)
                    self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
        	    nothing = "nothing"
                
    def moveUp(self):
        self.moveImage(0, -10.0)
    
    def moveUpLots(self):
        self.moveImage(0, -100.0)
        
    def moveDown(self):
        self.moveImage(0, 10.0)
        
    def moveDownLots(self):
        self.moveImage(0, 100.0)
        
    def moveLeft(self):
        self.moveImage(-10.0, 0)
        
    def moveLeftLots(self):
        self.moveImage(-100.0, 0)
        
    def moveRight(self):
        self.moveImage(10.0, 0)
    
    def moveRightLots(self):
        self.moveImage(100.0, 0)
        
    def moveImage(self, dx, dy):
        if haveDoc():
            nbrSelected = selectionCount()
        objList = []
        for i in range(nbrSelected):
            objList.append(getSelectedObject(i))
        for i in range(nbrSelected):
            try:
                obj = objList[i]
                if getProperty(obj, "itemType") == 2:
                    #based on which radio button is selected, we either move the image frame on the canvas, or move the image in its frame
                    if str(self.moveVar.get()) == "Frame":
                        #moveObject(dx, dy, obj)
                        setProperty(obj, "xPos", getProperty(obj, "xPos") + dx)
                        setProperty(obj, "yPos", getProperty(obj, "yPos") + dy)
                        self.forceRefresh(obj)
                    else:
                        #if the image is flipped, we need to reverse the delta-X or delta-Y in order to keep moving
                        #the image in the direction that the user expects
                        if getProperty(obj, "m_ImageIsFlippedH"):
                            dx = dx * -1
                        if getProperty(obj, "m_ImageIsFlippedV"):
                            dy = dy * -1
                        setProperty(obj, "imageXOffset", getProperty(obj, "imageXOffset") + dx)
                        setProperty(obj, "imageYOffset", getProperty(obj, "imageYOffset") + dy)
                        self.forceRefresh(obj)
                    docChanged(1)
                    setRedraw(True)
            except:
        	    nothing = "nothing"
                
    def forceRefresh(self, obj):
        #changing the certain properties doesn't actually redraw the image until the script is terminated
        #to fix this, we move the image and then move it back to the same spot, thus triggering a refresh of the image
        moveObject(1, 0, obj)
        moveObject(-1, 0, obj)
        docChanged(1)
        setRedraw(True)

    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()