Last active
June 18, 2026 10:20
-
-
Save alea12/e5ca0b249a2374def2f773de7e0284d2 to your computer and use it in GitHub Desktop.
bmp_to_tiff_converter.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| BMP → TIFF Converter (Updated - Cleaner Logging) | |
| """ | |
| import argparse | |
| import tkinter as tk | |
| from tkinter import filedialog, messagebox | |
| from pathlib import Path | |
| from collections import defaultdict | |
| from PIL import Image | |
| def convert_bmp_to_tiff(root_dir: str): | |
| root_path = Path(root_dir).resolve() | |
| if not root_path.exists() or not root_path.is_dir(): | |
| print(f"ERROR: '{root_path}' is not a valid folder.") | |
| return | |
| print(f"Scanning: {root_path}") | |
| print("-" * 60) | |
| # Find all BMP files (handles both .bmp and .BMP) | |
| bmp_files = list(root_path.rglob("*.bmp")) + list(root_path.rglob("*.BMP")) | |
| if not bmp_files: | |
| print("No BMP files found.") | |
| return | |
| # Group by parent folder | |
| bmps_by_dir = defaultdict(list) | |
| for bmp in bmp_files: | |
| bmps_by_dir[bmp.parent].append(bmp) | |
| total_converted = 0 | |
| total_skipped = 0 | |
| folders_processed = 0 | |
| for dir_path, bmp_list in sorted(bmps_by_dir.items()): | |
| tiff_dir = dir_path / "TIFF" | |
| tiff_dir.mkdir(exist_ok=True) | |
| new_in_this_folder = 0 | |
| skipped_in_this_folder = 0 | |
| for bmp_path in sorted(bmp_list): | |
| tif_path = tiff_dir / (bmp_path.stem + ".TIF") | |
| if tif_path.exists(): | |
| skipped_in_this_folder += 1 | |
| continue | |
| try: | |
| with Image.open(bmp_path) as img: | |
| img.save(tif_path, format="TIFF") | |
| print(f"✅ {dir_path.name}/{bmp_path.name} → TIFF/{tif_path.name}") | |
| new_in_this_folder += 1 | |
| total_converted += 1 | |
| except Exception as e: | |
| print(f"❌ ERROR: {bmp_path} → {e}") | |
| total_skipped += skipped_in_this_folder | |
| folders_processed += 1 | |
| # Clean per-folder summary | |
| if new_in_this_folder > 0 or skipped_in_this_folder > 0: | |
| print(f" → {new_in_this_folder} new | {skipped_in_this_folder} already existed") | |
| print("\n" + "=" * 60) | |
| print("CONVERSION COMPLETE") | |
| print(f" Folders processed : {folders_processed}") | |
| print(f" Newly converted : {total_converted}") | |
| print(f" Already existed : {total_skipped}") | |
| print("=" * 60) | |
| def main(): | |
| parser = argparse.ArgumentParser( | |
| description="Convert BMP files to TIFF (creates TIFF/ subfolder). Skips files that already exist." | |
| ) | |
| parser.add_argument( | |
| "root_folder", | |
| nargs="?", | |
| default=None, | |
| help="Root folder (optional - shows folder picker if omitted)" | |
| ) | |
| args = parser.parse_args() | |
| if args.root_folder: | |
| root_dir = args.root_folder | |
| else: | |
| root = tk.Tk() | |
| root.withdraw() | |
| root.attributes("-topmost", True) | |
| root_dir = filedialog.askdirectory(title="Select root folder containing BMPs") | |
| root.destroy() | |
| if not root_dir: | |
| messagebox.showinfo("Cancelled", "No folder selected.") | |
| return | |
| convert_bmp_to_tiff(root_dir) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment