Python Forum

Full Version: What is the best way to return these 4 integer values?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have a little Python program to resize pdfs. Works OK for my purposes.

I want to cut it up into functions.

The first function takes the pdf and splits it into jpgs.

The next function opens 1 of the jpgs and should return the values for cropping the pdf. It should just return 4 integers, or 2 tuples (left,top) and (right, bottom)

I don't know how to return these values from this function. What is the best way to return them??

def getSize():
    print('Now getting the optimal size for the pdf ...')
    jpgfiles = os.listdir(pathTojpgs)
    jpgfiles.sort()
    picture = Image.open(pathTojpgs + jpgfiles[0])
    width, height = picture.size
    print('jpg width = ' + str(width) + ' jpg height = ' + str(height))
    answer='NO'
    top = 200
    left=200
    bottom=2000
    right=1500
    im1 = picture.crop((left, top, right, bottom))
    im1 = im1.resize(newsize)
    im1.show()
    answer = input('enter OK if you are happy, otherwise enter NO to try again  ')
    while answer not in 'OK':        
        print('enter new values for top, left, bottom, right')        
        x1 = input('value for left ... ')
        y1 = input('value for top ... ')        
        x2 = input('value for right ... ')
        y2 = input('value for bottom ... ')        
        left = int(x1)
        top = int(y1)        
        right = int(x2)
        bottom = int(y2)
        im1 = picture.crop((left, top, right, bottom))
        im1 = im1.resize(newsize)
        im1.show()
        answer = input('enter OK if you are happy, otherwise enter NO to try again  ')
    return  HOW???? ;
which will then go in this function:

for jpg in jpgfiles:
        picture1 = Image.open(pathTojpgs + jpg)
        im1 = picture1.crop((left, top, right, bottom))
        im1 = im1.resize(newsize)
        output = jpg.split('.')       
        savefilename = output[0] + 'shrunk.jpg'
        im1.save(pathToShrunkjpgs + savefilename)
        print(jpg + ' shrunk and saved to ' + pathToShrunkjpgs) 
    name = output[0]
    jpg2pdf(name) # join the jpgs to a pdf again
    junkjpgs(pathTojpgs) # get rid of the mess
    junkjpgs(pathToShrunkjpgs)
return (left, top, right, bottom) # one tuple
or
return((left, top), (right, bottom)) # tuple of tuples
I would define namedtuple in advance, e.g. Point with x and y or Rectangle with left, top, right and bottom. And will return namedtuple

from collections import namedtuple

Rectangle = namedtuple('Rectangle', 'left, top, right, bottom')

def get_int(prompt):
    while True:
        try:
            return int(input(prompt))
        except TypeError:
            print('This is not a valid input. Try again.')


def getSize():
    print('Now getting the optimal size for the pdf ...')
    jpgfiles = os.listdir(pathTojpgs)
    jpgfiles.sort()
    picture = Image.open(pathTojpgs + jpgfiles[0])
    width, height = picture.size
    print('jpg width = ' + str(width) + ' jpg height = ' + str(height))
    crop_rect = Rectangle(left=200, top=200, right=1500, bottom=2000) # you can pass them as positional arguments, but kwargs make it more clear
    while True: 
        im1 = picture.crop(crop_rect) # Fix the error, no need to unpack
        im1 = im1.resize(newsize)
        im1.show()
        answer = input('enter OK if you are happy, otherwise enter NO to try again: ')
        if answer.lower() == 'ok':
            break # break of the loop or you can directly do return  crop_rect and remove the return statement from the end
        print('enter new values for top, left, bottom, right')
        crop_rect = Rectangle(*[get_int(f'Value for {coord}: ') for coord in Rectangle._fields])  
    return crop_rect
I also simplified your function and made another function to guarantee that input is int
Thank you very much, I've never used tuples before, wasn't sure how to handle them!

Slight hiccough:

I only changed getSize() by passing it jpgfiles[0]

def getSize(ajpg):
    print('Now getting the optimal size for the pdf ...')    
    picture = Image.open(pathTojpgs + ajpg)
    width, height = picture.size
    print('jpg width = ' + str(width) + ' jpg height = ' + str(height))
    crop_rect = Rectangle(left=200, top=200, right=1500, bottom=2000) # you can pass them as positional arguments, but kwargs make it more clear
    while True: 
        im1 = picture.crop(*crop_rect)
        im1 = im1.resize(newsize)
        im1.show()
        answer = input('enter OK if you are happy, otherwise enter NO to try again: ')
        if answer.lower() == 'ok':
            break # break of the loop or you can directly do return  crop_rect and remove the return statement from the end
        print('enter new values for top, left, bottom, right')
        crop_rect = Rectangle(*[get_int(f'Value for {coord}: ') for coord in Rectangle._fields])  
    return  crop_rect
I tried to use getSize(ajpg) like this:

for file in pdfNames:
    print('splitting ' + file + ' to jpgs ')
    outputName = file.split('.')
    saveFilename = outputName[0]
    splitPDF(file, saveFilename)
    print('pdf split to jpgs!')
    print('now reize the jpgs ... ')
    jpgfiles = os.listdir(pathTojpgs)
    jpgfiles.sort()
    size1 = getSize(jpgfiles[0])
    for jpg in jpgfiles:        
        picture1 = Image.open(pathTojpgs + jpg)
        im1 = picture1.crop(size1)
        im1 = im1.resize(newsize)
        output = jpg.split('.')       
        savefilename = output[0] + 'shrunk.jpg'
        im1.save(pathToShrunkjpgs + savefilename)
        print(jpg + ' shrunk and saved to ' + pathToShrunkjpgs) 
    name = output[0]
    jpg2pdf(name)
    junkjpgs(pathTojpgs)
    junkjpgs(pathToShrunkjpgs)
but getSize(ajpg) is showing this error:

Quote:>>> size1 = getSize(jpgfiles[0])
Now getting the optimal size for the pdf ...
jpg width = 1654 jpg height = 2339
Traceback (most recent call last):
File "<pyshell#61>", line 1, in <module>
size1 = getSize(jpgfiles[0])
File "<pyshell#60>", line 8, in getSize
im1 = picture.crop(*crop_rect)
TypeError: crop() takes from 1 to 2 positional arguments but 5 were given
>>>

I can't see the problem, can you please advise?
sorry, I overlooked that - you don't need to unpack the tuple when you pass it to crop
        im1 = picture.crop(*crop_rect)
should be
        im1 = picture.crop(crop_rect)
Thanks again!

I stopped yesterday, too long in front of the computer. It's nearly 6am now, I just tried it. Works great!

Quote:>>> size1
Rectangle(left=230, top=200, right=1330, bottom=1850)

That should keep the gf. happy!!

Obviously, your code is much more sophisticated than the rubbish I write. I'm still trying to understand it!

Thanks again!