def read(self): """Load exif data from disk.""" self.exif = ImageMetadata(self.filename) self.timestamp = None self.altitude = None self.latitude = None self.longitude = None self.timezone = None self.manual = False try: self.exif.read() except TypeError: raise IOError self.camera = get_camera(self) # Try to get a thumbnail. try: self.thumb = GdkPixbuf.Pixbuf.new_from_file_at_size( self.filename, self.thm_size, self.thm_size) except GObject.GError: if len(self.exif.previews) > 0: data = self.exif.previews[-1].data elif len(self.exif.exif_thumbnail.data) > 0: data = self.exif.exif_thumbnail.data else: raise IOError self.thumb = GdkPixbuf.Pixbuf.new_from_stream_at_scale( Gio.MemoryInputStream.new_from_data(data, None), self.thm_size, self.thm_size, True, None) # If we're reloading, then hide the label and clear the ListStore, # but if we're loading afresh then we'll need a new iter... if self.label is not None: self.label.hide() if self.thm_size < 250: if self.iter is None: self.iter = self.liststore.append() self.liststore.set_row(self.iter, [self.filename, self.long_summary(), self.thumb, self.timestamp]) self.calculate_timestamp() try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value] ) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value] ) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass
def read(self): """Discard all state and (re)initialize from disk.""" self.exif = fetch_exif(self.filename) self.manual = False self.modified_timeout = None self.latitude = 0.0 self.longitude = 0.0 self.altitude = 0.0 self.timestamp = 0 self.names = (None, None, None) self.geotimezone = '' try: self.orig_time = self.exif[ 'Exif.Photo.DateTimeOriginal'].value.timetuple() except KeyError: pass try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value] ) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value] ) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass modified.discard(self) self.calculate_timestamp() if self.iter is None: self.iter = Widgets.loaded_photos.append() Widgets.loaded_photos.set_row(self.iter, [self.filename, str(self), self.thumb, self.timestamp]) # Get the camera info self.camera_info = {'Make': '', 'Model': ''} keys = ['Exif.Image.' + key for key in self.camera_info.keys() + ['CameraSerialNumber']] + ['Exif.Photo.BodySerialNumber'] for key in keys: try: self.camera_info.update( {key.split('.')[-1]: self.exif[key].value}) except KeyError: pass
def read(self): """Load exif data from disk.""" self.exif = ImageMetadata(self.filename) self.timestamp = None self.altitude = None self.latitude = None self.longitude = None self.timezone = None self.manual = False try: self.exif.read() except TypeError: raise IOError Camera(self.exif) # Try to get a thumbnail. try: self.thumb = GdkPixbuf.Pixbuf.new_from_file_at_size( self.filename, self.thm_size, self.thm_size) except GObject.GError: if len(self.exif.previews) > 0: data = self.exif.previews[-1].data elif len(self.exif.exif_thumbnail.data) > 0: data = self.exif.exif_thumbnail.data else: raise IOError self.thumb = GdkPixbuf.Pixbuf.new_from_stream_at_scale( Gio.MemoryInputStream.new_from_data(data, None), self.thm_size, self.thm_size, True, None) self.calculate_timestamp() try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value] ) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value] ) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass
def read(self): """Load exif data from disk.""" self.exif = ImageMetadata(self.filename) self.timestamp = None self.altitude = None self.latitude = None self.longitude = None self.timezone = None self.manual = False try: self.exif.read() except TypeError: raise IOError Camera(self.exif) # Try to get a thumbnail. try: self.thumb = GdkPixbuf.Pixbuf.new_from_file_at_size( self.filename, self.thm_size, self.thm_size) except GObject.GError: if len(self.exif.previews) > 0: data = self.exif.previews[-1].data elif len(self.exif.exif_thumbnail.data) > 0: data = self.exif.exif_thumbnail.data else: raise IOError self.thumb = GdkPixbuf.Pixbuf.new_from_stream_at_scale( Gio.MemoryInputStream.new_from_data(data, None), self.thm_size, self.thm_size, True, None) self.calculate_timestamp() try: self.latitude = dms_to_decimal( *self.exif[GPS + 'Latitude'].value + [self.exif[GPS + 'LatitudeRef'].value]) self.longitude = dms_to_decimal( *self.exif[GPS + 'Longitude'].value + [self.exif[GPS + 'LongitudeRef'].value]) except KeyError: pass try: self.altitude = float(self.exif[GPS + 'Altitude'].value) if int(self.exif[GPS + 'AltitudeRef'].value) > 0: self.altitude *= -1 except KeyError: pass
def test_gps_math(self): """Test coordinate conversion functions.""" rats_to_fracs = lambda rats: [Fraction(rat.to_float()) for rat in rats] # Really important that this method is bulletproof self.assertFalse(valid_coords(None, None)) self.assertFalse(valid_coords('', '')) self.assertFalse(valid_coords(True, True)) self.assertFalse(valid_coords(False, False)) self.assertFalse(valid_coords(45, 270)) self.assertFalse(valid_coords(100, 50)) self.assertFalse(valid_coords([], 50)) self.assertFalse(valid_coords(45, {'grunt':42})) self.assertFalse(valid_coords(self, 50)) self.assertFalse(valid_coords(45, valid_coords)) self.assertFalse(valid_coords("ya", "dun goofed")) # St. John's broke the math. I'm not sure why. # Seriously. Revert commit 362dd6eb and watch this explode. stjohns = Coordinates() stjohns.latitude = 47.56494 stjohns.longitude = -52.70931 stjohns.lookup_geoname() self.assertEqual(stjohns.city, "St. John's") # Pick 100 random coordinates on the globe, convert them from decimal # to sexagesimal and then back, and ensure that they are always equal. for _ in range(100): # Oh, and test altitudes too altitude = round(random_coord(1000), 6) fraction = float_to_rational(altitude) self.assertAlmostEqual( abs(altitude), fraction.numerator / fraction.denominator, 3 ) decimal_lat = round(random_coord(80), 6) decimal_lon = round(random_coord(180), 6) self.assertTrue(valid_coords(decimal_lat, decimal_lon)) dms_lat = decimal_to_dms(decimal_lat) dms_lon = decimal_to_dms(decimal_lon) self.assertEqual(len(dms_lat), 3) self.assertEqual( dms_lat[0].numerator, floor(abs(decimal_lat)) ) self.assertEqual(len(dms_lon), 3) self.assertEqual( dms_lon[0].numerator, floor(abs(decimal_lon)) ) self.assertAlmostEqual( decimal_lat, dms_to_decimal(*rats_to_fracs(dms_lat) + ['N' if decimal_lat >= 0 else 'S']), 10 # equal to 10 places ) self.assertAlmostEqual( decimal_lon, dms_to_decimal(*rats_to_fracs(dms_lon) + ['E' if decimal_lon >= 0 else 'W']), 10 # equal to 10 places )
def test_gps_math(self): """Test coordinate conversion functions.""" rats_to_fracs = lambda rats: [Fraction(rat.to_float()) for rat in rats] # Really important that this method is bulletproof self.assertFalse(valid_coords(None, None)) self.assertFalse(valid_coords('', '')) self.assertFalse(valid_coords(True, True)) self.assertFalse(valid_coords(False, False)) self.assertFalse(valid_coords(45, 270)) self.assertFalse(valid_coords(100, 50)) self.assertFalse(valid_coords([], 50)) self.assertFalse(valid_coords(45, {'grunt':42})) self.assertFalse(valid_coords(self, 50)) self.assertFalse(valid_coords(45, valid_coords)) self.assertFalse(valid_coords("ya", "dun goofed")) # St. John's broke the math. I'm not sure why. # Seriously. Revert commit 362dd6eb and watch this explode. stjohns = Coordinates() stjohns.latitude = 47.56494 stjohns.longitude = -52.70931 stjohns.lookup_geoname() self.assertEqual(stjohns.city, "St. John's") # Pick 100 random coordinates on the globe, convert them from decimal # to sexagesimal and then back, and ensure that they are always equal. for i in range(100): # Oh, and test altitudes too altitude = round(random_coord(1000), 6) fraction = float_to_rational(altitude) self.assertAlmostEqual( abs(altitude), fraction.numerator / fraction.denominator, 3 ) decimal_lat = round(random_coord(80), 6) decimal_lon = round(random_coord(180), 6) self.assertTrue(valid_coords(decimal_lat, decimal_lon)) dms_lat = decimal_to_dms(decimal_lat) dms_lon = decimal_to_dms(decimal_lon) self.assertEqual(len(dms_lat), 3) self.assertEqual( dms_lat[0].numerator, floor(abs(decimal_lat)) ) self.assertEqual(len(dms_lon), 3) self.assertEqual( dms_lon[0].numerator, floor(abs(decimal_lon)) ) self.assertAlmostEqual( decimal_lat, dms_to_decimal(*rats_to_fracs(dms_lat) + ['N' if decimal_lat >= 0 else 'S']), 10 # equal to 10 places ) self.assertAlmostEqual( decimal_lon, dms_to_decimal(*rats_to_fracs(dms_lon) + ['E' if decimal_lon >= 0 else 'W']), 10 # equal to 10 places )