Welcome, guest | Sign In | My Account | Store | Cart
import os
import pygame, sys
from pygame.locals import K_a, K_s,K_w,K_d,K_LEFTBRACKET,K_RIGHTBRACKET, K_RIGHT, K_LEFT, QUIT

from PIL import Image
pygame.init()


'''

main() sets these (perhaps differently), so make changes down there.
If you cut/copy this code somewhere you need these variables globally,
or make it a class and make these attributes.

'''

resolution = 300    #the resolution (in dpi) the resulting cropped images should have.

infile_folder = '.'             #path to folder images to process are in.  '.' is the folder this script is in
infile_prefix = "album80-86_"   #prefix common to all the images you'd like to access

start_page = 1                  #which page to start on.  0 is the first page.

outfile_folder= "./cropped"
outfile_prefix = "photo80-86_"
outfile_extension = "jpg"      #must be three character extension with no period. Why? Because I am lazy.  So no "jpeg", okay?


BG_COLOR = (0,0,0)

def displayRect(screen, px, topleft, prior,pos,scale):
    # ensure that the rect always has positive width, height

    if topleft == None:
        #func was called without a topleft, which means clear the previous rectangle
        screen.fill(BG_COLOR)
        rect = px.get_rect()
        px = pygame.transform.scale(px,[int(rect.width/scale), int(rect.height/scale)])
        screen.blit(px, (rect[0]-pos[0],rect[1]-pos[1]))
        pygame.display.flip()

        return None

    #or, the usual situation, topleft is defined, so blit over the old rect and blit in the new.
    topleft = [(val/scale-pos[i]) for i,val in enumerate(topleft)]
    x, y = topleft
    bottomright = pygame.mouse.get_pos()
    width =  bottomright[0] - topleft[0]
    height = bottomright[1] - topleft[1]
    if width < 0:
        x += width
        width = abs(width)
    if height < 0:
        y += height
        height = abs(height)

    # eliminate redundant drawing cycles (when mouse isn't moving)
 
    current = x, y, width, height
    if not (width and height):
        return current
    if current == prior:
        return current

    # draw transparent box and blit it onto canvas
    rect = px.get_rect()
    px = pygame.transform.scale(px,[int(rect.width/scale), int(rect.height/scale)])
    screen.blit(px, (rect[0]-pos[0],rect[1]-pos[1]))
    im = pygame.Surface((width, height))
    im.fill((128, 128, 128))
    pygame.draw.rect(im, (32, 32, 32), im.get_rect(), 1)
    im.set_alpha(128)
    screen.blit(im, (x, y))
    pygame.display.flip()

    # return current box extents
    return (x, y, width, height)

def setup(px):
    screen = pygame.display.set_mode( px.get_rect()[2:] )
    screen.blit(px, px.get_rect())
    pygame.display.flip()
    return screen, px

def move(pos,scale,px,screen):
    x,y = pos
    #print pos,x
    rect = px.get_rect()
    screen.fill(BG_COLOR)
    px = pygame.transform.scale(px,[int(rect.width/scale), int(rect.height/scale)])
    screen.blit(px, (rect[0]-x,rect[1]-y))
    pygame.display.flip()
    #px.rect.topleft = pr.rect.topleft[0] - x, 

def mainLoop():
    topleft = bottomright = prior = None
    n=0
    scale = 1
    pos = [0,0]

    #create list of files matching prefix in folder, and sort it
    # input_loc = first file  #input_loc = 'album86-92_003.jpg'
    infiles = []
    len_prefix = len(infile_prefix)
    for fname in os.listdir(infile_folder):
        if fname[:len_prefix] == infile_prefix:
            if fname[-3:] in ['jpg','png']:
                infiles.append(fname)
    infiles.sort()

    file_idx = start_page
    try:
        infile = infiles[file_idx]
    except IndexError:
        print "the start page you requested is beyond the scope of the files loaded.\nYou have been taken to the last page instead."
        file_idx = len(infiles)-1
        infile = infiles[file_idx]

    #get files begining with output prefix, grab suffixes and sort.
    #but, if folder does not exist or is empty, just start at 0 
    outfiles = []
    len_prefix = len(outfile_prefix)

    try:
        for fname in os.listdir(outfile_folder):
            if fname[:len_prefix] == outfile_prefix:
                outfiles.append(fname)
    except OSError:
        os.makedirs(outfile_folder)
        out_idx = 0

    else:
        outfiles.sort()
        try:
            out_idx = int(outfiles[-1][len_prefix:-4])+1
        except ValueError:
            print "Egad! Not all files with the output prefix specified end with a number followed by a three character extension\nMaybe start a new output folder?"
            print "...Quitting"
            return 0
        except IndexError:
            #folder exisits but is empty
            out_idx = 0

    input_loc = os.path.join(infile_folder,infile)
    screen, px = setup(px = pygame.image.load(input_loc))        
    
    outfilename = outfile_prefix+str(out_idx).zfill(3)+'.'+outfile_extension
    output_loc = os.path.join(outfile_folder,outfilename)
    while n!=1:
        for event in pygame.event.get():

            if event.type == QUIT: 
                sys.exit(0)

            if event.type == pygame.MOUSEBUTTONUP:
                if not topleft:
                    topleft = [(val+pos[i])*scale for i,val in enumerate(event.pos)]
                    #print "tr: ",topleft
                else:
                    bottomright = [(val+pos[i])*scale for i,val in enumerate(event.pos)]
                    #print "br: ",bottomright
                    

            if event.type == pygame.KEYDOWN and event.key == K_a:
                pos = [pos[0]-200,pos[1]]
                move(pos,scale,px,screen)
            if event.type == pygame.KEYDOWN and event.key == K_d:
                pos = [pos[0]+200,pos[1]]
                move(pos,scale,px,screen)
            if event.type == pygame.KEYDOWN and event.key == K_w:
                pos = [pos[0],pos[1]-200]
                move(pos,scale,px,screen)
            if event.type == pygame.KEYDOWN and event.key == K_s:
                pos = [pos[0],pos[1]+200]
                move(pos,scale,px,screen)


            if event.type == pygame.KEYDOWN and event.key == K_RIGHTBRACKET:
                scale = scale/1.25
                move(pos,scale,px,screen)
            if event.type == pygame.KEYDOWN and event.key == K_LEFTBRACKET:
                scale = scale*1.25
                move(pos,scale,px,screen)
            
            if event.type == pygame.KEYDOWN and event.key == K_RIGHT:
                file_idx += 1
                try:
                    infile = infiles[file_idx]
                    #print "file_idx: ",file_idx
                except IndexError:
                    file_idx -= 1
                    print "End of album"
                    #raise
                else:
                    input_loc = os.path.join(infile_folder,infile)
                    px = pygame.image.load(input_loc)
                    pos = [0,0]
                    topleft = bottomright = prior = None
                    prior = displayRect(screen, px, topleft, prior,pos,scale)

            if event.type == pygame.KEYDOWN and event.key == K_LEFT:
                if file_idx == 0:
                    print "This is the begining of the album, cannot go back a page."
                else:
                    #print "file_idx",file_idx
                    file_idx -= 1
                    infile = infiles[file_idx]
                    input_loc = os.path.join(infile_folder,infile)
                    px = pygame.image.load(input_loc)
                    pos = [0,0]
                    topleft = bottomright = prior = None
                    prior = displayRect(screen, px, topleft, prior,pos,scale)


                
        if topleft:
            #first corner has been selected
            prior = displayRect(screen, px, topleft, prior,pos,scale)
            if bottomright:
                #selection has been made!
                left, upper, right, lower = ( topleft + bottomright )
                # ensure output rect always has positive width, height
                if right < left:
                    left, right = right, left
                if lower < upper:
                    lower, upper = upper, lower
                im = Image.open(input_loc)
                im = im.crop(( int(left), int(upper), int(right), int(lower)))
                dpi = resolution
                im.save(output_loc, dpi = (dpi,dpi))
                out_idx += 1
                outfilename = outfile_prefix+str(out_idx).zfill(3)+'.'+outfile_extension
                output_loc = os.path.join(outfile_folder,outfilename)
                topleft = bottomright = prior = None
                prior = displayRect(screen, px, topleft, prior,pos,scale)
                print "saved"
                
    return

if __name__ == "__main__":
    os.system( [ 'clear', 'cls' ][ os.name == 'nt' ] )
    print'''
Hello! 

This program exists to speed up cropping out many sections from larger images 
while also changing the resolution of the cropped images.

The Zudell family photo album was scanned at 600 dpi resolution.
The default resolution for cropped images is 300 dpi.
    '''
    resolution = raw_input('enter new integer resolution, or nothing for default: ')
    os.system( [ 'clear', 'cls' ][ os.name == 'nt' ] )
    try: resolution = int(resolution)
    except:
        print '\nNo new resolution specified, using 300 dpi'
        resolution = int(300)
    dirs = []
    for f in os.listdir('.'):
        if os.path.isdir(f):
             dirs.append(f)

    print '''\n\n\n\n
now, enter the name of the directory you want to work on. here is a list of sub 
directories within this current directory:\n'''
    if dirs:
        for dir in dirs: print dir
    else:
        print "oops, there are no sub-directories here"

    print "\n\nenter nothing or nonsense to use the current directory"
    path = raw_input("enter directory to use: ")
    infile_folder = path.strip()
    os.system( [ 'clear', 'cls' ][ os.name == 'nt' ] )
    if os.path.isdir(infile_folder):
        pass
    elif os.path.isdir('./'+infile_folder):
        infile_folder = './'+infile_folder
    else:
        print "no valid directory entered, using current"
        infile_folder = '.'

    for f in os.listdir(infile_folder):
        print f
    if not os.listdir(infile_folder):
        print "oh... There aren't any files at all in here"
        d = raw_input("press enter to quit")
        pygame.display.quit()
 
    print '''\n\n
You may choose a filename prefix so that only some of the images in this dir 
are available for editing.  all files in this directory are listed above. \n'''

    infile_prefix = raw_input('input file prefix (or nothing to use all files): ')
    os.system( [ 'clear', 'cls' ][ os.name == 'nt' ] )

    print '''\n\n
You may choose a prefix for output files also. they will go in the ./cropped folder.\n'''

    outfile_prefix = raw_input('output file prefix (or nothing for default): ')
    if not outfile_prefix: outfile_prefix = "image_"
    os.system( [ 'clear', 'cls' ][ os.name == 'nt' ] )

    print '''
Use the left ard right arrows to change image. 

'[' and ']' zoom out and in, respectively.  

click and drag a box to crop. 

too move around:

   w
  asd


And come back to this screen to see unnecessary messages.
    '''
    raw_input('\npress enter to begin')
    mainLoop()

    pygame.display.quit()

History