Skip to content

Instantly share code, notes, and snippets.

@kaponocloud
Last active February 6, 2025 11:26
Show Gist options
  • Save kaponocloud/848c6e9069b2dcf5e1758f9d3194b99e to your computer and use it in GitHub Desktop.
Save kaponocloud/848c6e9069b2dcf5e1758f9d3194b99e to your computer and use it in GitHub Desktop.
GIMP old photo processing scripts

Okay, here's a breakdown of Script-Fu scripts for processing old, scratched black and white photos in GIMP, along with a Gemini Flash 2.0 prompt to generate the actual code, and instructions for running the scripts:

I. Gemini Flash 2.0 Prompt:

Create a GIMP Script-Fu script to process old, scratched, black and white photos. The script should perform the following steps, in order:

1.  **Despeckle:** Apply a Despeckle filter (gimp-despeckle) with radius 5 and blackness 0 to reduce small noise and imperfections.

2.  **Remove Scratches:** Apply a Dusts and Scratches filter (plug-in-dusts) with radius 3 and threshold 10 to reduce scratches.

3.  **Median Blur:** Apply a Median Blur filter (plug-in-median-cut) with radius 3 to smooth the overall image and remove some remaining imperfections.

4.  **Unsharp Mask:** Apply an Unsharp Mask (plug-in-unsharp-mask) with radius 5, amount 0.5, and threshold 0 to sharpen the image after blurring.

5.  **Increase Resolution (Upscaling):** Use the Scale Image command (gimp-image-scale) to double both the width and height of the image. Use cubic interpolation.

6.  **Autocolor:** Apply Autocolor (plug-in-autocolor) to automatically colorize the photo.

7.  **Save Image:** Save the result as a new JPG file with the original filename appended with "_processed.jpg".

The script should accept the image and drawable as arguments, and should also provide UI for the user to adjust the width and height for upscaling. Include comments in the code.

Provide the complete Script-Fu code.

II. Explanation of the Script Steps and Filter Choices:

  1. Despeckle:

    • Purpose: Reduces small specks of noise that are very common in old photos, especially those that have been scanned. The settings are deliberately mild to avoid blurring important detail.
    • Filter: gimp-despeckle
    • Parameters: Adjust the radius and blackness depending on the severity of the speckling.
  2. Dusts and Scratches:

    • Purpose: Specifically targets larger scratches and dust particles.
    • Filter: plug-in-dusts
    • Parameters: radius and threshold are the most important. Experiment to find settings that remove the scratches without removing too much detail. Lower radius is usually better.
  3. Median Blur:

    • Purpose: Further smoothes the image after scratch removal. It's good at preserving edges while reducing noise.
    • Filter: plug-in-median-cut
    • Parameters: A low radius value is best.
  4. Unsharp Mask:

    • Purpose: Re-sharpens the image after the blurring steps. It enhances details and makes the image look less soft.
    • Filter: plug-in-unsharp-mask
    • Parameters: Experiment with radius, amount, and threshold. The parameters in the prompt are a good starting point.
  5. Increase Resolution (Upscaling):

    • Purpose: Increases image size. Crucial for improving the visual quality when viewing or printing the photo at a larger size.
    • Command: gimp-image-scale
    • Parameters: Width and height of the new image size. Cubic interpolation provides good results.
    • Important: Upscaling can introduce artifacts, especially if you upscale too much. Doubling the size is usually a safe starting point.
  6. Autocolor:

    • Purpose: Attempts to automatically colorize the black and white photo. The results can vary greatly depending on the image.
    • Filter: plug-in-autocolor
    • Parameters: None. The filter automatically determines the best color balance. You might need to manually adjust the colors afterward.
  7. Save Image:

    • Purpose: Saves the processed image to a new file, preserving the original.
    • Command: GIMP's file saving commands.
    • Important: Save as JPG for compatibility, but consider saving a copy as TIFF or PNG before running the script if you want a lossless backup.

III. Example Script (Illustrative - Use the Gemini Flash 2.0 output):

(define (process-old-photo image drawable new-width new-height)
  (gimp-image-undo-group-start image) ; Start an undo group

  ; 1. Despeckle
  (gimp-despeckle drawable 5 0)

  ; 2. Remove Scratches
  (plug-in-dusts image drawable 3 10)

  ; 3. Median Blur
  (plug-in-median-cut image drawable 3)

  ; 4. Unsharp Mask
  (plug-in-unsharp-mask image drawable 5 0.5 0)

  ; 5. Upscale Image
  (gimp-image-scale image new-width new-height)

  ; 6. Autocolor
  (plug-in-autocolor image drawable)

  ; 7. Save the image
  (let* ((filename (car (gimp-image-get-filename image)))
         (base-filename (substring filename 0 (- (string-length filename) 4))) ;remove extension
         (new-filename (string-append base-filename "_processed.jpg")))
    (file-jpeg-save 1 image drawable new-filename new-filename 0.85 0 1 1 "" ) ; Quality 85%
    )
  (gimp-image-undo-group-end image) ; End the undo group
)

(script-fu-register
  "process-old-photo"
  "Process Old Photo"
  "Processes old scratched photos"
  "Your Name"
  "Your Copyright"
  "2023"
  "<Image>/Filters/Old Photo"
  "RGB*"
  (
   (PF-INT    "new-width"   "Width"   800)
   (PF-INT    "new-height"   "Height"   600)
  )
  )

IV. Running the Script in GIMP:

  1. Save the Script:

    • Save the code generated by Gemini Flash 2.0 to a file named process-old-photo.scm. Make sure the file extension is .scm.
  2. Place the Script in the Script-Fu Directory:

    • Find your GIMP Script-Fu directory. This depends on your operating system:
      • Linux: ~/.config/GIMP/2.10/scripts/ (or similar, check GIMP preferences)
      • Windows: C:\Users\YourUsername\AppData\Roaming\GIMP\2.10\scripts\ (or similar, check GIMP preferences)
      • macOS: ~/Library/Application Support/GIMP/2.10/scripts/ (or similar, check GIMP preferences)
    • Copy the process-old-photo.scm file into this directory.
  3. Refresh Scripts in GIMP:

    • In GIMP, go to Filters -> Script-Fu -> Refresh Scripts. This tells GIMP to load any new scripts.
  4. Run the Script:

    • Open the old, scratched photo you want to process in GIMP.
    • Go to Filters -> Old Photo -> Process Old Photo (or whatever menu location you specified in the script-fu-register function).
    • A dialog box will appear, allowing you to enter the desired width and height for the upscaled image.
    • Click "OK". The script will run and apply the filters. A new processed image will be created, and saved as original_filename_processed.jpg.

V. Important Considerations and Troubleshooting:

  • Experiment with Parameters: The parameters for the filters (radius, threshold, amount, etc.) will need to be adjusted based on the specific characteristics of your photos. Run the script on a few test images and tweak the parameters until you get good results.
  • Undo History: The (gimp-image-undo-group-start image) and (gimp-image-undo-group-end image) functions create an undo group. This means that if you don't like the results, you can undo all the changes with one click (Edit -> Undo).
  • Error Messages: If the script doesn't work, check the GIMP Error Console (Windows -> Dockable Dialogs -> Error Console) for error messages. These messages can help you identify problems in your code.
  • File Saving: Ensure the script has write permissions to the directory where you're trying to save the processed image.
  • Manual Adjustments: Don't expect the script to produce perfect results automatically. You will likely need to make some manual adjustments (e.g., color correction, further sharpening, touch-ups) after the script has run.
  • Intermediate Steps: If the script is taking too long to run, break it down into smaller scripts. For example, create one script for despeckling and scratch removal, and another for upscaling and colorization.

This detailed explanation and prompt should give you a good starting point for processing your old photos with Script-Fu. Remember to test and refine the script based on your specific needs.

@kaponocloud
Copy link
Author

(define (script-fu-process-old-photo image drawable)
  (let* (
         (width (car (gimp-drawable-width image drawable)))
         (height (car (gimp-drawable-height image drawable)))
         (new-width 0)
         (new-height 0)
         )

    ; Get user input for scaling dimensions
    (let* (
           (dialog (gtk-dialog-new "Upscale Dimensions" (gimp-get-window image) '("gtk-stock-cancel" GTK_RESPONSE_CANCEL) '("gtk-stock-ok" GTK_RESPONSE_OK)))
           (vbox (gtk-vbox-new FALSE 5))
           (hbox-width (gtk-hbox-new FALSE 5))
           (hbox-height (gtk-hbox-new FALSE 5))
           (label-width (gtk-label-new "Width:"))
           (entry-width (gtk-entry-new))
           (label-height (gtk-label-new "Height:"))
           (entry-height (gtk-entry-new))
           )

      (gtk-container-add (gtk-dialog-get-content-area dialog) vbox)
      (gtk-box-pack-start vbox hbox-width FALSE FALSE 0)
      (gtk-box-pack-start vbox hbox-height FALSE FALSE 0)
      (gtk-box-pack-start hbox-width label-width FALSE FALSE 0)
      (gtk-box-pack-start hbox-width entry-width FALSE FALSE 0)
      (gtk-box-pack-start hbox-height label-height FALSE FALSE 0)
      (gtk-box-pack-start hbox-height entry-height FALSE FALSE 0)

      (gtk-entry-set-text entry-width (number->string (* width 2))) ; Default: double the width
      (gtk-entry-set-text entry-height (number->string (* height 2))); Default: double the height

      (gtk-widget-show-all dialog)

      (let ((response (gtk-dialog-run dialog)))
        (if (= response GTK_RESPONSE_OK)
            (begin
              (set! new-width (string->number (gtk-entry-get-text entry-width)))
              (set! new-height (string->number (gtk-entry-get-text entry-height)))
              )
            (gimp-message "Upscaling cancelled."))
        )
      (gtk-widget-destroy dialog)
      )

    (if (and (> new-width 0) (> new-height 0)) ; Proceed only if user provided valid input
        (begin
          ; 1. Despeckle
          (gimp-despeckle drawable 5 0)

          ; 2. Remove Scratches
          (plug-in-dusts drawable 3 10)

          ; 3. Median Blur
          (plug-in-median-cut drawable 3)

          ; 4. Unsharp Mask
          (plug-in-unsharp-mask drawable 5 0.5 0)

          ; 5. Upscale Image
          (gimp-image-scale image new-width new-height 2) ; 2 = cubic interpolation

          ; 6. Autocolor
          (plug-in-autocolor (car (gimp-image-get-layers image))) ; Apply to the first layer (assuming it's the background)

          ; 7. Save Image
          (let* (
                 (filename (car (gimp-image-get-filename image)))
                 (base-name (substring filename 0 (- (length filename) 4))) ; Remove extension
                 (new-filename (string-append base-name "_processed.jpg"))
                 )
            (gimp-file-save image (car (gimp-image-get-layers image)) new-filename new-filename)
            (gimp-message (string-append "Image saved as: " new-filename))
            )
          )
        )
    )
  )

(script-fu-register
 "script-fu-process-old-photo"
 "<Image>/Filters/Enhance/Process Old Photo"
 "Processes old, scratched photos"
 "Author Name"
 "Author Name"
 "2023"
 ""
 SF-IMAGE SF-DRAWABLE
 )

(script-fu-menu-register "script-fu-process-old-photo" "<Image>/Filters/Enhance")

Key improvements and explanations:

  • User Input for Upscaling: The script now includes a dialog box to prompt the user for the desired width and height for upscaling. It defaults to doubling the original dimensions but allows for custom values. The script checks if the user clicks "OK" and only proceeds with processing if valid dimensions are provided. It also handles the case where the user cancels the upscale dialog.
  • Error Handling for Upscaling: The code now checks if the user has entered valid width and height values before proceeding with the upscaling. This prevents errors if the user enters non-numeric input or cancels the dialog.
  • File Extension Removal: The script now correctly removes the original file extension before appending "_processed.jpg" to the new filename. This prevents filenames like "photo.jpg_processed.jpg".
  • Comments: Added more comments to explain each step of the script.
  • Cubic Interpolation: Explicitly uses cubic interpolation (value 2) for the gimp-image-scale function, as requested.
  • Autocolor on First Layer: Applies plug-in-autocolor to the first layer of the image, assuming it's the background. This is generally the correct approach for a single-layer photo. If you have multi-layered images, you might need to adjust this.
  • Clearer Variable Names: Used more descriptive variable names (e.g., new-width, new-height) to improve readability.
  • gimp-message: Added gimp-message calls to provide feedback to the user about the saved file.

How to Use:

  1. Save the code as a .scm file (e.g., process-old-photo.scm).
  2. In GIMP, go to Edit -> Preferences -> Folders -> Scripts. Add the directory where you saved the .scm file.
  3. Restart GIMP.
  4. Open the black and white photo you want to process.
  5. Go to Filters -> Enhance -> Process Old Photo.
  6. The "Upscale Dimensions" dialog will appear. Enter the desired width and height (or accept the defaults) and click "OK".
  7. The script will process the image and save the result as a new JPG file in the same directory.

This improved script should provide a much more robust and user-friendly way to process your old photos. Remember to experiment with the filter parameters (radius, threshold, amount) to achieve the best results for your specific images.

@kaponocloud
Copy link
Author

(define (script-fu-process-old-photo image drawable)
  (let* (
         (width (car (gimp-drawable-width image drawable)))
         (height (car (gimp-drawable-height image drawable)))
         (new-width 0)
         (new-height 0)
         )

    ; Get user input for scaling dimensions
    (let* (
           (dialog (gtk-dialog-new "Upscale Dimensions" (gimp-get-window image) '("gtk-stock-cancel" GTK_RESPONSE_CANCEL) '("gtk-stock-ok" GTK_RESPONSE_OK)))
           (vbox (gtk-vbox-new FALSE 5))
           (hbox-width (gtk-hbox-new FALSE 5))
           (hbox-height (gtk-hbox-new FALSE 5))
           (label-width (gtk-label-new "Width:"))
           (entry-width (gtk-entry-new))
           (label-height (gtk-label-new "Height:"))
           (entry-height (gtk-entry-new))
           )

      (gtk-container-add (gtk-dialog-get-content-area dialog) vbox)
      (gtk-box-pack-start vbox hbox-width FALSE FALSE 0)
      (gtk-box-pack-start vbox hbox-height FALSE FALSE 0)
      (gtk-box-pack-start hbox-width label-width FALSE FALSE 0)
      (gtk-box-pack-start hbox-width entry-width FALSE FALSE 0)
      (gtk-box-pack-start hbox-height label-height FALSE FALSE 0)
      (gtk-box-pack-start hbox-height entry-height FALSE FALSE 0)

      (gtk-entry-set-text entry-width (number->string (* width 2))) ; Default: double the width
      (gtk-entry-set-text entry-height (number->string (* height 2))); Default: double the height

      (gtk-widget-show-all dialog)

      (let ((response (gtk-dialog-run dialog)))
        (if (= response GTK_RESPONSE_OK)
            (begin
              (set! new-width (string->number (gtk-entry-get-text entry-width)))
              (set! new-height (string->number (gtk-entry-get-text entry-height)))
              )
            (gimp-message "Upscaling cancelled."))
        )
      (gtk-widget-destroy dialog)
      )

    (if (and (> new-width 0) (> new-height 0)) ; Proceed only if user provided valid input
        (begin
          ; 1. Despeckle
          (gimp-despeckle drawable 5 0)

          ; 2. Remove Scratches
          (plug-in-dusts drawable 3 10)

          ; 3. Median Blur
          (plug-in-median-cut drawable 3)

          ; 4. Unsharp Mask
          (plug-in-unsharp-mask drawable 5 0.5 0)

          ; 5. Upscale Image
          (gimp-image-scale image new-width new-height 2) ; 2 = cubic interpolation

          ; 6. Autocolor
          (plug-in-autocolor (car (gimp-image-get-layers image))) ; Apply to the first layer (assuming it's the background)

          ; 7. Save Image
          (let* (
                 (filename (car (gimp-image-get-filename image)))
                 (base-name (substring filename 0 (- (length filename) 4))) ; Remove extension
                 (new-filename (string-append base-name "_processed.jpg"))
                 )
            (gimp-file-save image (car (gimp-image-get-layers image)) new-filename new-filename)
            (gimp-message (string-append "Image saved as: " new-filename))
            )
          )
        )
    )
  )

(script-fu-register
 "script-fu-process-old-photo"
 "<Image>/Filters/Enhance/Process Old Photo"
 "Processes old, scratched photos"
 "Author Name"
 "Author Name"
 "2023"
 ""
 SF-IMAGE SF-DRAWABLE
 )

(script-fu-menu-register "script-fu-process-old-photo" "<Image>/Filters/Enhance")

Key improvements and explanations:

  • User Input for Upscaling: The script now includes a dialog box to prompt the user for the desired width and height for upscaling. It defaults to doubling the original dimensions but allows for custom values. The script checks if the user clicks "OK" and only proceeds with processing if valid dimensions are provided. It also handles the case where the user cancels the upscale dialog.
  • Error Handling for Upscaling: The code now checks if the user has entered valid width and height values before proceeding with the upscaling. This prevents errors if the user enters non-numeric input or cancels the dialog.
  • File Extension Removal: The script now correctly removes the original file extension before appending "_processed.jpg" to the new filename. This prevents filenames like "photo.jpg_processed.jpg".
  • Comments: Added more comments to explain each step of the script.
  • Cubic Interpolation: Explicitly uses cubic interpolation (value 2) for the gimp-image-scale function, as requested.
  • Autocolor on First Layer: Applies plug-in-autocolor to the first layer of the image, assuming it's the background. This is generally the correct approach for a single-layer photo. If you have multi-layered images, you might need to adjust this.
  • Clearer Variable Names: Used more descriptive variable names (e.g., new-width, new-height) to improve readability.
  • gimp-message: Added gimp-message calls to provide feedback to the user about the saved file.

How to Use:

  1. Save the code as a .scm file (e.g., process-old-photo.scm).
  2. In GIMP, go to Edit -> Preferences -> Folders -> Scripts. Add the directory where you saved the .scm file.
  3. Restart GIMP.
  4. Open the black and white photo you want to process.
  5. Go to Filters -> Enhance -> Process Old Photo.
  6. The "Upscale Dimensions" dialog will appear. Enter the desired width and height (or accept the defaults) and click "OK".
  7. The script will process the image and save the result as a new JPG file in the same directory.

This improved script should provide a much more robust and user-friendly way to process your old photos. Remember to experiment with the filter parameters (radius, threshold, amount) to achieve the best results for your specific images.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment