示例#1
0
    def test_no_app1_segment(self):
        """Verify behavior of an image without an APP1 segment marker.

        Assert the ``has_exif`` attribute is false. Verify non-EXIF ``dir()`` list contents. Then,
        check the ``get_file()`` hexadecimal.

        """
        image_path = os.path.join(os.path.dirname(__file__), "no_app1.png")
        with open(image_path, "rb") as image_file:
            my_image = Image(image_file)

        self.assertFalse(my_image.has_exif)

        self.assertEqual(
            str(dir(my_image)),
            Baseline("""
            ['_segments', 'delete', 'delete_all', 'get', 'get_all', 'get_file', 'get_thumbnail', 'has_exif', 'list_all']
            """),
        )

        with pytest.raises(RuntimeError,
                           match="image does not contain thumbnail"):
            my_image.get_thumbnail()

        self.assertEqual(
            "\n".join(textwrap.wrap(str(my_image.get_file()), 90)),
            NO_APP1_PNG)
示例#2
0
def set_description(filename, description):
    with open(filename, 'rb') as img:
        imgobj = Image(img)

    print(imgobj.list_all())
    imgobj.image_description = description
    print(imgobj.list_all())
    with open(filename, 'wb') as writeimg:
        writeimg.write(imgobj.get_file())
示例#3
0
    def create_exif(self, img, coords):
        with open(img, 'rb') as file:
            file = Exif(file)

            file.gps_latitude = coords['lat']
            file.gps_longitude = coords['lon']

            with open(img, 'wb') as new_image_file:
                new_image_file.write(file.get_file())
示例#4
0
def test_get_file():
    """Verify that an image is writable to a file after modifying its EXIF metadata.

    Assert the produced file is equivalent to a known baseline.

    """
    image = Image(os.path.join(os.path.dirname(__file__), "noise.jpg"))
    image.software = "Python"

    file_hex = binascii.hexlify(image.get_file()).decode("utf-8")
    assert "\n".join(textwrap.wrap(file_hex,
                                   90)) == MODIFIED_NOISE_FILE_HEX_BASELINE
示例#5
0
def write_new_date(filename: Path, new_date: datetime):
    logging.info('update file ' + str(filename) + ' with ' + str(new_date))
    with open(filename, 'rb') as image_file:
        image = Image(image_file)

    new_date_str = new_date.strftime(DATETIME_STR_FORMAT)

    image.datetime_original = new_date_str
    image.datetime = new_date_str

    with open(filename, 'wb') as new_image_file:
        new_image_file.write(image.get_file())
示例#6
0
def main():
    # Open JSON file
    # Parser JSON

    headers = {"Content-type": "application/x-www-form-urlencoded"}
    fd = open("memories_history.json")
    memories = json.load(fd)
    for x in memories["Saved Media"]:
        if x["Media Type"] == "PHOTO":
            url = x["Download Link"]
            split_url = url.split("?")
            r = requests.post(
                split_url[0],
                headers=headers,
                data=split_url[1],
            )
            if r.status_code == 200:
                # 200 means that we got HTTP success
                aws_resp = requests.get(r.text)
                aws_url = r.text.split("?")
                print(aws_url[0])
                last_occur = aws_url[0].rfind("/", 0) + 1
                print(last_occur)
                filename = aws_url[0][last_occur:]
                i = Image.open(BytesIO(aws_resp.content))
                i = i.save(filename, quality="keep")
                time.sleep(1)
                # Prepare the datetime info
                date_datetime = datetime.strptime(x["Date"],
                                                  "%Y-%m-%d %H:%M:%S %Z")
                with open(filename, "rb") as image_file_thing:

                    image_file = EImage(image_file_thing)
                    image_file.datetime_original = date_datetime.strftime(
                        DATETIME_STR_FORMAT)
                    image_file.datetime_scanned = date_datetime.strftime(
                        DATETIME_STR_FORMAT)
                    image_file.datetime_digitized = date_datetime.strftime(
                        DATETIME_STR_FORMAT)

                    with open("{}_akk.jpg".format(filename),
                              "wb") as new_image_file:
                        new_image_file.write(image_file.get_file())

            else:
                print(r.status_code)
                exit()

    fd.close()
示例#7
0
    def test_no_app1_segment(self):
        """Verify behavior of an image without an APP1 segment marker.

        Assert the ``has_exif`` attribute is false. Verify non-EXIF ``dir()`` list contents. Then,
        check the ``get_file()`` hexadecimal.

        """
        image_path = os.path.join(os.path.dirname(__file__), 'no_app1.png')
        with open(image_path, 'rb') as image_file:
            my_image = Image(image_file)

        self.assertFalse(my_image.has_exif)

        self.assertEqual(str(dir(my_image)), Baseline("""
            ['_segments', 'get', 'get_file', 'has_exif']
            """))

        self.assertEqual('\n'.join(textwrap.wrap(str(my_image.get_file()), 90)), NO_APP1_PNG)
示例#8
0
def clear_img(filename):
    file_mod = filename.split('.')
    file_mod = file_mod[0]+_cleaned+'.'+file_mod[1]
   
    with open(filename, 'rb') as image_file:
        my_image = Image(image_file)
    
    
    for element in dir(my_image):
        try:
            print(f"{element}:  {my_image[element]}")
            del my_image[element]
        except:
            print(f"{element} unknown")
    
    with open(file_mod, 'wb') as new_image_file:
    	new_image_file.write(my_image.get_file())
    print(f'File {filename} cleared and saved as a {file_mod}')
示例#9
0
def change_datetimes(image_path, time_delta):
    """Take in image file and time change as a time delta object.
    Change exif datetime, datetime_digitized, and datetime_original
    Save file with updated exif datetimes."""
    # Open image.
    with open(image_path, 'rb') as image_file:
        image = Image(image_file)
    # Generate new datetime.
    old_datetime = datetime.datetime.strptime(image.datetime,
                                              '%Y:%m:%d %H:%M:%S')
    new_datetime = (old_datetime + time_delta).strftime("%Y:%m:%d %H:%M:%S")
    # Replace all exif datetimes with new datetime.
    image.datetime = new_datetime
    image.datetime_digitized = new_datetime
    image.datetime_original = new_datetime
    # Rewrite image file.
    with open(image_path, 'wb') as new_image_file:
        new_image_file.write(image.get_file())
    print(f"{image_path[7::]} datetime fixed!")
示例#10
0
class TestGetFile(unittest.TestCase):
    """Test cases for modifying EXIF attributes and getting new file contents."""
    def setUp(self):
        """Open sample image file in binary mode for use in test cases."""
        noise = os.path.join(os.path.dirname(__file__), 'noise.jpg')
        with open(noise, 'rb') as image_file:
            self.image = Image(image_file)

        assert self.image.has_exif

    def test_get_file(self):
        """Verify that an image is writable to a file after modifying its EXIF metadata.

        Assert the produced file is equivalent to a known baseline.

        """
        self.image.software = "Python"
        file_hex = binascii.hexlify(self.image.get_file())
        if sys.version_info[0] == 3:
            file_hex = file_hex.decode("utf8")
        self.assertEqual('\n'.join(textwrap.wrap(file_hex, 90)),
                         MODIFIED_NOISE_FILE_HEX_BASELINE)
示例#11
0
    def geotag_photo(self, file, lat, lon):

        exif_lat = (int(lat), int(lat % 1 * 60), (lat % 1 * 60) % 1 * 60)
        exif_lon = (int(lon), int(lon % 1 * 60), (lon % 1 * 60) % 1 * 60)
        if int(lat) < 0:
            exif_lat_ref = 'S'
        else:
            exif_lat_ref = 'N'

        if int(lon) < 0:
            exif_lon_ref = 'W'
        else:
            exif_lon_ref = 'E'

        with open(file, 'rb') as image_file:
            my_image = Image(image_file)
        my_image.make = "Python"
        my_image.gps_latitude_ref = exif_lat_ref
        my_image.gps_latitude = exif_lat
        my_image.gps_longitude_ref = exif_lon_ref
        my_image.gps_longitude = exif_lon

        with open(file, 'wb') as new_image_file:
            new_image_file.write(my_image.get_file())
示例#12
0
def process_one_file(
    in_file: Path, out_file: Path, strategies: List[str], formats: List[str]
):
    if not in_file.is_file():
        return

    if in_file.name.startswith("."):
        return

    if in_file.suffix == ".json":
        return

    print(f"{esc(1)}{esc(96)}{in_file.name}{esc(0)} =>\t", end="")

    date: Optional[datetime] = None
    location: Optional[CoordinatesDMS] = None
    image: Optional[Image] = None

    for strategy in reversed(strategies):
        strategy = strategy.lower()

        if strategy == "exif":
            try:
                with in_file.open("rb") as fo:
                    image = Image(fo)
            except Exception:
                image = None
                continue

            e_date, e_location = get_info_from_exif(image)
            date = e_date or date
            location = e_location or location

        elif strategy == "json":
            j_date, j_location = get_info_from_json(in_file)
            date = j_date or date
            location = j_location or location

        elif strategy == "filename":
            f_date, f_location = get_info_from_filename(in_file, formats)
            date = f_date or date
            location = f_location or location

    if date is None:
        print(f"{esc(91)}no date{esc(0)}, ", end="")
    else:
        print(f"{esc(92)}{date.isoformat()}{esc(0)}, ", end="")
        if image is not None:
            image.datetime = date.strftime(DATETIME_STR_FORMAT)

    if location is None:
        print(f"{esc(91)}no location{esc(0)}")
    else:
        print(f"{esc(92)}{coords_dms2dec(location)}{esc(0)}")
        if image is not None:
            try:
                (
                    (image.gps_latitude, image.gps_latitude_ref),
                    (image.gps_longitude, image.gps_longitude_ref),
                ) = location
            except TypeError:
                pass

    if image is not None:
        out_file.write_bytes(image.get_file())
    else:
        out_file.write_bytes(in_file.read_bytes())

    if date is not None:
        os.utime(out_file, (date.timestamp(), date.timestamp()))
def strip_exifdates(myfile, date_now, dryrun):
    """Function to remove known EXIF date data that affects sorting"""
    if dryrun == False:
        local_exceptions = {}
        with open(myfile, "rb") as image_file:
            try:
                my_image = Image(image_file)
            except AssertionError as err:
                exc_type, value, traceback = sys.exc_info()
                local_exceptions[myfile] = exc_type
                logger.exception(
                    f"exif library exception caught with {myfile}",
                    exc_info=True)
                return
            try:
                logger.debug(
                    f"Attempting to modify EXIF datetime for {myfile}")
                logger.debug(f"Before my_image.datetime: {my_image.datetime}")
                my_image.datetime = f"{date_now.year}:{date_now.month}:{date_now.day} {date_now.hour}:{date_now.minute}:{date_now.second}"
                logger.debug(f"After my_image.datetime: {my_image.datetime}")
            except (AttributeError, KeyError) as err:
                exc_type, value, traceback = sys.exc_info()
                local_exceptions[myfile] = exc_type
                logger.exception(
                    f"Exception caught modifying datetime with {myfile}",
                    exc_info=True)
                pass
            try:
                logger.debug(
                    f"Attempting to modify EXIF datetime_original for {myfile}"
                )
                logger.debug(
                    f"Before my_image.datetime_original: {my_image.datetime_original}"
                )
                my_image.datetime_original = f"{date_now.year}:{date_now.month}:{date_now.day} {date_now.hour}:{date_now.minute}:{date_now.second}"
                logger.debug(
                    f"After my_image.datetime_original: {my_image.datetime_original}"
                )
            except (AttributeError, KeyError) as err:
                exc_type, value, traceback = sys.exc_info()
                local_exceptions[myfile] = exc_type
                logger.exception(
                    f"Exception caught modifying datetime_original with {myfile}",
                    exc_info=True)
                pass
            try:
                logger.debug(
                    f"Attempting to modify EXIF datetime_digitized for {myfile}"
                )
                logger.debug(
                    f"Before my_image.datetime_digitized: {my_image.datetime_digitized}"
                )
                my_image.datetime_digitized = f"{date_now.year}:{date_now.month}:{date_now.day} {date_now.hour}:{date_now.minute}:{date_now.second}"
                logger.debug(
                    f"After my_image.datetime_digitized: {my_image.datetime_digitized}"
                )
            except (AttributeError, KeyError) as err:
                exc_type, value, traceback = sys.exc_info()
                local_exceptions[myfile] = exc_type
                logger.exception(
                    f"Exception caught modifying datetime_digitized with {myfile}",
                    exc_info=True)
                pass
            try:
                logger.debug(
                    f"Attempting to modify EXIF gps_datestamp for {myfile}")
                logger.debug(
                    f"Before my_image.gps_datestamp: {my_image.gps_datestamp}")
                my_image.gps_datestamp = f"{date_now.year}:{date_now.month}:{date_now.day}"
                logger.debug(
                    f"After my_image.gps_datestamp: {my_image.gps_datestamp}")
            except (AttributeError, KeyError) as err:
                exc_type, value, traceback = sys.exc_info()
                local_exceptions[myfile] = exc_type
                logger.exception(
                    f"Exception caught modifying gps_datestamp with {myfile}",
                    exc_info=True)
                pass
            with open(myfile, "wb") as new_image_file:
                new_image_file.write(my_image.get_file())
    if dryrun == True:
        print(f"DRYRUN: Would have removed EXIF date data on {myfile}")
    logger.debug(f"Iteration exceptions: {local_exceptions}")
    return local_exceptions
示例#14
0
import exif
from exif import Image

#https://pypi.org/project/exif/

# open image as my_image
with open('1.jpg', 'rb') as image_file:
    my_image = Image(image_file)

# show all image attributes
print(my_image.list_all())

### show model attribute from my_image
##print(my_image.model)

# set image attributes
my_image.focal_length = 99
my_image.model = "iPhone 13"

# print for testing
print(">>", my_image.focal_length)

# save modified image as modified_image.jpg
with open('modified_image.jpg', 'wb') as new_image_file:
    new_image_file.write(my_image.get_file())
def processFile(args):
    argob, path = args
    path = Path(path)
    file_info = {
        "creation": None,
        "file_prefix": "",
        "file_suffix": "",
        "file_content_type": "",
        "old_conflict": "",
        "dtpattern_in_path": False,
        "conflict_count": 0,
        "cleaned_file_name": ""
    }
    creation = None
    image_exif = None
    image_exif_date_error = False
    lower_suffix = path.suffix.lower()
    if lower_suffix in img_suffixes:
        file_info["file_content_type"] = "IMG"
        try:
            with path.open(mode='rb') as f:
                image_exif = Image(f)
        except Exception as exc:
            logger.debug("Exception while reading exif: %s" % exc)
        if not image_exif or not image_exif.has_exif:
            logger.debug("image has no exif data/is not compatible: %s", path)
            image_exif = None
        elif hasattr(image_exif, "datetime"):
            try:
                creation = \
                    dt.strptime(image_exif.datetime, "%Y:%m:%d %H:%M:%S")
            except ValueError:
                logger.warning("Invalid format: %s", image_exif.datetime)
                image_exif_date_error = True
        elif hasattr(image_exif, "datetime_original"):
            try:
                creation = \
                    dt.strptime(
                        image_exif.datetime_original, "%Y:%m:%d %H:%M:%S"
                    )
            except ValueError:
                logger.warning("Invalid format: %s",
                               image_exif.datetime_original)
                image_exif_date_error = True
    elif lower_suffix in mov_suffixes:
        file_info["file_content_type"] = "MOV"
    else:
        if not argob.prune:
            logger.info("unrecognized file: %s", path)
        elif argob.dry_run:
            logger.info("Would remove: %s (unrecognized)", path)
        else:
            path.unlink()
        return 1
    if argob.conflict == "ignore":
        file_info["cleaned_file_name"] = path.stem
    else:
        # find conflict counter and hash
        conflictmatch = extract_conflict_pattern.match(path.stem).groupdict()
        file_info["cleaned_file_name"] = conflictmatch["unrelated"]
        if conflictmatch["conflict_hash"]:
            if argob.conflict == "hash":
                # if hash is found, one conflict is indicated
                file_info["conflict_count"] = 1
            else:
                file_info["cleaned_file_name"] = "%s-%s" % (
                    file_info["cleaned_file_name"],
                    conflictmatch["conflict_hash"])
        # if hash and counter: conflict_count = counter + 1
        # if counter: conflict_count  = counter
        # if hash: conflict_count  = 1
        file_info["conflict_count"] += \
            int(conflictmatch["conflict_counter"] or 0)
    # check and potential extract datetime info from filename
    dtnamematch = extraction_pattern.match(file_info["cleaned_file_name"])
    if dtnamematch:
        dtnamematchg = dtnamematch.groupdict()
        file_info["file_prefix"] = dtnamematchg["prefix"] or ""
        file_info["file_suffix"] = dtnamematchg["suffix"] or ""

        file_info["dtpattern_in_path"] = True

        if not creation:
            logger.debug("extract time from path: %s", path)
            creation = dt(year=int(dtnamematchg["year"]),
                          month=int(dtnamematchg["month"]),
                          day=int(dtnamematchg["day"]),
                          hour=int(dtnamematchg["hour"] or 0),
                          minute=int(dtnamematchg["minute"] or 0),
                          second=int(dtnamematchg["second"] or 0))
    # still no creation time
    if not creation:
        logger.debug("extract time from st_ctime: %s", path)
        creation = dt.fromtimestamp(path.stat().st_ctime)
    file_info["creation"] = creation

    if image_exif_date_error:
        file_info["old_file_hash"] = generate_hash(path)
        if argob.dry_run:
            logger.info("Would fix: %s to %s, of %s", image_exif.datetime,
                        creation.strftime("%Y:%m:%d %H:%M:%S"), path)
        else:
            image_exif.datetime = creation.strftime("%Y:%m:%d %H:%M:%S")
            image_exif.datetime_original = image_exif.datetime
            with path.open(mode='wb') as f:
                f.write(image_exif.get_file())

    file_info["file_hash"] = generate_hash(path)
    if rename_file(argob, path, file_info):
        return 1
    return 0
示例#16
0
class TestModifyExif(unittest.TestCase):

    """Test cases for deleting EXIF attributes."""

    def setUp(self):
        """Open sample image file in binary mode for use in test cases."""
        grand_canyon = os.path.join(os.path.dirname(__file__), 'grand_canyon.jpg')
        with open(grand_canyon, 'rb') as image_file:
            self.image = Image(image_file)

        assert self.image.has_exif

    def test_delete_all_tags(self):
        """Verify deleting all EXIF tags from the Image object."""
        self.image.delete_all()

        segment_hex = self.image._segments['APP1'].get_segment_hex()
        self.assertEqual('\n'.join(textwrap.wrap(segment_hex, 90)), DELETE_ALL_HEX_BASELINE)

        with TemporaryFile("w+b") as temporary_file_stream:
            temporary_file_stream.write(self.image.get_file())
            temporary_file_stream.seek(0)
            reloaded_image = Image(temporary_file_stream)

        dunder_dir_text = '\n'.join(textwrap.wrap(repr(sorted(dir(reloaded_image))), 90))
        self.assertEqual(dunder_dir_text, Baseline("""
            ['<unknown EXIF tag 59932>', '_segments', 'delete', 'delete_all', 'get', 'get_file',
            'get_thumbnail', 'has_exif', 'resolution_unit', 'x_resolution', 'y_resolution']
            """))

    def test_delete_ascii_tags(self):
        """Verify deleting EXIF ASCII from the Image object and the hexadecimal equivalent."""
        del self.image.make
        del self.image.model

        with self.assertRaisesRegex(AttributeError, "image does not have attribute make"):
            self.image.make
        with self.assertRaisesRegex(AttributeError, "image does not have attribute model"):
            self.image.model

        segment_hex = self.image._segments['APP1'].get_segment_hex()
        self.assertEqual('\n'.join(textwrap.wrap(segment_hex, 90)), DELETE_ASCII_TAGS_HEX_BASELINE)

    def test_delete_gps_tags(self):
        """Verify deleting EXIF geotags from the Image object and the hexadecimal equivalent."""
        del self.image.gps_latitude
        del self.image.gps_longitude
        del self.image.gps_altitude

        with self.assertRaisesRegex(AttributeError, "image does not have attribute gps_latitude"):
            self.image.gps_latitude
        with self.assertRaisesRegex(AttributeError, "image does not have attribute gps_longitude"):
            self.image.gps_longitude
        with self.assertRaisesRegex(AttributeError, "image does not have attribute gps_altitude"):
            self.image.gps_altitude

        segment_hex = self.image._segments['APP1'].get_segment_hex()
        self.assertEqual('\n'.join(textwrap.wrap(segment_hex, 90)), DELETE_GEOTAG_HEX_BASELINE)

    def test_delete_method(self):
        """Test behavior when setting tags using the ``delete()`` method."""
        self.image.delete("model")

        with self.assertRaisesRegex(AttributeError, "image does not have attribute model"):
            self.image.model

    def test_handle_unset_attribute(self):
        """Verify that accessing an attribute not present in an image raises an AttributeError."""
        with self.assertRaisesRegex(AttributeError, "image does not have attribute light_source"):
            del self.image.light_source

    def test_index_deleter(self):
        """Test deleting attributes using index syntax."""
        del self.image["model"]

        with self.assertRaisesRegex(AttributeError, "image does not have attribute model"):
            self.image.model

    def test_standard_delete(self):
        """Verify that writing and deleting non-EXIF attributes behave normally."""
        self.image.dummy_attr = 123
        assert self.image.dummy_attr == 123
        del self.image.dummy_attr
        with self.assertRaisesRegex(AttributeError, "unknown image attribute dummy_attr"):
            self.image.dummy_attr
示例#17
0
    17: (1017664, 4813),
    23: 'T',
    24: (1017664, 4813),
    29: '2019:01:11',
    31: (65, 1)
}

with open(im_path, 'rb') as image_file:

    im = Image(image_file)

    im.make = data['make']
    im.model = data['model']

    im.camera = data['camera']

    im.GPSInfo = GPSInfo

with open(new_im_name, 'wb') as new_image_file:
    new_image_file.write(im.get_file())

with open(new_im_name, 'rb') as image_file:
    imtest = Image(image_file)

os.system('rm ' + im_path)

os.system('cp ' + exif_list[0] + ' ' + exif_list[0] + '1')

os.system('mv ' + exif_list[0] + '1' + ' ' + exif_folder + '/' + im_name +
          'exif.jpg.exif')
示例#18
0
    print('USAGE: exifGPSimplant filename latitude [0-360) longitude [0 - 180)')
    exit(-1)
else:
    (recipient, latitude, longitude) = names[1:4]

with open(recipient, 'rb') as image_file:
    img = Image(image_file)

img.gps_latitude = dd_GPS_dms(latitude)
img.gps_longitude = dd_GPS_dms(longitude)
#img.gps_altitude = 1200 # An orphan...

print(img.gps_latitude, img.gps_longitude)

with open(recipient, 'wb') as image_file:
    image_file.write(img.get_file())

## Note the GPS tags format
# 34°56'43.386"N 109°46'32.447"W

## Other locations...
# https://www.gps-coordinates.net/gps-coordinates-converter
# Whitewater, CA: 33.923685, -116.640324
# Yosemite Valley: 37° 43′ 18″ N, 119° 38′ 47″ W
# Mocassin (Tuolumne Count, CA): 37° 48′ 39″ N, 120° 18′ 0″ W
# Hollywood Sign Puzzle View: 34°06'18.3"N 118°19'52.0"W
# Hoover Dam: 36° 0′ 56″ N, 114° 44′ 16″ W
# Rainbow Canyon: 36° 21′ 56.88″ N, 117° 30′ 5.4″ W
# Route 66 (AZ): 35°14'15.5"N 113°12'22.6"W
# Las Vegas' Replica of the Statue of Liberty 36°6'3.58"N 115°10'23.029"W
# The Tepees in Petrified Forest 34°56'43.386"N 109°46'32.447"W