Code backup
This commit is contained in:
2026-05-10 16:59:01 +02:00
commit 368d6fafea
796 changed files with 315310 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
dist
build
*.spec
.idea
tests
*venv/
__pycache__/
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Sascha Schiwy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+94
View File
@@ -0,0 +1,94 @@
# HeicConverter
## Introduction
A very simple command line tool to convert *.heic files to jpg. Since the available programs for windows are either paid
or not working for me, I decided to make a simple python script to help convert these files.
## Features
- Convert all HEIC files to jpg in a folder and sub-folders recursively
- Skips already existing conversions
- Keep Metadata of the original file
- Optional: Remove source files
- Optional: Overwrite existing files
## Quick Usage
1. Copy the prepared exe to the folder with heic files for convert and double click it.
2. Use Command line and append the path of interest:
~~~~
./heicConverter.exe path/to/pictures
~~~~
## Command Line
Start the script (or exe) from command line for additional options:
~~~~
heicConverter.exe [-h] [-r] [-o] [--not-recursive] [--skip-prompt] path
Convert HEIC files to JPEG
positional arguments:
path the path to the file or directory to convert
options:
-h, --help show this help message and exit
-r, --remove Remove converted HEIC Files
-o, --overwrite Overwrite existing JPEG files
--not-recursive Do not search subdirectories
--skip-prompt Skip the prompt at the end
~~~~
## GUI
Also a GUI Version is available. Just start HeicConverterGui.exe.
![GUI](doc/gui_example.png)
## Installation
### Windows
Download the latest release from the [Release Page](https://github.com/saschiwy/HeicConverter/releases) and extract it
somewhere on your machine.
### Linux / Mac
Download the repo, install the dependencies and run the script.
## Development Dependencies
Install the python package dependencies with:
~~~~
pip install -r requirements.txt
~~~~
## Create your own executable
Install pyinstaller with:
~~~~
pip install pyinstaller
~~~~
Install the dependencies, navigate with a console to the source dir and run the following commands:
~~~~
python -m PyInstaller --onefile --console heicConverter.py
python -m PyInstaller --onefile --windowed heicConverterGui.py
~~~~
## Remarks
This software was mainly created by people at StackOverflow:
https://stackoverflow.com/questions/54395735/how-to-work-with-heic-image-file-types-in-python
## Example
![Example](doc/example.png)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JBK73YUVW7MGW&source=url)
+115
View File
@@ -0,0 +1,115 @@
import os
from PIL import Image, ExifTags, UnidentifiedImageError
from pillow_heif import register_heif_opener
from datetime import datetime
import piexif
import fnmatch
register_heif_opener(allow_incorrect_headers=True)
def get_file_list(dir_of_interest, recursive):
"""
Get a list of all files in the directory of interest
:param dir_of_interest: the directory to search
:param recursive: search subdirectories
:return: a list of files
"""
file_list = []
if os.path.isdir(dir_of_interest):
for root, dirs, files in os.walk(dir_of_interest):
if not recursive:
dirs.clear()
for file in files:
if fnmatch.fnmatch(file.lower(), '*.heic'):
file_list.append([os.path.normpath(root), file])
return file_list
else:
print("Path {} is not a valid directory.".format(dir_of_interest))
return None
def convert_heic_file(source_file, target_file, overwrite, remove):
"""
Convert a single heic file to jpeg
:param source_file: the source file
:param target_file: the target file
:param overwrite: overwrite existing jpeg files
:param remove: remove converted heic files
:return: True if successful, False otherwise
"""
if os.path.exists(target_file) and not overwrite:
print(f'File {target_file} already exists, skip')
return False
try:
image = Image.open(source_file)
image_exif = image.getexif()
if image_exif:
# Make a map with tag names and grab the datetime
exif = {ExifTags.TAGS[k]: v for k, v in image_exif.items() if k in ExifTags.TAGS and type(v) is not bytes}
if 'DateTime' in exif:
date = datetime.strptime(exif['DateTime'], '%Y:%m:%d %H:%M:%S')
else:
date = datetime.now()
# Load exif data via piexif
exif_dict = piexif.load(image.info["exif"])
# Update exif data with orientation and datetime
exif_dict["0th"][piexif.ImageIFD.DateTime] = date.strftime("%Y:%m:%d %H:%M:%S")
exif_dict["0th"][piexif.ImageIFD.Orientation] = 1
exif_bytes = piexif.dump(exif_dict)
# Save image as jpeg
image.save(target_file, "jpeg", exif=exif_bytes)
print(f'Converted image: {source_file}')
if remove:
os.remove(source_file)
return True
else:
print(f"Unable to get exif data for {source_file}")
except UnidentifiedImageError as e:
print(f"{source_file} is not a valid image : {e}")
except Exception as e:
print(f"Unable to convert {source_file}: {e}")
return False
def convert_heic_to_jpeg(dir_of_interest, recursive, overwrite, remove):
"""
Convert all heic files in the directory of interest to jpeg
:param dir_of_interest: The directory to search
:param recursive: search subdirectories
:param overwrite: overwrite existing jpeg files
:param remove: remove converted heic files
:return: a list of successfully converted files
"""
heic_files = get_file_list(dir_of_interest, recursive)
# Extract files of interest
success_files = []
print(f'Found {len(heic_files)} files to convert in folder {dir_of_interest}')
# Convert files to jpg while keeping the timestamp
for root, filename in heic_files:
target_filename = os.path.splitext(filename)[0] + ".jpg"
target_file = os.path.join(root, target_filename)
source_file = os.path.join(root, filename)
if convert_heic_file(source_file, target_file, overwrite, remove):
success_files.append(target_filename)
return success_files
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

@@ -0,0 +1 @@
root@PC284:/mnt/e/Code/VSC/Python3/_sftw/HeicConverter# python3 heicConverter.py -r -o fc/Mario
@@ -0,0 +1,46 @@
import os
import argparse
from converter import convert_heic_to_jpeg, convert_heic_file
def parse_args():
"""
Parse command line arguments
:return: the parsed arguments
"""
parser = argparse.ArgumentParser(description='Convert HEIC files to JPEG')
parser.add_argument('path', help='the path to the file or directory to convert', default='./', nargs='?')
parser.add_argument('-r', '--remove', help='Remove converted HEIC Files', action='store_true')
parser.add_argument('-o', '--overwrite', help='Overwrite existing JPEG files', action='store_true')
parser.add_argument('--not-recursive', help='Do not search subdirectories', action='store_true')
parser.add_argument('--skip-prompt', help='Skip the prompt at the end', action='store_true')
return parser.parse_args()
if __name__ == '__main__':
path = os.path.abspath(os.getcwd())
args = parse_args()
if args.path:
path = args.path
path = os.path.abspath(path)
if os.path.isdir(path):
print(f'Converting HEIC files in directory {path}')
converted = convert_heic_to_jpeg(path, not args.not_recursive, args.overwrite, args.remove)
print(f'\nSuccessfully converted {len(converted)} files')
elif os.path.isfile(path):
print(f'Converting HEIC file {path}')
convert_heic_file(path, os.path.splitext(path)[0] + ".jpg", args.overwrite, args.remove)
print(f'\nSuccessfully converted file')
else:
print(f'Dont know what to do with {path}')
if not args.skip_prompt:
input("Press Enter to continue...")
@@ -0,0 +1,87 @@
import os
import tkinter as tk
from tkinter import filedialog
from tkinter import scrolledtext
from tkinter import ttk # ttk for modern themed widgets
from converter import convert_heic_to_jpeg, convert_heic_file
from ctypes import windll
windll.shcore.SetProcessDpiAwareness(1)
class HEICConverterGUI:
def __init__(self, master):
self.master = master
master.title("HEIC to JPEG Converter")
master.geometry("600x500") # Set a default size for the window
# Style configuration
style = ttk.Style()
style.configure("TButton", font=("Helvetica", 12), padding=10)
style.configure("TLabel", font=("Helvetica", 12), padding=5)
style.configure("TCheckbutton", font=("Helvetica", 12), padding=5)
style.configure("TEntry", font=("Helvetica", 12), padding=5)
self.path_label = ttk.Label(master, text="File or Directory Path:")
self.path_label.pack(anchor='w', padx=10, pady=5)
self.path_entry = ttk.Entry(master, width=50)
self.path_entry.pack(anchor='w', padx=10, pady=5)
self.browse_button = ttk.Button(master, text="Browse", command=self.browse)
self.browse_button.pack(anchor='w', padx=10, pady=5)
self.remove_var = tk.BooleanVar()
self.remove_check = ttk.Checkbutton(master, text="Remove converted HEIC Files", variable=self.remove_var)
self.remove_check.pack(anchor='w', padx=10, pady=5)
self.overwrite_var = tk.BooleanVar()
self.overwrite_check = ttk.Checkbutton(master, text="Overwrite existing JPEG files", variable=self.overwrite_var)
self.overwrite_check.pack(anchor='w', padx=10, pady=5)
self.recursive_var = tk.BooleanVar(value=True)
self.recursive_check = ttk.Checkbutton(master, text="Search subdirectories", variable=self.recursive_var)
self.recursive_check.pack(anchor='w', padx=10, pady=5)
self.convert_button = ttk.Button(master, text="Convert", command=self.convert)
self.convert_button.pack(anchor='w', padx=10, pady=5)
# Console Output
self.console_output = scrolledtext.ScrolledText(master, width=80, height=20, wrap=tk.WORD)
self.console_output.pack(anchor='w', padx=10, pady=10)
def browse(self):
file_path = filedialog.askdirectory()
self.path_entry.delete(0, tk.END)
self.path_entry.insert(0, file_path)
def convert(self):
path = self.path_entry.get()
remove = self.remove_var.get()
overwrite = self.overwrite_var.get()
recursive = self.recursive_var.get()
output_text = ""
if os.path.isdir(path):
output_text += f'Converting HEIC files in directory {path}\n'
converted = convert_heic_to_jpeg(path, recursive, overwrite, remove)
output_text += f'Successfully converted {len(converted)} files\n'
elif os.path.isfile(path):
output_text += f'Converting HEIC file {path}\n'
convert_heic_file(path, os.path.splitext(path)[0] + ".jpg", overwrite, remove)
output_text += 'Successfully converted file\n'
else:
output_text += f'Don\'t know what to do with {path}\n'
self.console_output.insert(tk.END, output_text)
self.console_output.see(tk.END)
def main():
root = tk.Tk()
gui = HEICConverterGUI(root)
root.mainloop()
if __name__ == '__main__':
main()
@@ -0,0 +1,3 @@
pillow>=9.2.0
pillow_heif>=0.18.0
piexif==1.1.3