コード例 #1
0
def order():
    """
    order by date using exif info
    """
    log_function_call(order.__name__)
    inpath = os.getcwd()

    Tagdict = read_exiftags(file_types=settings.image_types, ignore_model=True)
    timeJumpDetector = TimeJumpDetector()
    time_old = giveDatetime()
    dircounter = 1
    filenames = []
    leng = len(list(Tagdict.values())[0])
    dirNameDict_firsttime = OrderedDict()
    dirNameDict_lasttime = OrderedDict()
    time = giveDatetime(create_model(Tagdict, 0).get_date())
    daystring = dateformating(time, "YYMMDD_")
    dirName = daystring + "%02d" % dircounter
    dirNameDict_firsttime[time] = dirName
    log().info('Number of JPG: %d', leng)
    for i in range(leng):
        model = create_model(Tagdict, i)
        time = giveDatetime(model.get_date())

        if timeJumpDetector.isJump(time, len(filenames)):
            dirNameDict_lasttime[time_old] = dirName
            moveFiles(filenames, os.path.join(inpath, dirName))

            filenames = []
            if newdate(time, time_old):
                daystring = dateformating(time, "YYMMDD_")
                dircounter = 1
            else:
                dircounter += 1
            dirName = daystring + "%02d" % dircounter
            dirNameDict_firsttime[time] = dirName
        filenames.append((model.dir, model.filename))
        time_old = time

    dirNameDict_lasttime[time_old] = dirName
    moveFiles(filenames, os.path.join(inpath, dirName))

    print_firstlast_of_dirname(dirNameDict_firsttime, dirNameDict_lasttime)

    Tagdict_mp4 = read_exiftags(file_types=settings.video_types)
    if len(Tagdict_mp4) == 0:
        return
    leng = len(list(Tagdict_mp4.values())[0])
    log().info('Number of mp4: %d', leng)
    for i in range(leng):
        model = create_model(Tagdict_mp4, i)
        time = giveDatetime(model.get_date())
        dirName = find_dir_with_closest_time(dirNameDict_firsttime,
                                             dirNameDict_lasttime, time)

        if dirName:
            move(model.filename, model.dir,
                 os.path.join(inpath, dirName, "mp4"))
        else:
            log().warning("Did not move %s to %s", model.filename, dirName)
コード例 #2
0
def print_info(tagGroupNames=(), allGroups=False):
    """
    write tag info of tagGroupNames to a file in saves dir
    :param tagGroupNames: selectable groups (look into constants)
    :param allGroups: take all tagGroupNames
    """
    tagdict = read_exiftags()
    model = create_model(tagdict, 0)
    tagnames = model.TagNames
    if allGroups: tagGroupNames = tagnames.keys()
    for tagGroupName in tagnames:
        if not tagGroupNames == [] and not tagGroupName in tagGroupNames:
            continue
        outstring = "%-80s\t" % "File Name"
        for entry in tagnames[tagGroupName]:
            if not entry in tagdict: continue
            outstring += "%-30s\t" % entry
        outstring += "\n"

        for i in range(len(tagdict["File Name"])):
            outstring += "%-80s\t" % tagdict["File Name"][i]
            for entry in tagnames[tagGroupName]:
                if not entry in tagdict: continue
                val = tagdict[entry]
                outstring += "%-30s\t" % val[i]
            outstring += "\n"

        dirname = get_saves_dir()
        writeToFile(os.path.join(dirname, "tags_" + tagGroupName + ".txt"),
                    outstring)
コード例 #3
0
def shift_time(hours: int = 0, minutes: int = 0, seconds: int = 0, is_video: bool = False):
    """
    shift DateTimeOriginal to correct for wrong camera time setting

    :example: to adjust time zone by one, set hours=-1

    :param hours: hours to shift
    :param minutes: minutes to shift
    :param seconds: seconds to shift
    :param is_video: whether to modify videos, if false modifies pictures
    """
    log_function_call(shift_time.__name__, hours, minutes, seconds, is_video)
    inpath = os.getcwd()
    delta_t = dt.timedelta(hours=hours, minutes=minutes, seconds=seconds)
    Tagdict = read_exiftags(inpath, settings.video_types if is_video else settings.image_types)
    if has_not_keys(Tagdict, keys=["Directory", "File Name", "Date/Time Original"]): return
    leng = len(list(Tagdict.values())[0])
    time_tags = ["DateTimeOriginal", "CreateDate", "ModifyDate"]
    time_tags_mp4 = ["TrackCreateDate", "TrackModifyDate", "MediaCreateDate", "MediaModifyDate"]
    dir_change_printer = DirChangePrinter(Tagdict["Directory"][0])
    for i in range(leng):
        model = create_model(Tagdict, i)
        time = giveDatetime(model.get_date())
        newtime = time + delta_t
        timestring = dateformating(newtime, "YYYY:MM:DD HH:mm:ss")
        outTagDict = {}
        for time_tag in time_tags:
            outTagDict[time_tag] = timestring
        if is_video:
            for time_tag in time_tags_mp4:
                outTagDict[time_tag] = timestring
        write_exiftag(outTagDict, model.dir, model.filename)
        dir_change_printer.update(model.dir)
    dir_change_printer.finish()
コード例 #4
0
ファイル: futureexif.py プロジェクト: mvolkert/EXIFnaming
def _detect_3D():
    """
    not yet fully implemented
    """
    inpath = os.getcwd()
    Tagdict = read_exiftags(inpath)
    if has_not_keys(Tagdict,
                    keys=[
                        "Directory", "File Name", "Date/Time Original",
                        "Burst Mode", "Sequence Number"
                    ]):
        return
    time_old = giveDatetime()
    filenames = []
    dir3D = "3D"
    for i in range(len(list(Tagdict.values())[0])):
        newDir = os.path.join(Tagdict["Directory"][i], dir3D)
        os.makedirs(newDir, exist_ok=True)
        model = create_model(Tagdict, i)
        SequenceNumber = model.get_sequence_number()
        if model.is_series() or SequenceNumber > 1: continue
        time = giveDatetime(model.get_date())
        timedelta = time - time_old
        timedelta_sec = timedelta.days * 3600 * 24 + timedelta.seconds
        time_old = time
        if timedelta_sec < 10 or (SequenceNumber == 1
                                  and timedelta_sec < 15) or filenames == []:
            filenames.append(getPath(Tagdict, i))
        elif len(filenames) > 1:
            for filename in filenames:
                if os.path.isfile(
                        filename.replace(Tagdict["Directory"][i], newDir)):
                    continue
                shutil.copy2(filename, newDir)
            filenames = []
コード例 #5
0
def rename_from_exif():
    """
    use exif information written by :func:`write_exif_using_csv` to restore filename
    """
    Tagdict = read_exiftags()
    if has_not_keys(Tagdict, keys=["Label"]): return

    temppostfix = renameTemp(Tagdict["Directory"], Tagdict["File Name"])
    leng = len(list(Tagdict.values())[0])
    for i in range(leng):
        filename = Tagdict["File Name"][i]
        ext = filename[filename.rfind('.'):]
        renameInPlace(Tagdict["Directory"][i], filename + temppostfix,
                      Tagdict["Label"][i] + ext)
コード例 #6
0
def rotate(subname: str = "",
           folder: str = r"",
           sign=1,
           override=True,
           ask=True):
    """
    rotate back according to tag information (Rotate 90 CW or Rotate 270 CW)
    Some programs like franzis hdr projects rotate the resolution of the picture -> picture gets upward resolution and
    shown as rotated two times. This function reverses the resolution rotation according to exif info.
    Pictures that either have no rotation according to exif or have a normal resolution ratio are not modified.
    So calling it a second time wont change anything.
    :param subname: only files that contain this name are rotated, empty string: no restriction
    :param sign: direction of rotation
    :param folder: only files in directories that match this regex are rotated, empty string: no restriction
    :param override: override file with rotated one
    :param ask: if should ask for user confirmation
    """
    log_function_call(rotate.__name__, subname, folder, sign, override, ask)
    from PIL import Image

    NFiles = 0
    clock = Clock()
    inpath = os.getcwd()
    for (dirpath, dirnames, filenames) in os.walk(inpath):
        if is_invalid_path(dirpath, regex=folder): continue
        if len(filenames) == 0: continue
        Tagdict = read_exiftags(dirpath, settings.image_types, ask=ask)
        if has_not_keys(Tagdict, keys=["Orientation"]): continue
        leng = len(list(Tagdict.values())[0])
        for i in range(leng):
            # Load the original image:
            model = create_model(Tagdict, i)
            if not subname in model.filename: continue
            if model.is_rotated_by(0) or not model.is_upward():
                continue
            name = model.get_path()
            log().info("rotate %s", model.filename)
            img = Image.open(name)
            if model.is_rotated_by(90):
                img_rot = img.rotate(90 * sign, expand=True)
            elif model.is_rotated_by(-90):
                img_rot = img.rotate(-90 * sign, expand=True)
            else:
                continue
            NFiles += 1
            if not override:
                name = name[:name.rfind(".")] + "_ROTATED" + name[name.
                                                                  rfind("."):]
            img_rot.save(name, 'JPEG', quality=99, exif=img.info['exif'])
    clock.finish()
コード例 #7
0
def searchby_exiftag_equality(tag_name: str, value: str):
    """
    searches for files where the value of the exiftag equals the input value
    :param tag_name: exiftag key
    :param value: exiftag value
    """
    Tagdict = read_exiftags()
    if has_not_keys(
            Tagdict,
            keys=["Directory", "File Name", "Date/Time Original", tag_name]):
        return
    leng = len(list(Tagdict.values())[0])
    files = []
    for i in range(leng):
        if not Tagdict[tag_name][i] == value: continue
        files.append(getPath(Tagdict, i))
    copyFilesTo(files, os.path.join(os.getcwd(), "matches"))
コード例 #8
0
def searchby_exiftag_interval(tag_name: str, min_value: float,
                              max_value: float):
    """
    searches for files where the value of the exiftag is in the specified interval
    :param tag_name: exiftag key
    :param min_value: interval start
    :param max_value: interval end
    """
    inpath = os.getcwd()
    Tagdict = read_exiftags(inpath)
    if has_not_keys(Tagdict, keys=[tag_name]): return
    leng = len(list(Tagdict.values())[0])
    files = []
    for i in range(leng):
        value = tofloat(Tagdict[tag_name][i])
        if not (value and min_value < value < max_value): continue
        files.append(getPath(Tagdict, i))
    copyFilesTo(files, os.path.join(inpath, "matches"))
コード例 #9
0
ファイル: futureexif.py プロジェクト: mvolkert/EXIFnaming
def _detect_sunset():
    """
    not yet fully implemented
    """
    inpath = os.getcwd()
    Tagdict = read_exiftags(inpath)
    if has_not_keys(Tagdict, keys=["Directory", "File Name", "Scene Mode"]):
        return
    for i in range(len(list(Tagdict.values())[0])):
        newDir = os.path.join(Tagdict["Directory"][i], "Sunset")
        os.makedirs(newDir, exist_ok=True)
        model = create_model(Tagdict, i)
        time = giveDatetime(model.get_date())
        if 23 < time.hour or time.hour < 17: continue
        if not model.is_sun(): continue
        filename = getPath(Tagdict, i)
        if os.path.isfile(filename.replace(Tagdict["Directory"][i], newDir)):
            continue
        shutil.copy2(filename, newDir)
コード例 #10
0
def location_to_keywords():
    """
    import location exif information to put into Keywords

    deprecated: try to use write_exif_using_csv() instead
    """
    inpath = os.getcwd()
    log().info("process %d Files in %s, subdir: %r",
               count_files_in(inpath, settings.image_types + settings.video_types, ""), inpath, settings.includeSubdirs)
    askToContinue()
    Tagdict = read_exiftags(inpath, ask=False)
    leng = len(list(Tagdict.values())[0])
    for i in range(leng):
        dirpath = Tagdict["Directory"][i]
        filename = Tagdict["File Name"][i]
        image_tags = Tagdict["Keywords"][i].split(', ')
        outTagDict = {'Keywords': image_tags, 'Subject': list(image_tags)}
        location = Location(Tagdict, i)
        add_dict(outTagDict, location.to_tag_dict())
        write_exiftag(outTagDict, dirpath, filename)
コード例 #11
0
def first_date_per_folder() -> OrderedDict:
    """
    find files with missing exif data
    """
    log_function_call(first_date_per_folder.__name__)

    clock = Clock()
    inpath = os.getcwd()
    folder_dict = OrderedDict()

    for (dirpath, dirnames, filenames) in os.walk(inpath):
        if is_invalid_path(dirpath): continue
        if fileop.count_files(filenames, settings.image_types) == 0: continue
        Tagdict = read_exiftags(dirpath, settings.image_types, ask=False)
        if len(list(Tagdict.values())) == 0: continue
        folder_dict[os.path.relpath(dirpath, inpath)] = [
            date for date in Tagdict["Date/Time Original"] if date
        ][0]

    clock.finish()
    return folder_dict
コード例 #12
0
def order_with_timetable(timefile: str = None):
    """
    use timetable to create folder structure
    :param timefile: timetable file
    :return:
    """
    if not timefile:
        timefile = get_info_dir("timetable.txt")

    log_function_call(order_with_timetable.__name__, timefile)

    dirNameDict_firsttime, dirNameDict_lasttime = _read_timetable(timefile)
    Tagdict = read_exiftags()
    leng = len(list(Tagdict.values())[0])
    log().info('Number of jpg: %d', leng)
    for i in range(leng):
        model = create_model(Tagdict, i)
        time = giveDatetime(model.get_date())
        dirName = find_dir_with_closest_time(dirNameDict_firsttime,
                                             dirNameDict_lasttime, time)

        if dirName:
            move(model.filename, model.dir, os.path.join(os.getcwd(), dirName))
コード例 #13
0
def rename(Prefix="",
           dateformat='YYMM-DD',
           startindex=1,
           onlyprint=False,
           keeptags=True,
           is_video=False,
           name=""):
    """
    Rename into Format: [Prefix][dateformat](_[name])_[Filenumber][SeriesType][SeriesSubNumber]_[PhotoMode]
    :param Prefix: prefix has to fulfil regex [-a-zA-Z]*
    :param dateformat: Y:Year,M:Month,D:Day,N:DayCounter; Number of occurrences determine number of digits
    :param startindex: minimal counter
    :param onlyprint: do not rename; only output file of proposed renaming into saves directory
    :param keeptags: any tags - name or postfixes will be preserved
    :param is_video: is video file extension
    :param name: optional name between date and filenumber, seldom used
    """
    log_function_call(rename.__name__, Prefix, dateformat, startindex,
                      onlyprint, keeptags, is_video, name)
    Tagdict = read_exiftags(
        file_types=settings.video_types if is_video else settings.image_types)
    if not Tagdict: return

    # rename temporary
    if not onlyprint:
        temppostfix = renameTemp(Tagdict["Directory"], Tagdict["File Name"])
    else:
        temppostfix = ""

    # initialize
    outstring = ""
    Tagdict["File Name new"] = []
    time_old = giveDatetime()
    counter = startindex - 1
    digits = _count_files_for_each_date(Tagdict, startindex, dateformat)
    number_of_files = len(list(Tagdict.values())[0])
    daystring = ""

    for i in range(number_of_files):
        model = create_model(Tagdict, i)
        time = giveDatetime(model.get_date())
        filename = model.filename

        if newdate(time, time_old, 'D' in dateformat or 'N' in dateformat):
            daystring = dateformating(time, dateformat)
            if not i == 0: counter = 0

        filenameBuilder = FilenameBuilder(filename)
        filenameBuilder.add_main(Prefix + daystring)
        filenameBuilder.add_main(model.get_model_abbr())
        filenameBuilder.add_main(name)

        if is_video:
            counter += 1
            counterString = "M%02d" % counter
            filenameBuilder.add_post(model.get_recMode())
        else:
            # SequenceNumber
            sequence_number = model.get_sequence_number()
            if sequence_number < 2 and not time == time_old or model.ignore_same_date(
            ):
                counter += 1
            counterString = ("%0" + digits + "d") % counter
            if not "HDR" in filename:
                counterString += model.get_sequence_string()

        filenameBuilder.add_main(counterString)
        filenameBuilder.add_post(model.get_mode())
        if keeptags: filenameBuilder.use_old_tags()

        newname = filenameBuilder.build()

        # handle already exiting filename - its ok when they are in different directories
        # its not ok to have to files with one uppercase and another lowercase -> equals with ignore case
        if len(Tagdict["File Name new"]) > 0:
            if newname.lower() == Tagdict["File Name new"][-1].lower() and \
                    Tagdict["Directory"][i].lower() == Tagdict["Directory"][i - 1].lower():
                log().warning("%s already exists - postfix it with V%d",
                              os.path.join(model.dir, newname), 1)
                newname = filenameBuilder.set_version("V%d" % 1).build()

            for version in range(2, 100):
                indexes_samename = [
                    i for i, name in enumerate(Tagdict["File Name new"])
                    if name.lower() == newname.lower()
                ]
                if indexes_samename:
                    if Tagdict["Directory"][i] == Tagdict["Directory"][
                            indexes_samename[0]]:
                        log().warning(
                            "%s already exists - postfix it with V%d",
                            os.path.join(model.dir, newname), version)
                        newname = filenameBuilder.set_version("V%d" %
                                                              version).build()
                    else:
                        break
                else:
                    break

        time_old = time
        Tagdict["File Name new"].append(newname)
        outstring += _write(model.dir, filename, temppostfix, newname,
                            onlyprint)

    dirname = get_saves_dir()
    timestring = dateformating(dt.datetime.now(), "_MMDDHHmmss")
    video_str = "_video" if is_video else ""
    np.savez_compressed(os.path.join(dirname, "Tags" + video_str + timestring),
                        Tagdict=Tagdict)
    writeToFile(
        os.path.join(dirname, "newnames" + video_str + timestring + ".txt"),
        outstring)
コード例 #14
0
def find_bad_exif(do_move=True,
                  check_date_additional=False,
                  folder: str = r""):
    """
    find files with missing exif data
    """
    log_function_call(find_bad_exif.__name__, do_move)

    clock = Clock()
    inpath = os.getcwd()
    lines_no_tags = OrderedSet()
    lines_bad_date_additional = OrderedSet()
    lines_date_missing = OrderedSet()
    out_filename_no_tags = get_info_dir("no_tags.csv")
    file_no_tags, writer_no_tags = fileop.create_csv_writer(
        out_filename_no_tags, ["directory", "name_part"])
    out_filename_bad_date_additional = get_info_dir("bad_date_additional.csv")
    file_bad_date_additional, writer_bad_date_additional = fileop.create_csv_writer(
        out_filename_bad_date_additional, ["directory", "name_part"])
    out_filename_date_missing = get_info_dir("date_missing.csv")
    file_date_missing, writer_date_missing = fileop.create_csv_writer(
        out_filename_date_missing, ["directory", "name_part"])
    for (dirpath, dirnames, filenames) in os.walk(inpath):
        if is_invalid_path(dirpath, regex=folder): continue
        if fileop.count_files(filenames, settings.image_types) == 0: continue
        Tagdict = read_exiftags(dirpath, settings.image_types, ask=False)
        if len(list(Tagdict.values())) == 0: continue
        leng = len(list(Tagdict.values())[0])
        for i in range(leng):
            if (not "Keywords" in Tagdict or not Tagdict["Keywords"][i]) or \
                    (not "Subject" in Tagdict or not Tagdict["Subject"][i]) or \
                    (not "Description" in Tagdict or not Tagdict["Description"][i]) or \
                    (not "User Comment" in Tagdict or not Tagdict["User Comment"][i]):
                lines_no_tags.add((os.path.basename(dirpath),
                                   _remove_counter(Tagdict["File Name"][i])))
                if do_move and not "bad_exif" in dirpath:
                    move(
                        Tagdict["File Name"][i], dirpath,
                        dirpath.replace(
                            inpath, os.path.join(inpath, "bad_exif_keywords")))
            if not "Date/Time Original" in Tagdict or not Tagdict[
                    "Date/Time Original"][i]:
                lines_date_missing.add(
                    (os.path.basename(dirpath),
                     _remove_counter(Tagdict["File Name"][i])))
                if do_move and not "bad_exif" in dirpath:
                    move(
                        Tagdict["File Name"][i], dirpath,
                        dirpath.replace(
                            inpath,
                            os.path.join(inpath, "bad_exif_date_missing")))
            if check_date_additional and \
                    (("Date Created" in Tagdict and Tagdict["Date Created"][i]) or
                     ("Time Created" in Tagdict and Tagdict["Time Created"][i]) or
                     ("Create Date" in Tagdict and Tagdict["Create Date"][i]) or
                     ("Modify Date" in Tagdict and Tagdict["Modify Date"][i]) or
                     ("Digital Creation Date" in Tagdict and Tagdict["Digital Creation Date"][i])):
                lines_bad_date_additional.add(
                    (os.path.basename(dirpath),
                     _remove_counter(Tagdict["File Name"][i])))
                if do_move and not "bad_exif" in dirpath:
                    move(
                        Tagdict["File Name"][i], dirpath,
                        dirpath.replace(
                            inpath,
                            os.path.join(inpath, "bad_exif_date_additional")))
    writer_no_tags.writerows(lines_no_tags)
    writer_bad_date_additional.writerows(lines_bad_date_additional)
    writer_date_missing.writerows(lines_date_missing)
    file_no_tags.close()
    file_bad_date_additional.close()
    file_date_missing.close()
    clock.finish()