def main(assets, keep_meta, geo_tag, dest_dir, size): minumum_size = True resizePercent = 0 # This is time in seconds to allow for dropbox to process each photo. Older iOS devices will require more time. upload_pause = 3 if size == 'fifty': scale = float(50) / 100 elif size == 'custom': scale = tf2 # Numbers only for textbox entries scale.keyboard_type = ui.KEYBOARD_NUMBER_PAD # Display ui locked in portrait orientation and wait till user selects something from it. v2.present(orientations=['portrait']) v2.wait_modal() scale = float(scale.text) / 100 # No minumums here...reduce all photos no matter what their size. minumum_size = False # If user pressed the close button then cancel script if not ok: console.hud_alert('Script Cancelled') sys.exit() elif size == 'none': scale = 1 # Disable idle timer to cover working with a large batch of photos console.set_idle_timer_disabled(True) start = time.clock() # Create an instance of Dropbox client drop_client = get_client() for asset in assets: print('\nProcessing photo...') ''' Get date & time photo was created on YOUR iOS device. Note that in some cases the creation date may not be the date the photo was taken (ie you got it via text, email, Facebook, etc), but rather the date the photo was saved to the camera roll on your device. ''' the_year, the_date, the_time = get_date_time(asset.creation_date) file_name = '' # Formulate file name for photo old_filename = str(ObjCInstance(asset).filename()) if the_date: folder_name = '{}/{}'.format(the_year, the_date) new_filename = '{}.{}'.format(the_time, old_filename) else: folder_name = 'NoDates' new_filename = old_filename keep_meta = False new_filename = '{}/{}/{}'.format(dest_dir, folder_name, new_filename) if folder_name == 'NoDates': no_exif.append(new_filename) file_name = '{}.{}'.format(the_time, file_name) # Get dimensions for resize based on size of original photo new_w, new_h, w, h, resizeOk = get_dimensions(asset, scale, new_filename, minumum_size) fmt = '\nOriginal Name: {}\nNew Name: {}' print(fmt.format(old_filename, new_filename)) fmt = '\nOriginal Size: {}x{}\nNew Size: {}x{}' print(fmt.format(w, h, new_w, new_h)) addToMsg = 'with' if keep_meta else 'without' if resizeOk: msg = '\nCreating resized copy of original photo {} the metadata from original.' else: msg = '\nCreating copy of original photo {} the metadata from original.' print(msg.format(addToMsg)) # Fetch asset's image data & return it as a io.BytesIO object and then as a byte string img = asset.get_image_data(original=False).getvalue() # Write string image of original photo to Pythonista script dir with open('with_meta.jpg', 'wb') as out_file: out_file.write(img) # Open image, resize it, and write new image to scripts dir img = Image.open('with_meta.jpg') # Retrieve a number that represents the orientation of photo orientation = str(ObjCInstance(asset).orientation()) # Landscape if orientation in ('1', '3'): img = img.resize((new_w, new_h), Image.ANTIALIAS) # Occasionally metadata will say the photo orientation is 1 even though the width is less than the height of photo. oriented = 'portrait' if new_w < new_h else 'landscape' # Portrait elif orientation in ('6', '8'): img = img.resize((new_h, new_w), Image.ANTIALIAS) oriented = 'portrait' # Unavailable else: img = img.resize((new_w, new_h), Image.ANTIALIAS) oriented = 'unknown' print('\nThe orientation for photo is {}.'.format(oriented)) if geo_tag: # Get geo-tagging info the_location = get_location(asset.location) if the_location: print('\nGeo-tagging photo...') the_time = the_time.replace('.', ':') the_location = '{} @ {} in {}'.format(the_date, the_time, the_location) ''' Get degrees needed to rotate photo for it's proper orientation. See www.impulsesdventue.com/photoexif orientation.html for more details. ''' degrees = get_degrees_to_rotate(orientation) # Rotate photo so tag is on bottom of photo regardless of orientation img = img.rotate(degrees).convert('RGBA') # Tuple w, h = img.size draw = ImageDraw.Draw(img) # Font for geo-tag will be 28 pt Helvetica fontsize = 28 font = ImageFont.truetype('Helvetica', fontsize) y = h - 35 # Put red text @ bottom left of photo draw.text((25, y), the_location, (255, 0, 0), font=font) # Rotate photo back to original position img = img.rotate(-degrees) else: print('\nNo gps metadata for photo.') no_gps.append(new_filename) else: print('\nPhoto will not be geo_tagged. Flag is set to false.') # Save new image img.save('without_meta.jpg') if keep_meta: ''' Copy metadata from 'with_meta.jpg' to 'without_meta.jpg and call this reprocessed image file 'meta_resized.jpg'. ''' copy_meta('with_meta.jpg', 'without_meta.jpg', new_w, new_h) jpg_file = 'meta_resized.jpg' else: # Use resized photo that has not had metadata added back into it jpg_file = 'without_meta.jpg' print('\nUploading photo to Dropbox...') ''' Upload resized photo with or without original metadata to Dropbox...use 'with' statement to open file so file closes automatically at end of 'with'. ''' with open(jpg_file, 'r') as img: response = drop_client.put_file(new_filename, img) # Give Dropbox server time to process...pause time is user defined. time.sleep(upload_pause) response = jpg_file = the_location = img = the_date = the_time = the_year = new_filename = old_filename = '' print('\nUpload successful.') finish = time.clock() print('{} photos processed in {}'.format( count, timer(start, finish, count, upload_pause))) if no_exif: print( '\nPhotos with no DateTimeOriginal tag in their metadata and will need categorizing manually:' ) print('\n'.join(no_exif)) if no_resize: print( '\nPhotos that did not get resized because either you chose not to resize, or they were smaller than the minumum size of 1600x1200:' ) print('\n'.join(no_resize)) if no_gps: print( '\nPhotos that did not get geo-tagged because there was no gps info in the photo\'s metadata:' ) print('\n'.join(no_gps)) # Re-enable idle timer console.set_idle_timer_disabled(False)
def main(): console.clear() try: ''' Here we are picking photos from the camera roll which, in Pythonista, allows us access to extra media data in photo's metafile. Because raw data is set to true, the image is a string representing the image object, not the object itself. ''' choose = photos.pick_image(show_albums = True, multi = True, original = True, raw_data = True, include_metadata = True) except: sys.exit('No photos choosen...exiting.') minumum_size = True resizePercent = 0 # Pick a scaling percent for selected photo(s) try: ans = console.alert('Reduce the selected photo(s) by what percent of their original size?', '', '50% with a 1600x1200 minumum', 'Custom without a minumum', 'None') if ans == 1: scale = float(50) / 100 elif ans == 2: msg = 'Enter desired reduction percent for selected photo(s): ' scale = float(console.input_alert(msg,'Numbers only','35')) / 100 # No minumums here...reduce all photos no matter what their size. minumum_size = False elif ans == 3: # Don't resize scale = 1 except (IndexError, ValueError): sys.exit('No valid entry...Process cancelled.') start = time.clock() # Create an instance of Dropbox client drop_client = get_client() ans = '' dest_dir = '/Photos' ''' When metadata is returned with photo the photo is a tuple, with one the image, and the other the media metadata. ''' for count,photo in enumerate(choose): print '\nProcessing photo...' # Raw data string and Metadata img, meta = photo #print meta #sys.exit() # Get date & time photo was taken theYear, theDate, theTime = GetDateTime(meta) # Formulate file name for photo old_filename = str(meta.get('filename')) if theDate: folder_name = '{}/{}'.format(theYear, theDate) new_filename = '{}.{}'.format(theTime, old_filename) else: folder_name = 'NoDates' new_filename = old_filename new_filename = '{}/{}/{}'.format(dest_dir, folder_name, new_filename) if folder_name == 'NoDates': no_exif.append(new_filename) # Get dimensions for resize based on size of original photo new_w, new_h, w, h, resizeOk = GetDimensions(meta, scale, new_filename, minumum_size) fmt = '\nOriginal Name: {}\nNew Name: {}' print fmt.format(old_filename, new_filename) fmt = '\nOriginal Size: {}x{}\nNew Size: {}x{}' print fmt.format(w, h, new_w, new_h) addToMsg = 'with' if keepMeta else 'without' if resizeOk: msg = '\nCreating resized copy of original photo {} the metadata from original.' else: msg = '\nCreating copy of original photo {} the metadata from original.' print msg.format(addToMsg) # Write string image of original photo to Pythonista script dir with open('with_meta.jpg', 'wb') as out_file: out_file.write(img) # Open image, resize it, and write new image to scripts dir img = Image.open('with_meta.jpg') if geoTag: # Get geo-tagging info theLocation = GetLocation(meta) if theLocation: print '\nGeo-tagging photo...' # Find out if photo is oriented for landscape or portrait orientation = meta.get('Orientation') # ccc: add a default? ''' Get degrees needed to rotate photo for it's proper orientation. See www.impulsesdventue.com/photo exif-orientation.html for more details. ''' degrees, oriented = GetDegreesToRotate(orientation) print '\nThe orientation for photo is {}.'.format(oriented) theTime = theTime.replace('.',':') theLocation = '{} @ {} in {}'.format(theDate, theTime, theLocation) # Rotate so tag is on bottom of photo regardless of orientation img = img.rotate(degrees).convert('RGBA') # Tuple w, h= img.size draw = ImageDraw.Draw(img) ''' Font for geo-tag of smaller photos will be 28 point Helvetica, while the rest will be 56 point. ''' fontsize = 56 if w > 1200 else 28 font = ImageFont.truetype('Helvetica', fontsize) # Put red text @ bottom left of photo draw.text((25, h-75), theLocation,(255, 0, 0), font = font) # Rotate back to original position img = img.rotate(-degrees) else: print '\nNo gps metadata for photo.' no_gps.append(new_filename) else: print '\nPhoto will not be geotagged. Flag is set to false.' meta = '' resized = img.resize((new_w, new_h),Image.ANTIALIAS) resized.save('without_meta.jpg') resized = '' if keepMeta: ''' Copy metadata from 'with_meta.jpg' to 'without_meta.jpg and call this reprocessed image file 'meta_resized.jpg'. ''' CopyMeta('with_meta.jpg', 'without_meta.jpg', new_w, new_h) jpgFile = 'meta_resized.jpg' else: # Use resized photo that has not had metadata added back into it jpgFile = 'without_meta.jpg' print '\nUploading photo to Dropbox...' ''' Upload resized photo with or without original metadata to Dropbox...use with statement to open file so file closes automatically at end of with. ''' with open(jpgFile,'r') as img: response = drop_client.put_file(new_filename, img) # Give Dropbox server time to process time.sleep(5) response = jpgFile = theLocation = img = theDate = theTime = theYear = new_filename = old_filename = '' print '\nUpload successful.' finish = time.clock() print '{} photos processed in {}'.format(count + 1, Timer(start, finish, count + 1)) if no_exif: print '\nPhotos with no DateTimeOriginal tag in their metadata and will need categorizing manually:' print '\n'.join(no_exif) if no_resize: print '\nPhotos that did not get resized because either you chose not to resize, or they were smaller than the minumum size of 1600x1200:' print '\n'.join(no_resize) if no_gps: print '\nPhotos that did not get geo-tagged because there was no gps info in the photo\'s metadata:' print '\n'.join(no_gps)
def main(assets, keep_meta, geo_tag, dest_dir, size): minumum_size = True resizePercent = 0 # This is time in seconds to allow for dropbox to process each photo. Older iOS devices will require more time. upload_pause = 3 if size == 'fifty': scale = float(50) / 100 elif size == 'custom': scale = v2['scale_text'] # Numbers only for textbox entries scale.keyboard_type = ui.KEYBOARD_NUMBER_PAD # Display ui locked in portrait orientation and wait till user selects something from it. v2.present(orientations = ['portrait']) v2.wait_modal() scale = float(scale.text) / 100 # No minumums here...reduce all photos no matter what their size. minumum_size = False # If user pressed the close button then cancel script if not ok: sys.exit('Script Cancelled') elif size == 'none': scale = 1 # Disable idle timer to cover working with a large batch of photos console.set_idle_timer_disabled(True) start = time.clock() # Create an instance of Dropbox client drop_client = get_client() for asset in assets: print '\nProcessing photo...' # Get date & time photo was taken the_year, the_date, the_time = get_date_time(asset.creation_date) file_name = '' # Formulate file name for photo old_filename = str(ObjCInstance(asset).filename()) if the_date: folder_name = '{}/{}'.format(the_year, the_date) new_filename = '{}.{}'.format(the_time, old_filename) else: folder_name = 'NoDates' new_filename = old_filename keep_meta = False new_filename = '{}/{}/{}'.format(dest_dir, folder_name, new_filename) if folder_name == 'NoDates': no_exif.append(new_filename) file_name = '{}.{}'.format(the_time, file_name) # Get dimensions for resize based on size of original photo new_w, new_h, w, h, resizeOk = get_dimensions(asset, scale, new_filename, minumum_size) fmt = '\nOriginal Name: {}\nNew Name: {}' print fmt.format(old_filename, new_filename) fmt = '\nOriginal Size: {}x{}\nNew Size: {}x{}' print fmt.format(w, h, new_w, new_h) addToMsg = 'with' if keep_meta else 'without' if resizeOk: msg = '\nCreating resized copy of original photo {} the metadata from original.' else: msg = '\nCreating copy of original photo {} the metadata from original.' print msg.format(addToMsg) # Fetch asset's image data & return it as a io.BytesIO object and then as a byte string img = asset.get_image_data(original = False).getvalue() # Write string image of original photo to Pythonista script dir with open('with_meta.jpg', 'wb') as out_file: out_file.write(img) # Open image, resize it, and write new image to scripts dir img = Image.open('with_meta.jpg') # Retrieve a number that represents the orientation of photo orientation = str(ObjCInstance(asset).orientation()) # Landscape if orientation == '1' or orientation == '3': img = img.resize((new_w, new_h),Image.ANTIALIAS) # Occasionally metadata will say the photo orientation is 1 even though the width is less than the height of photo. if new_w < new_h: oriented = 'portrait' else: oriented = 'landscape' # Portrait elif orientation == '6' or orientation == '8': img = img.resize((new_h, new_w), Image.ANTIALIAS) oriented = 'portrait' # Unavailable else: img = img.resize((new_w, new_h),Image.ANTIALIAS) oriented = 'unknown' print '\nThe orientation for photo is {}.'.format(oriented) if geo_tag: # Get geo-tagging info the_location = get_location(asset.location) if the_location: print '\nGeo-tagging photo...' the_time = the_time.replace('.',':') the_location = '{} @ {} in {}'.format(the_date, the_time, the_location) ''' Get degrees needed to rotate photo for it's proper orientation. See www.impulsesdventue.com/photoexif orientation.html for more details. ''' degrees = get_degrees_to_rotate(orientation) # Rotate photo so tag is on bottom of photo regardless of orientation img = img.rotate(degrees).convert('RGBA') # Tuple w, h = img.size draw = ImageDraw.Draw(img) # Font for geo-tag will be 28 pt Helvetica fontsize = 28 font = ImageFont.truetype('Helvetica', fontsize) y = h - 35 # Put red text @ bottom left of photo draw.text((25, y), the_location,(255, 0, 0), font = font) # Rotate photo back to original position img = img.rotate(-degrees) else: print '\nNo gps metadata for photo.' no_gps.append(new_filename) else: print '\nPhoto will not be geo_tagged. Flag is set to false.' # Save new image img.save('without_meta.jpg') if keep_meta: ''' Copy metadata from 'with_meta.jpg' to 'without_meta.jpg and call this reprocessed image file 'meta_resized.jpg'. ''' copy_meta('with_meta.jpg', 'without_meta.jpg', new_w, new_h) jpg_file = 'meta_resized.jpg' else: # Use resized photo that has not had metadata added back into it jpg_file = 'without_meta.jpg' print '\nUploading photo to Dropbox...' ''' Upload resized photo with or without original metadata to Dropbox...use 'with' statement to open file so file closes automatically at end of 'with'. ''' with open(jpg_file,'r') as img: response = drop_client.put_file(new_filename, img) # Give Dropbox server time to process...pause time is user defined. time.sleep(upload_pause) response = jpg_file = the_location = img = the_date = the_time = the_year = new_filename = old_filename = '' print '\nUpload successful.' finish = time.clock() print '{} photos processed in {}'.format(count, timer(start, finish, count, upload_pause)) if no_exif: print '\nPhotos with no DateTimeOriginal tag in their metadata and will need categorizing manually:' print '\n'.join(no_exif) if no_resize: print '\nPhotos that did not get resized because either you chose not to resize, or they were smaller than the minumum size of 1600x1200:' print '\n'.join(no_resize) if no_gps: print '\nPhotos that did not get geo-tagged because there was no gps info in the photo\'s metadata:' print '\n'.join(no_gps) # Re-enable idle timer console.set_idle_timer_disabled(False)
def main(choose, keepMeta, geoTag, dest_dir, size): minumum_size = True resizePercent = 0 if size == 'fifty': scale = float(50) / 100 elif size == 'custom': msg = 'Enter desired reduction percent for selected photo(s): ' try: scale = float(console.input_alert(msg,'Numbers only','35')) / 100 # No minumums here...reduce all photos no matter what their size. minumum_size = False except KeyboardInterrupt: sys.exit('Script cancelled.') elif size == 'none': scale = 1 #john = dialogs.form_dialog(title = 'Photo Options',fields=[{'type':'switch','title':'Geotag'}, {'type':'switch','title':'Keep Metadata'}]) # Disable idle timer to cover working with a large batch of photos console.set_idle_timer_disabled(True) start = time.clock() # Create an instance of Dropbox client drop_client = get_client() ans = '' ''' When metadata is returned with photo the photo is a tuple, with one the image, and the other the media metadata. ''' for count, photo in enumerate(choose): # Raw data string and Metadata img, meta = photo #print meta #sys.exit() print('\nProcessing photo...') # Get date & time photo was taken theYear, theDate, theTime = GetDateTime(meta) # Formulate file name for photo old_filename = str(meta.get('filename')) if theDate: folder_name = '{}/{}'.format(theYear, theDate) new_filename = '{}.{}'.format(theTime, old_filename) else: folder_name = 'NoDates' new_filename = old_filename keepMeta = False new_filename = '{}/{}/{}'.format(dest_dir, folder_name, new_filename) if folder_name == 'NoDates': no_exif.append(new_filename) # Get dimensions for resize based on size of original photo new_w, new_h, w, h, resizeOk = GetDimensions(meta, scale, new_filename, minumum_size) fmt = '\nOriginal Name: {}\nNew Name: {}' print(fmt.format(old_filename, new_filename)) fmt = '\nOriginal Size: {}x{}\nNew Size: {}x{}' print(fmt.format(w, h, new_w, new_h)) addToMsg = 'with' if keepMeta else 'without' if resizeOk: msg = '\nCreating resized copy of original photo {} the metadata from original.' else: msg = '\nCreating copy of original photo {} the metadata from original.' print(msg.format(addToMsg)) # Write string image of original photo to Pythonista script dir with open('with_meta.jpg', 'wb') as out_file: out_file.write(img) # Open image, resize it, and write new image to scripts dir img = Image.open('with_meta.jpg') img = img.resize((new_w, new_h),Image.ANTIALIAS) if geoTag: # Get geo-tagging info theLocation = GetLocation(meta) if theLocation: print('\nGeo-tagging photo...') # Find out if photo is oriented for landscape or portrait orientation = meta.get('Orientation') # ccc: add a default? ''' Get degrees needed to rotate photo for it's proper orientation. See www.impulsesdventue.com/photo exif-orientation.html for more details. ''' degrees, oriented = GetDegreesToRotate(orientation) print('\nThe orientation for photo is {}.'.format(oriented)) theTime = theTime.replace('.',':') theLocation = '{} @ {} in {}'.format(theDate, theTime, theLocation) # Rotate so tag is on bottom of photo regardless of orientation img = img.rotate(degrees).convert('RGBA') # Tuple w, h = img.size draw = ImageDraw.Draw(img) # Font for geo-tag will be 28 pt Helvetica #fontsize = 56 if w > 1300 else 28 fontsize = 28 font = ImageFont.truetype('Helvetica', fontsize) # Determine y axis for geotag #if h < 1000: #y = h - 35 #else: #y = h - 75 y = h - 35 # Put red text @ bottom left of photo draw.text((25, y), theLocation,(255, 0, 0), font = font) # Rotate back to original position img = img.rotate(-degrees) else: print('\nNo gps metadata for photo.') no_gps.append(new_filename) else: print('\nPhoto will not be geotagged. Flag is set to false.') meta = '' #img = img.resize((new_w, new_h),Image.ANTIALIAS) # Save new image img.save('without_meta.jpg') if keepMeta: ''' Copy metadata from 'with_meta.jpg' to 'without_meta.jpg and call this reprocessed image file 'meta_resized.jpg'. ''' CopyMeta('with_meta.jpg', 'without_meta.jpg', new_w, new_h) jpgFile = 'meta_resized.jpg' else: # Use resized photo that has not had metadata added back into it jpgFile = 'without_meta.jpg' print('\nUploading photo to Dropbox...') ''' Upload resized photo with or without original metadata to Dropbox...use with statement to open file so file closes automatically at end of with. ''' with open(jpgFile,'r') as img: response = drop_client.put_file(new_filename, img) # Give Dropbox server time to process time.sleep(5) response = jpgFile = theLocation = img = theDate = theTime = theYear = new_filename = old_filename = '' print('\nUpload successful.') finish = time.clock() print('{} photos processed in {}'.format(count + 1, Timer(start, finish, count + 1))) if no_exif: print('\nPhotos with no DateTimeOriginal tag in their metadata and will need categorizing manually:') print('\n'.join(no_exif)) if no_resize: print('\nPhotos that did not get resized because either you chose not to resize, or they were smaller than the minumum size of 1600x1200:') print('\n'.join(no_resize)) if no_gps: print('\nPhotos that did not get geo-tagged because there was no gps info in the photo\'s metadata:') print('\n'.join(no_gps))