Last active
February 24, 2026 03:53
-
-
Save anthonyryan1/33b98f3caf50f7bee2bd09fbb37cc7fd to your computer and use it in GitHub Desktop.
GNOME/simple-scan ICC application through post-processing
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 | |
| import os | |
| import sys | |
| import subprocess | |
| import tempfile | |
| import shutil | |
| # Make sure you have imagemagick with lcms support | |
| # Update the path to your ICC | |
| # Save this somewhere, make it +x | |
| # and point simple-scan post-processing at it | |
| SCANNER_PROFILE = "/home/yourusername/path/to/your.icc" | |
| sRGB_PROFILE = "/usr/share/color/icc/colord/sRGB.icc" | |
| import gi | |
| gi.require_version('Notify', '0.7') | |
| from gi.repository import Notify | |
| def send_notification(title, message, icon="scanner"): | |
| if not Notify.is_initted(): | |
| Notify.init("Simple Scan Post-Processor") | |
| # Create and show the notification | |
| notification = Notify.Notification.new(title, message, icon) | |
| notification.show() | |
| # simple-scan passes at least 3 arguments: | |
| # sys.argv[1] = mime-type | |
| # sys.argv[2] = keep-origin | |
| # sys.argv[3] = input-file | |
| if len(sys.argv) < 4: | |
| print("Error: Expected at least 3 arguments from simple-scan.", file=sys.stderr) | |
| sys.exit(1) | |
| mime_type = sys.argv[1] | |
| keep_origin = sys.argv[2] | |
| scan_file = sys.argv[3] | |
| if not os.path.isfile(scan_file): | |
| print(f"Error: File '{scan_file}' does not exist.", file=sys.stderr) | |
| sys.exit(1) | |
| # Only process PNG files | |
| if mime_type != 'image/png' and not scan_file.lower().endswith('.png'): | |
| print(f"Skipping '{scan_file}': Not a PNG file (MIME: {mime_type}).") | |
| sys.exit(0) | |
| # Verify profiles exist | |
| for profile in [SCANNER_PROFILE, sRGB_PROFILE]: | |
| if not os.path.isfile(profile): | |
| error_msg = f"ICC profile not found:\n{profile}" | |
| print(error_msg, file=sys.stderr) | |
| send_notification("Scan Processing Failed", error_msg, "dialog-error") | |
| sys.exit(1) | |
| # Create a secure temporary file for the ImageMagick output | |
| fd, temp_file = tempfile.mkstemp(suffix='.png', prefix='scan_hook_') | |
| os.close(fd) | |
| try: | |
| # Construct the ImageMagick command | |
| cmd = [ | |
| "magick", | |
| scan_file, | |
| "-profile", SCANNER_PROFILE, | |
| "-profile", sRGB_PROFILE, | |
| temp_file | |
| ] | |
| print(f"Applying color profiles to '{scan_file}'...") | |
| # Run the command | |
| result = subprocess.run(cmd, capture_output=True, text=True) | |
| if result.returncode == 0: | |
| # Safely replace the original file | |
| shutil.move(temp_file, scan_file) | |
| filename = os.path.basename(scan_file) | |
| print(f"Successfully processed and replaced '{scan_file}'.") | |
| # Send success notification | |
| send_notification( | |
| "Scan Processed", | |
| f"Color profiles applied to {filename}", | |
| "image-x-generic" | |
| ) | |
| else: | |
| print(f"ImageMagick failed with error:\n{result.stderr}", file=sys.stderr) | |
| os.remove(temp_file) | |
| # Send failure notification | |
| send_notification( | |
| "Scan Processing Failed", | |
| "ImageMagick encountered an error.", | |
| "dialog-error" | |
| ) | |
| sys.exit(1) | |
| except Exception as e: | |
| print(f"An unexpected error occurred: {e}", file=sys.stderr) | |
| if os.path.exists(temp_file): | |
| os.remove(temp_file) | |
| send_notification( | |
| "Scan Processing Error", | |
| str(e), | |
| "dialog-error" | |
| ) | |
| sys.exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment