|
| 1 | +--- |
| 2 | +title: Batch Process |
| 3 | +type: docs |
| 4 | +url: "/hub/practical-applications/Batch-Process" |
| 5 | +--- |
| 6 | + |
| 7 | +## Introduction |
| 8 | + |
| 9 | +The [**Batch Process**](../../plug-ins/folder/Batch-Process/) plug-in is an advanced practical example that demonstrates building a flexible batch processing framework in Script-Fu. The **standalone version** is approximately **850 lines** (all libraries inlined), providing a complete working example that can be used as-is or customized. |
| 10 | + |
| 11 | +The heavy lifting (directory recursion, file discovery, validation, progress reporting, image lifecycle management) lives in inlined library functions. The plug-in demonstrates a complete workflow: |
| 12 | + |
| 13 | +1. **GUI parameters** - source, destination, display options |
| 14 | +2. **Processing logic** - scale down, sharpen, and prepare for export |
| 15 | +3. **Export logic** - save as CMYK PSD with color profile |
| 16 | +4. **Resource management** - properly handle displays and temporary images |
| 17 | + |
| 18 | +## Getting Started |
| 19 | + |
| 20 | +**This plug-in is ready to use!** Just configure these values at the top of the file: |
| 21 | + |
| 22 | +- **`default-src-dir`** (line 34) - Your default source directory |
| 23 | +- **`default-dst-dir`** (line 35) - Your default destination directory |
| 24 | +- **`softproof-icc`** (line 33) - Path to your ICC color profile (or set to `""` if not using) |
| 25 | + |
| 26 | +You can also set these paths through the GUI when running the plug-in. The defaults are only used as fallbacks if the GUI paths are invalid. |
| 27 | + |
| 28 | +The example processing function creates a 50% scaled-down version of each image with sharpening applied—a common workflow for creating web/social media versions from high-res originals. |
| 29 | + |
| 30 | +## Two Operating Modes |
| 31 | + |
| 32 | +The plug-in supports two distinct workflows: |
| 33 | + |
| 34 | +### 1. File System Mode (Default) |
| 35 | +- Recursively discovers files in a source directory |
| 36 | +- Loads each file, processes it, exports to destination, closes it |
| 37 | +- Perfect for batch processing entire folder hierarchies |
| 38 | +- Uses `.xcf` extension by default (easily configurable) |
| 39 | + |
| 40 | +### 2. Open Images Mode |
| 41 | +- Processes images already open in GIMP |
| 42 | +- Does **not** close them afterward (preserves user's workspace) |
| 43 | +- Ideal for processing multiple images you're actively working on |
| 44 | +- Source directory parameter ignored in this mode |
| 45 | + |
| 46 | +## Architecture Overview |
| 47 | + |
| 48 | +Here's the high-level structure of the batch processing plug-in: |
| 49 | + |
| 50 | +```scheme |
| 51 | +(define (script-fu-batch-process gui-src-dir |
| 52 | + gui-dst-dir |
| 53 | + show-images |
| 54 | + use-open-images) |
| 55 | + (let ((success (if (is-true? use-open-images) |
| 56 | + (batch-process-open-images gui-dst-dir |
| 57 | + default-dst-dir |
| 58 | + image-process |
| 59 | + export-process) |
| 60 | + (batch-process-file-system gui-src-dir |
| 61 | + default-src-dir |
| 62 | + "xcf" |
| 63 | + gui-dst-dir |
| 64 | + default-dst-dir |
| 65 | + show-images |
| 66 | + image-process |
| 67 | + export-process)))) |
| 68 | + (unless success |
| 69 | + (message-box (if (is-true? use-open-images) |
| 70 | + "No open images found." |
| 71 | + "No .xcf files found in source directory."))))) |
| 72 | +``` |
| 73 | + |
| 74 | +The main function is simple: |
| 75 | + |
| 76 | +1. Chooses the appropriate batch function based on mode |
| 77 | +2. Passes custom processing and export functions |
| 78 | +3. Reports if nothing was processed |
| 79 | + |
| 80 | +## The Processing Pipeline |
| 81 | + |
| 82 | +Each image goes through this sequence: |
| 83 | + |
| 84 | +### File System Mode: |
| 85 | +1. **Discover** - Recursively find all matching files |
| 86 | +2. **Load** - Open the file in GIMP |
| 87 | +3. **Display** (optional) - Show it on screen during processing |
| 88 | +4. **Process** - Call `image-process` function |
| 89 | +5. **Export** - Call `export-process` function with result |
| 90 | +6. **Clean up** - Close display and image (we loaded it, we close it) |
| 91 | + |
| 92 | +### Open Images Mode: |
| 93 | +1. **List** - Get all currently open images |
| 94 | +2. **Process** - Call `image-process` function |
| 95 | +3. **Export** - Call `export-process` function with result |
| 96 | +4. **Clean up** - Close only export image if created (never the original) |
| 97 | + |
| 98 | +## Custom Processing Function |
| 99 | + |
| 100 | +The `image-process` function defines what happens to each image. The example creates a scaled-down, sharpened version: |
| 101 | + |
| 102 | +```scheme |
| 103 | +(define (image-process src-image drawables) |
| 104 | + (gimp-context-push) |
| 105 | + (gimp-context-set-interpolation INTERPOLATION-CUBIC) |
| 106 | + ;; Create an image by copying and pasting to a new image |
| 107 | + (gimp-selection-none src-image) |
| 108 | + (gimp-edit-copy-visible src-image) |
| 109 | + (let* ((dst-image (edit-paste-as-new-image)) |
| 110 | + (dst-display (display-new dst-image)) |
| 111 | + (active-layer (get-active-layers-list dst-image #t)) |
| 112 | + (scale 50) |
| 113 | + (sharpen 0.25)) |
| 114 | + ;; Image reduction |
| 115 | + (image-scale-by-percent dst-image scale scale) |
| 116 | + ;; Post scale sharpen |
| 117 | + (gegl-sharpen active-layer LAYER-MODE-REPLACE 100 3 sharpen 0 #t #f) |
| 118 | + ;; Name the layer |
| 119 | + (gimp-item-set-name active-layer (image-get-base-name src-image)) |
| 120 | + (gimp-displays-flush) |
| 121 | + (gimp-context-pop) |
| 122 | + (message "Prepared image for export") |
| 123 | + ;; Return image ID and display of the created image |
| 124 | + (list dst-image dst-display))) |
| 125 | +``` |
| 126 | + |
| 127 | +**Key points about this function:** |
| 128 | + |
| 129 | +- **Returns a list**: `(list dst-image dst-display)` - both the processed image ID and its display ID |
| 130 | +- **Creates a new image**: Uses copy-paste to avoid modifying the source |
| 131 | +- **Shows the result**: Creates a display so you can see processing in real-time (if enabled) |
| 132 | +- **Clean processing**: The batch framework handles closing the display afterward |
| 133 | + |
| 134 | +The return value pattern is important: by returning both the image and display IDs, the framework can properly clean up all resources (close the display window and delete the temporary image) after export. |
| 135 | + |
| 136 | +## Custom Export Function |
| 137 | + |
| 138 | +The `export-process` function defines how to save the result: |
| 139 | + |
| 140 | +```scheme |
| 141 | +(define (export-process image dst-file) |
| 142 | + (file-cmyk-psd-save image dst-file softproof-icc)) |
| 143 | +``` |
| 144 | + |
| 145 | +This uses the global `softproof-icc` variable defined at the top of the file. The export saves as a PSD with CMYK color conversion using the specified ICC profile. |
| 146 | + |
| 147 | +## Path Validation Strategy |
| 148 | + |
| 149 | +The plug-in implements a robust fallback system: |
| 150 | + |
| 151 | +1. **Try GUI path** - Use what the user entered |
| 152 | +2. **Validate format** - Check for invalid characters, empty strings |
| 153 | +3. **Validate existence** - Check if directory actually exists |
| 154 | +4. **Fall back to default** - Use hardcoded path if GUI path invalid |
| 155 | +5. **Exit with error** - If even the fallback is invalid |
| 156 | + |
| 157 | +This ensures the plug-in never tries to process with invalid paths, and provides clear error messages when something is wrong. |
| 158 | + |
| 159 | +## Flat Export Structure |
| 160 | + |
| 161 | +The export uses a **flat directory structure**: |
| 162 | + |
| 163 | +``` |
| 164 | +Source: |
| 165 | + /art/project/ |
| 166 | + image1.xcf |
| 167 | + subdir/ |
| 168 | + image2.xcf |
| 169 | + deeper/ |
| 170 | + image3.xcf |
| 171 | +
|
| 172 | +Destination: |
| 173 | + /export/ |
| 174 | + image1.psd |
| 175 | + image2.psd |
| 176 | + image3.psd |
| 177 | +``` |
| 178 | + |
| 179 | +All files are exported to the destination root, regardless of source subdirectory depth. This simplifies export management and avoids recreating potentially deep directory structures. |
| 180 | + |
| 181 | +## Image Lifecycle Management |
| 182 | + |
| 183 | +The plug-in carefully manages which resources it closes: |
| 184 | + |
| 185 | +### File System Mode: |
| 186 | +- **Source image**: Loads image ➜ **Script owns it** ➜ Must close it |
| 187 | +- **Source display** (optional): Creates display ➜ **Script owns it** ➜ Must close it |
| 188 | +- **Export image**: Processing creates new image ➜ **Script owns it** ➜ Closed via display |
| 189 | +- **Export display**: Processing creates display ➜ **Script owns it** ➜ Must close it |
| 190 | + |
| 191 | +### Open Images Mode: |
| 192 | +- **Source image**: Already open ➜ **User owns it** ➜ **Never close it** |
| 193 | +- **Export image**: Processing creates new image ➜ **Script owns it** ➜ Closed via display |
| 194 | +- **Export display**: Processing creates display ➜ **Script owns it** ➜ Must close it |
| 195 | + |
| 196 | +**Important**: When you close a display with `gimp-display-delete`, GIMP automatically deletes the underlying image if it has no other displays. This is why the plug-in only needs to explicitly close displays—the images are cleaned up automatically. |
| 197 | + |
| 198 | +This ensures the plug-in never closes images the user expects to remain open, while properly cleaning up all temporary resources it creates. |
| 199 | + |
| 200 | + |
| 201 | +### 3. Adjust File Extension |
| 202 | + |
| 203 | +Change which files to process in the main function (around line 50): |
| 204 | + |
| 205 | +```scheme |
| 206 | +;; In script-fu-batch-process, change: |
| 207 | +(batch-process-file-system ... "xcf" ...) ; Original - process XCF files |
| 208 | +(batch-process-file-system ... "png" ...) ; Process PNG files instead |
| 209 | +(batch-process-file-system ... "jpg" ...) ; Process JPEG files instead |
| 210 | +``` |
| 211 | + |
| 212 | +### 4. Modify Default Paths |
| 213 | + |
| 214 | +Update the global variables at the top of the file (lines 33-35): |
| 215 | + |
| 216 | +```scheme |
| 217 | +;; Global variables |
| 218 | +(define debug #f) |
| 219 | +(define softproof-icc "/your/path/to/profile.icc") |
| 220 | +(define default-src-dir "/your/default/source/") |
| 221 | +(define default-dst-dir "/your/default/destination/") |
| 222 | +``` |
| 223 | + |
| 224 | +These paths are used as fallbacks if the GUI paths are invalid or empty. |
| 225 | + |
| 226 | +## Debug Mode |
| 227 | + |
| 228 | +Enable debug output by modifying the global variable: |
| 229 | + |
| 230 | +```scheme |
| 231 | +;; Global variables |
| 232 | +(define debug #f) |
| 233 | +``` |
| 234 | + |
| 235 | +Change to: |
| 236 | + |
| 237 | +```scheme |
| 238 | +;; Global variables |
| 239 | +(define debug #t) |
| 240 | +``` |
| 241 | + |
| 242 | +With debug mode enabled, you'll see detailed output in the Error Console: |
| 243 | + |
| 244 | +## Error Handling |
| 245 | + |
| 246 | +The plug-in includes comprehensive error handling: |
| 247 | + |
| 248 | +- **Invalid paths**: Clear error messages with path shown |
| 249 | +- **No files found**: User-friendly message box |
| 250 | +- **No open images**: Specific message for open images mode |
| 251 | +- **Missing file paths**: Skips untitled images with warning |
| 252 | + |
| 253 | +## Performance Considerations |
| 254 | + |
| 255 | +For large batch operations: |
| 256 | + |
| 257 | +- **Show images = OFF** is significantly faster (no display overhead) |
| 258 | +- **File system mode** processes files one at a time, freeing memory between files |
| 259 | +- **Open images mode** requires all images in memory simultaneously |
| 260 | +- Progress bar updates can slow processing slightly but provide valuable feedback |
| 261 | + |
| 262 | +## Conclusion |
| 263 | + |
| 264 | +The Batch Process framework demonstrates advanced Script-Fu techniques: |
| 265 | + |
| 266 | +- **Dual-mode operation** - Process files from disk OR already-open images |
| 267 | +- **Robust validation** - Path validation with fallbacks and error handling |
| 268 | +- **Flexible architecture** - Easy to customize for different processing needs |
| 269 | +- **Clean resource management** - Proper handling of images, displays, and temporary resources |
| 270 | +- **Progress reporting** - User feedback during long operations |
| 271 | +- **Return value patterns** - Demonstrates returning both image and display IDs for proper cleanup |
| 272 | +- **Complete example** - All libraries inlined, ready to use and learn from |
| 273 | + |
| 274 | +This is a **working example** that you can use as-is for creating scaled-down versions of images, or easily customize for your own batch processing needs. The standalone version (850+ lines) includes all necessary library functions, making it easy to study and understand the complete workflow. |
0 commit comments