Loading...
Loading...
Create and manipulate images using GIMP, Inkscape, ImageMagick, FFmpeg, ExifTool, OptiPNG, jpegoptim, and pdftoppm via CLI. Use for: resizing, cropping, compositing, text overlays, watermarks, color correction, format conversion, WebP export, SVG creation, SVG-to-PNG export, OG images, social banners, logo manipulation, batch processing, lossless compression, metadata read/strip, GIF creation, animation, PDF-to-image. Triggers: gimp, inkscape, imagemagick, resize image, crop image, convert image, svg to png, add text to image, watermark, composite, image editing, banner, social card, compress image, strip metadata, gif, pdf to image, webp.
npx skill4agent add ramon-webdevpro-nl/claude-skills gimp-inkscape| Task | Use | Notes |
|---|---|---|
| Simple resize | ImageMagick | 10× faster than GIMP, one liner |
| Batch resize folder | ImageMagick mogrify | Purpose-built for batch |
| SVG → PNG | Inkscape | Vector quality, exact dimensions |
| Text overlay / watermark | ImageMagick | Reliable; GIMP Script-Fu text is flaky |
| Complex typography | Inkscape SVG | Pixel-perfect vector text |
| Format conversion | ImageMagick | One liner, handles WebP too |
| Compositing / layers | GIMP | Full layer control |
| Color correction | GIMP | Curves/levels more precise than IM |
| PNG compression | OptiPNG | Lossless, 20–50% savings |
| JPEG compression | jpegoptim | Lossless recompression |
| Metadata read/strip | ExifTool | The industry standard |
| GIF / animation | FFmpeg | Nothing else handles this |
| PDF → image | pdftoppm | Clean, DPI-controllable |
| Photo editing (advanced) | GIMP | Healing, clone stamp, curves |
pip install rembgrembg i input.png output.pngconvert input.png output.jpg
convert input.jpg output.webp
convert input.png -quality 92 output.jpg# Exact dimensions (may distort)
convert input.jpg -resize 1200x630! output.jpg
# Fit within box (preserves aspect ratio)
convert input.jpg -resize 1200x630 output.jpg
# Fill and crop to exact dimensions (centered)
convert input.jpg -resize 1200x630^ -gravity Center -extent 1200x630 output.jpg# Resize all JPEGs in place
mogrify -resize 800x600 /path/to/folder/*.jpg
# Resize and output to a different folder
mogrify -resize 800x600 -path /output/folder /input/folder/*.jpg
# Convert all PNGs to WebP
mogrify -format webp /path/to/folder/*.png# Simple text in bottom-right corner
convert input.jpg \
-font DejaVu-Sans -pointsize 36 \
-fill white -annotate +20+40 "© ReshareAI" \
output.jpg
# Centered text with shadow
convert input.jpg \
-font DejaVu-Sans-Bold -pointsize 72 \
-fill black -annotate +202+302 "Headline" \
-fill white -annotate +200+300 "Headline" \
output.jpg
# Semi-transparent watermark tiled across image
convert input.jpg \
-font DejaVu-Sans -pointsize 48 -fill "rgba(255,255,255,0.3)" \
-gravity Center -annotate 30x30+0+0 "WATERMARK" \
output.jpg# Place logo.png bottom-right with 10px padding
convert base.jpg \
logo.png \
-gravity SouthEast -geometry +10+10 \
-composite output.jpg
# Place with opacity
convert base.jpg \
\( logo.png -alpha set -channel Alpha -evaluate multiply 0.5 \) \
-gravity Center -composite output.jpg# Brightness / contrast
convert input.jpg -brightness-contrast 10x20 output.jpg
# Saturation
convert input.jpg -modulate 100,130,100 output.jpg
# Grayscale
convert input.jpg -colorspace Gray output.jpg
# Sharpen
convert input.jpg -unsharp 0x1 output.jpgidentify input.jpg
identify -verbose input.jpg | grep -E "Geometry|Colorspace|Format|filesize"# PNG/JPEG → WebP
convert input.png -quality 85 output.webp
# WebP → PNG
convert input.webp output.png
# Batch convert all JPEGs to WebP
mogrify -format webp -quality 85 /path/to/folder/*.jpg# Basic
ffmpeg -i input.mp4 -vf "fps=10,scale=800:-1" output.gif
# High quality (uses palette)
ffmpeg -i input.mp4 -vf "fps=12,scale=800:-1:flags=lanczos,palettegen" palette.png
ffmpeg -i input.mp4 -i palette.png -vf "fps=12,scale=800:-1:flags=lanczos,paletteuse" output.gif
# Clip a section (start 5s, duration 3s)
ffmpeg -ss 5 -t 3 -i input.mp4 -vf "fps=10,scale=600:-1" output.gif# Extract every frame as PNG
ffmpeg -i input.mp4 /output/frame_%04d.png
# Extract 1 frame per second
ffmpeg -i input.mp4 -vf fps=1 /output/frame_%04d.png
# Extract a single frame at timestamp
ffmpeg -ss 00:00:05 -i input.mp4 -frames:v 1 output.png# Frames → MP4
ffmpeg -framerate 24 -i frame_%04d.png -c:v libx264 output.mp4
# Frames → GIF
ffmpeg -framerate 10 -i frame_%04d.png output.gifexiftool input.jpg
exiftool -s input.jpg # short tag names
exiftool -ImageSize -DateTimeOriginal input.jpg # specific fieldsexiftool -all= input.jpg # strips in place (saves backup)
exiftool -all= -overwrite_original input.jpg # no backup
exiftool -all= -overwrite_original /folder/*.jpg # batch stripexiftool -TagsFromFile source.jpg target.jpgexiftool -Artist="Ramon" -Copyright="© 2026 ReshareAI" input.jpg
exiftool -all= -overwrite_original -Artist="Ramon" /folder/*.jpg# Optimize (overwrites in place, creates backup .bak)
optipng input.png
# No backup
optipng -o 7 input.png # -o 7 is max compression (slower)
# Output to new file
optipng -out output.png input.png
# Batch
optipng /path/to/folder/*.png
# Check savings without writing
optipng -simulate input.png# Lossless optimization (in place)
jpegoptim input.jpg
# With target file size
jpegoptim --size=200k input.jpg
# Strip all metadata + optimize
jpegoptim --strip-all input.jpg
# Batch (folder)
jpegoptim /path/to/folder/*.jpg
# Batch with max quality floor
jpegoptim --max=90 /path/to/folder/*.jpg# All pages → PNG at 150 DPI (output: file-000001.png, file-000002.png ...)
pdftoppm -r 150 -png input.pdf /output/page
# All pages → JPEG
pdftoppm -r 150 -jpeg input.pdf /output/page
# Single page (page 1 only)
pdftoppm -r 300 -png -f 1 -l 1 input.pdf /output/page
# High DPI for print-quality extraction
pdftoppm -r 300 -png input.pdf /output/pageinkscape input.svg \
--export-type=png \
--export-filename=output.png \
--export-width=1200 \
--export-height=630inkscape input.svg \
--export-type=png \
--export-filename=output.png \
--export-id=layer1 \
--export-id-onlyinkscape input.svg --export-type=pdf --export-filename=output.pdf.svg<?xml version="1.0" encoding="UTF-8"?>
<svg width="1200" height="630" viewBox="0 0 1200 630"
xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bg" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#4C1D95"/>
<stop offset="100%" style="stop-color:#1E1B4B"/>
</linearGradient>
</defs>
<rect width="1200" height="630" fill="url(#bg)"/>
<!-- Text renders perfectly — no hallucination like GIMP/FLUX -->
<text x="100" y="280"
font-family="Inter, Arial, sans-serif"
font-size="96" font-weight="700"
fill="white">BrandName</text>
<text x="100" y="360"
font-family="Inter, Arial, sans-serif"
font-size="32" fill="rgba(255,255,255,0.7)">Tagline goes here</text>
</svg>gimp --no-interface --batch '(let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE "/path/input.png" "input.png")))
(drawable (car (gimp-image-get-active-drawable image))))
(gimp-image-scale-full image 1200 630 INTERPOLATION-LINEAR)
(file-png-save RUN-NONINTERACTIVE image (car (gimp-image-get-active-drawable image))
"/path/output.png" "output.png" 0 9 1 1 1 1 1))
(gimp-quit 0)'gimp --no-interface --batch '(let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE "/path/input.jpg" "input.jpg")))
(w (car (gimp-image-width image)))
(h (car (gimp-image-height image)))
(target-w 1200) (target-h 630)
(scale (max (/ target-w w) (/ target-h h)))
(new-w (inexact->exact (round (* w scale))))
(new-h (inexact->exact (round (* h scale)))))
(gimp-image-scale-full image new-w new-h INTERPOLATION-LINEAR)
(gimp-image-crop image target-w target-h
(/ (- new-w target-w) 2) (/ (- new-h target-h) 2))
(file-png-save RUN-NONINTERACTIVE image (car (gimp-image-get-active-drawable image))
"/path/output.png" "output.png" 0 9 1 1 1 1 1))
(gimp-quit 0)'gimp --no-interface --batch '(let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE "/path/input.png" "input.png")))
(overlay (car (gimp-layer-new image
(car (gimp-image-width image))
(car (gimp-image-height image))
RGBA-IMAGE "overlay" 60 LAYER-MODE-NORMAL))))
(gimp-image-insert-layer image overlay 0 -1)
(gimp-context-set-foreground (list 0 0 0))
(gimp-edit-fill overlay FILL-FOREGROUND)
(file-png-save RUN-NONINTERACTIVE image (car (gimp-image-flatten image))
"/path/output.png" "output.png" 0 9 1 1 1 1 1))
(gimp-quit 0)'gimp --no-interface --batch '(let* (
(base (car (gimp-file-load RUN-NONINTERACTIVE "/path/base.png" "base.png")))
(overlay-img (car (gimp-file-load RUN-NONINTERACTIVE "/path/overlay.png" "overlay.png")))
(overlay-layer (car (gimp-layer-new-from-drawable
(car (gimp-image-get-active-drawable overlay-img)) base))))
(gimp-image-insert-layer base overlay-layer 0 -1)
(gimp-layer-set-offsets overlay-layer 50 50)
(file-png-save RUN-NONINTERACTIVE base (car (gimp-image-flatten base))
"/path/output.png" "output.png" 0 9 1 1 1 1 1))
(gimp-quit 0)'gimp --no-interface --batch '(let* (
(image (car (gimp-file-load RUN-NONINTERACTIVE "/path/input.jpg" "input.jpg")))
(drawable (car (gimp-image-get-active-drawable image))))
(gimp-brightness-contrast drawable 20 30)
(gimp-drawable-hue-saturation drawable HUE-RANGE-ALL 0 0 25 0)
(file-jpeg-save RUN-NONINTERACTIVE image drawable
"/path/output.jpg" "output.jpg" 0.92 0 0 0 "" 0 1 0 2 0))
(gimp-quit 0)'# Step 1: write /tmp/card.svg
# Step 2: export
inkscape /tmp/card.svg \
--export-type=png \
--export-filename=/output/og.png \
--export-width=1200 \
--export-height=630
# Step 3: optimize
optipng -o 5 /output/og.png-annotate--no-interface(gimp-quit 0)~/--export-type--export-filename--export-png!1200x630!