Load Image with Metadata Crop
The LoadImage That Reads the Recipe and Passes You the Scissors
- cropped_image
- mask
- original_image
- prompt
- Metadata RAW
- BASE_FILENAME
- BASE_DIR
- crop_x
- crop_y
- crop_width
- crop_height
- height
- width
- original_height
- original_width
- zoom_factor
- megapixels
What it actually is
Every PNG that ComfyUI's SaveImage writes has the whole generation baked into the file as text chunks - the node graph, the prompt, the seed. Drag it back onto the canvas and the workflow rebuilds itself. This node is that trick made programmable: it loads an image, digs the embedded prompt and workflow back out, and hands them to you as data your graph can actually use. Then, because the pack it lives in is built around editing and upscaling crops via cloud APIs, it adds an optional crop - and tells you what it cropped and how zoomed-in that region was.
It's one of the utility nodes in trustypangolin/ComfyUI-API-DockerCPU, a pack whose whole reason to exist is running ComfyUI on machines with no GPU - VMs, cheap servers - and offloading inference to Replicate, Fal.ai, and HuggingFace. In that setup you're almost always editing an existing image: load it, crop the face or the background, send the crop to an upscaler or an edit model, put the result back. This loader is the front half of that pipeline.
How it works
The mechanism is straightforward and worth knowing because it explains the outputs. On load, the node reads the file's metadata: PNG workflow and prompt text chunks (parsed to JSON), JPEG EXIF tags, and WebP EXIF via piexif - ComfyUI's Prompt:/Workflow: prefixes get stripped first. If the file was re-encoded at any point, those chunks are gone and there's nothing to extract - this node reads what's still there, not what a screenshot or a Reddit repost deleted.
The crop is a plain PIL crop() clamped to the image bounds, and it computes a zoom factor: the diagonal of the full image divided by the diagonal of the crop. Crop a 1024×1024 image down to 512×512 and you get a zoom of 2.0. That number exists so you can upscale a crop, then composite it back onto the original at the right scale - which is exactly what an upscale-API workflow needs.
The inputs that matter
folder_type-inputoroutput, i.e. which ComfyUI folder the file dropdown lists. Defaultinput.image- the dropdown of files in that folder (you can upload directly).crop_x,crop_y,crop_width,crop_height- all default to-1, which means "no crop." Set all four to define the box.
That last one is the trap, so say it plainly: if any one of the four crop values is negative (or a width/height is 0), cropping is fully disabled and you get the whole image back. A beginner who sets only crop_width and stares at an uncropped result isn't broken - they just didn't set the other three.
What comes out
Seventeen outputs, but you'll reach for a handful. cropped_image and original_image are both IMAGE tensors, so you get to keep the full-resolution original while the crop flows downstream. mask is the inverted alpha channel of the crop - useful only if your source has transparency; a plain RGB file gives you a throwaway 64×64 zero mask, so don't go hunting for segmentation. prompt is the embedded generation JSON, and Metadata RAW is the full dict including workflow and EXIF. BASE_FILENAME and BASE_DIR feed the same pack's "Save Text With Filename" node, so you can dump the extracted prompt to a .txt named after the source image. Finally, the crop bookkeeping: crop_x/y/width/height (the actual clamped box), height/width, original_height/original_width, zoom_factor, and megapixels.
Installing it
Through ComfyUI Manager, search ComfyUI-API-DockerCPU and install. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/trustypangolin/ComfyUI-API-DockerCPU
cd ComfyUI-API-DockerCPU
pip install -r requirements.txt
Then restart ComfyUI. There are no model downloads - the pack's CPU build does zero local inference. For a genuinely GPU-less box there's a cpu-requirements.txt that pulls CPU-only PyTorch wheels instead of the CUDA ones. One note: the API nodes in this pack expect REPLICATE_API_TOKEN and FAL_KEY environment variables. This loader doesn't need them - it never touches the network - so if you're only here for the loader, install without keys and the API nodes will only complain when you actually run them.
Where people get burned
- Crop silently disabled. Re-read the four-input rule above; it's the most common "why isn't it cropping" post this node will generate.
- Missing metadata. You loaded a JPEG exported from an editor or a PNG that passed through an image host - the chunks are gone and
promptcomes back empty. Keep the original SaveImage PNG as your master file. - Mask is empty. Transparent-source-only; don't expect a region mask from an ordinary photo.
For its niche it's a genuinely useful little node - a metadata loader with a crop and a scale factor, wired for the CPU-API workflow it ships in. Not flashy, but it's the part that makes the flashy parts work.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| folder_type | COMBO | input | Which ComfyUI folder to load from. The image dropdown is refreshed automatically. |
| image | COMBO | 1 options: example.png | |
| crop_xopt | INT | -1-1–999999 | Left edge of crop. -1 disables cropping. |
| crop_yopt | INT | -1-1–999999 | Top edge of crop. -1 disables cropping. |
| crop_widthopt | INT | -1-1–999999 | Crop width. -1 disables cropping. |
| crop_heightopt | INT | -1-1–999999 | Crop height. -1 disables cropping. |
Outputs (17)
| Name | Type | Description |
|---|---|---|
| cropped_image | IMAGE | — |
| mask | MASK | — |
| original_image | IMAGE | — |
| prompt | JSON | — |
| Metadata RAW | METADATA_RAW | — |
| BASE_FILENAME | STRING | — |
| BASE_DIR | STRING | — |
| crop_x | INT | — |
| crop_y | INT | — |
| crop_width | INT | — |
| crop_height | INT | — |
| height | INT | — |
| width | INT | — |
| original_height | INT | — |
| original_width | INT | — |
| zoom_factor | FLOAT | — |
| megapixels | FLOAT | — |