def test_degree_to_dms(self): d, m, s = MetaHandler.degree_to_dms(-87.728055) self.assertEquals(d, -87) self.assertEquals(m, 43) self.assertEquals(s, Decimal('41.00')) d, m, s = MetaHandler.degree_to_dms(87.728055, prec=5) self.assertEquals(d, 87) self.assertEquals(m, 43) self.assertEquals(s, Decimal('40.99800'))
def __init__(self, output_dir, search_dirs=None): self.output_dir = output_dir self.search_dirs = search_dirs if self.search_dirs is None: self.search_dirs = [] self.zapi = ZooomrApi(API_KEY, SHARED_SECRET, 'write') self.meta_handler = MetaHandler()
def setUp(self): self.mh = MetaHandler()
class TestMetaHandler(unittest.TestCase): def setUp(self): self.mh = MetaHandler() def tearDown(self): del self.mh def test_store_metadata(self): metadata = { 'title': 'Test title', 'description': 'describing the image', 'tags': ['One', 'two', 'Seven'], 'lat': 39.94119033054447, 'lng': -75.1519775390625, 'license': 'All Rights Reserved', 'isfamily': 0, 'date_posted': datetime.datetime(2011, 4, 12, 16, 23, 4) } ## ensure it doesnt break with format that does not ## support EXIF/XMP/IPTC filename = '/tmp/image.gif' Image.new("RGB", (200, 400)).save(filename) self.mh.store_metadata(filename, metadata) filename = '/tmp/image.jpg' Image.new("RGB", (200, 400)).save(filename) ## check empty metadata dictionary self.mh.store_metadata(filename, {}) photo_meta = pyexiv2.ImageMetadata(filename) photo_meta.read() self.assertEquals(photo_meta.keys(), []) self.mh.store_metadata(filename, metadata) def test_degree_to_dms(self): d, m, s = MetaHandler.degree_to_dms(-87.728055) self.assertEquals(d, -87) self.assertEquals(m, 43) self.assertEquals(s, Decimal('41.00')) d, m, s = MetaHandler.degree_to_dms(87.728055, prec=5) self.assertEquals(d, 87) self.assertEquals(m, 43) self.assertEquals(s, Decimal('40.99800')) def test_convert_degrees_to_dms(self): expected_dict = { 'lat': (39, 56, Decimal('28.29'), 'N'), 'lng': (75, 9, Decimal('7.12'), 'W') } dms = self.mh.convert_degrees_to_dms( 39.94119033054447, -75.1519775390625 ) self.assertEquals(expected_dict, dms) expected_dict = { 'lat': (22, 52, Decimal('58.22'), 'S'), 'lng': (43, 13, Decimal('52.32'), 'W') } dms = self.mh.convert_degrees_to_dms( -22.882838743256254, -43.231201171875 ) self.assertEquals(expected_dict, dms)
class ZooomrTouchr(object): def __init__(self, output_dir, search_dirs=None): self.output_dir = output_dir self.search_dirs = search_dirs if self.search_dirs is None: self.search_dirs = [] self.zapi = ZooomrApi(API_KEY, SHARED_SECRET, 'write') self.meta_handler = MetaHandler() def find_local_photo(self, paths, metadata): if 'date_created' not in metadata: return [] files_found = [] for path in paths: date = metadata['date_created'] date_str = '%d/%02d/%02d' % (date.year, date.month, date.day) path = os.path.join(path, date_str) for dirpath, dirnames, filenames in os.walk(path): for filename in filenames: filepath = os.path.join(dirpath, filename) filedate = self.meta_handler.get_datetime_created(filepath) if date == filedate: logger.debug('found matching local photo: %s', filename) files_found.append((dirpath, filename)) ## sort images by modified date return sorted(files_found, cmp=self.cmp_file_mtime) def download_metadata(self, xml): metadata = {} photo_xml = xml.find('photo') metadata['id'] = photo_xml.get('id') for name in ['title', 'description']: metadata[name] = photo_xml.find(name).text metadata['license'] = LICENSES[int(photo_xml.get('license', 0))] timestamp = photo_xml.find('dates').get('posted') metadata['date_posted'] = datetime.datetime.utcfromtimestamp(float(timestamp)) ##FIXME: What about other machine tags?? metadata['tags'] = [] for label in photo_xml.findall('tags/tag'): ## tags/keywords: rc="labels" rda="Penticton" rdi="penticton" if label.get('rc') == 'labels': metadata['tags'].append(label.get('rda')) ## rc="camera" rda="2011:08:29 00:26:14Z" rdi="createdate" elif label.get('rc') == 'camera': if label.get('rdi') == 'createdate': date_str = label.get('rda')[:19] metadata['date_created'] = datetime.datetime.strptime( date_str, "%Y:%m:%d %H:%M:%S" ) elif label.get('rdi') == 'datetime': if 'date_created' not in metadata: metadata['date_created'] = datetime.datetime.strptime( label.get('rda')[:19].replace(' ', ':'), "%Y:%m:%d:%H:%M:%S" ) elif label.get('rdi') == 'imageheight': metadata['height'] = int(label.get('rda')) elif label.get('rdi') == 'imagewidth': metadata['width'] = int(label.get('rda')) ## extract visibility Zooomr settings for key in ['isfamily', 'isfriend', 'ispublic']: metadata[key] = photo_xml.find('visibility').get(key, 0) ##TODO: people & notes urls = {} for url_xml in photo_xml.findall('urls/url'): urls[url_xml.get('type')] = url_xml.text ## get geo info metadata.update( self.zapi.get_geo_location(urls['photopage']) ) return metadata def download_photo(self, photo_id): try: resp = self.zapi.photos_getInfo(photo_id=photo_id) except ZooomrError as inst: logger.error(inst.strerror) return None photo_url = self.zapi.get_photo_url(resp.find('photo'), Size.ORIGINAL) filename = "%s.%s" % ( resp.find('photo').get('id'), resp.find('photo').get('originalformat') ) path = os.path.join(self.output_dir, filename) metadata = self.download_metadata(resp) if not os.path.exists(path): logger.debug('start retrieving original photo') try: photo_data = urllib2.urlopen(photo_url, timeout=10) with open(path, 'wb') as photo_file: photo_file.write(photo_data.read()) except urllib2.URLError: logger.debug('cannot download image, search in local dir') ## search in local directory matching_files = self.find_local_photo(self.search_dirs, metadata) if len(matching_files) == 0: logger.error( 'could not find or download file for ID #%s', resp.find('photo').get('id') ) else: origin = os.path.join(matching_files[0][0], matching_files[0][1]) shutil.copy(origin, path) shutil.copystat(origin, path) return filename, metadata @staticmethod def cmp_file_mtime(fa, fb): fa_date = os.path.getmtime(os.path.join(*fa)) fb_date = os.path.getmtime(os.path.join(*fb)) return cmp(fb_date, fa_date)