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'))
Beispiel #2
0
    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)
Beispiel #5
0
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)