I use GIMP. It does the job quite well for most things but I felt a bit robbed (of my $0) when I found out there was no watermark tool, especially one that works in bulk. After trying to search around I did find a watermark python script that worked on basic terms at the Gimp Plugin Registry. However I believe it was limited to text and had some features I really wanted.

I decided to try to learn ‘script-fu’. I’ve got to say it was the roughest coding experience I’ve had in awhile. Even the GIMP batch tutorial leaves a lot to be explained, and it didn’t even work for me without trial and error on the batch command! Don’t get me started on how the code was laid out.

Regardless, you’re likely here just to get what you need done. Lets start.

  1. Download my script, here’s a link.
  2. Save this file to your GIMP install followed by \share\gimp\2.0\scripts. GIMP is often found under Program Files (for those Windows users like me). While you’re there, why not open up the file and take a look at my hard work and imagine the alcohol needed to fuel that.
  3. I did not put time into writing a fancy interface. This script is best run from command line. For Windows users Start -> Run… -> Cmd (hit OK) will do the trick.
  4. Type cd followed by your GIMP directory (i.e. cd “C:\Program Files\GIMP 2\bin”)

OK take a break for one second and see what my command lets you define:

Watermark Path – Path to a watermark in XCF (GIMP) format. Other formats may work as well.
Input files – Path to directory, followed by a wildcard search (i.e. *.jpg to target all jpg images to be watermarked).
Watermark Size – How big your watermark will be in accordance to the image. This is a percent but is entered as a decimal such as .05 (5%).
Watermark Padding – Each watermark will be padded from the corners of the image by a percentage (of the entire image) you define. This is a percent but is entered as a decimal as well.
Watermark Layer Mode – leave this as 0 (zero). higher numbers (i.e. 1,2,3…) will enable a different layer mode such as lighten/hard light/etc.
Position Number – My script allows for the watermark to be aligned in any corner, or the center. Acceptable values are 1,2,3,4,5.
Output Path – Where the watermarked images will be saved to.

Important notes:

  • Any paths defined should be enclosed in quotes. These quotes should be preceded by a backslash with no space. I.e. C:\Mike in the script would become \”c:\\mike\”. Any other backslashes MUST ALSO be preceded by a backslash (as seen between c: and mike).
  • Output path must be a directory. Do not leave a trailing slash on this.

So. You want to run THIS!

gimp-2.8.exe -b "(migee-add-watermark watermark-path inputfiles watermark-size watermark-padding watermark-layer-mode position output-dir)"

By example:

This is what I had to do to run my script on a folder WatermarkTest in my desktop on every JPG, having the watermark sized 25% and padded 1% along with a layer effect (15) and centered (5). Outputted files went to the same directory (the script prefixes all file names).

gimp-2.8.exe -b "(migee-add-watermark \"C:\\Users\\Migee\\Desktop\\WatermarkTest\\watermark.xcf\" \"C:\\Users\\Migee\\Desktop\\WatermarkTest\\*.jpg\" .25 .01 15 5 \"C:\\Users\\Migee\\Desktop\\WatermarkTest\")"

Final Notes:

Windows users, typing these the commands into a text file with the extension .BAT will save time if you do this a lot. It’s not easy with all the double slashes and slashed file location quotes.

This has HARDLY been tested and was really just completed to see if I could do this or not. I did little testing aside from the few images and singular watermark I’ve been working with. Please post up any problems and I can see if I can make this script work better!

Have improvements? Check out the code on GitHub


  • Great thanks man! Works fine! You make world better! Script saves time and money!

  • I got an error after the weekend with the script in the funcion gimp-file-saved. Does anyone know why can be?

  • I’ve been looking for this script for years but never knew it! Thank you so much for this, man. I’m going to use it All. The. Time.

  • Just watermarked hundreds of pictures on my wife’s jewelry web site in just a few minutes. Would’ve taken me a week or more w/o this. Thank you, thank you.

  • Great Tool! I’m really not a geek, but I manged it with your help! Great work!

  • Hi Mike,
    Great script, thank you. One thing I noticed is that, even adding a small (3KB) .XCF watermark to a 220KB JPEG file, the file size increases by more than 100KB. Is this something you were aware of?

  • This don’t work with gimp 2-6 ….but on 2-8 super . My images are bigger of 20kb only

  • How to use it? I’ve done as you’ve written… Gimp2 has started… when can I do it?

  • Hi every one, I wonder if this command may be “watermark-path” as “text-watermark”:
    gimp-2.8.exe -b “(migee-add-watermark watermark-path inputfiles watermark-size watermark-padding watermark-layer-mode position output-dir)”

    For excame: I want to watermark my image.png with text “hello-world”

  • Hi!

    I’ve been looking for this for long time, and from the feedbacks it seems to work like a breeze, but for me it isn’t.

    I have defined:

    Script folder: C:\Program Files\GIMP 2\share\gimp\2.0\scripts\migee.scm

    Original pictures folder: C:\Photos\Orig

    Watermarked pictures folder: C:\Photos\Watermarked

    Watermark file patch: C:\Photos\wm2013amM.xcf

    Gimp 2.8 folder: “C:\Program Files\GIMP 2\bin\gimp-2.8.exe”

    Command line used:

    “c:\Program Files\GIMP 2\bin\gimp-2.8.exe” -b “(migee-add-watermark \”c:\\Photos\\wm2013amM.xcf\” \”c:\\Photos\Orig\\*.jpg\” .05 .01 0 4 \”c:\\Photos\\Watermarked\”)”
    “C:\Program Files\GIMP 2\bin\gimp-2.8.exe” -b “(migee “C:\Photos\wm2013amM.xcf\” “C:\Photos\Orig\*.jpg” .06 .0 .0 4 “C:\Photos\Watermarked\”)”

    In the end it shows a prompt screen saying “batch command executed successfully”, but nothing happens. The screen keeps on forever if I do nothing. Then I closed the window and ran the script on verbose mode, with this command line:

    “c:\Program Files\GIMP 2\bin\gimp-2.8.exe” –verbose -b “(migee-add-watermark \”c:\\Photos\\wm2013amM.xcf\” \”c:\\Photos\Orig\\*.jpg\” .05 .01 0 4 \”c:\\Photos\\Watermarked\”)”

    I will post below the full log, but the last tools called my attention:

    loading menu ‘c:\Program Files\GIMP 2\share\gimp\2.0\menus\image-menu.xml’ for /image-menubar
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-lcms.dll’
    No batch interpreter specified, using the default ‘plug-in-script-fu-eval’.
    batch command executed successfully

    What that means?

    Can someone help me to clarify this?

    Full log below:

    INIT: gimp_load_config
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\unitrc’
    Parsing ‘c:\Program Files\GIMP 2\etc\gimp\2.0\gimprc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\gimprc’
    gimp_composite: verbose=no
    Processor instruction sets: +mmx +sse +sse2 -3dnow -altivec -vis
    Adding theme ‘Default’ (c:\Program Files\GIMP 2\share\gimp\2.0\themes\Default)
    Adding theme ‘Small’ (c:\Program Files\GIMP 2\share\gimp\2.0\themes\Small)
    Writing ‘C:\Users\Alexandre\.gimp-2.8\themerc’
    Trying splash ‘C:\Users\Alexandre\.gimp-2.8\gimp-splash.png’ … failed
    Trying splash ‘c:\Program Files\GIMP 2\share\gimp\2.0\images\gimp-splash.png’ ..
    . OK
    INIT: gimp_initialize
    INIT: gimp_real_initialize
    INIT: gui_initialize_after_callback
    INIT: gimp_restore
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\parasiterc’
    Loading ‘brush factory’ data
    Loading ‘dynamics factory’ data
    Loading ‘pattern factory’ data
    Loading ‘palette factory’ data
    Loading ‘gradient factory’ data
    Loading fonts
    Loading ‘tool preset factory’ data
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\templaterc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\modulerc’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcolor-selector-cmyk.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcolor-selector-cmyk.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcolor-selector-water.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcolor-selector-water.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcolor-selector-wheel.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcolor-selector-wheel.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcontroller-dx-dinput.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libcontroller-dx-dinput.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-color-blind.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-color-blind.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-gamma.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-gamma.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-high-contrast.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-high-contrast.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-lcms.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-lcms.dll’
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-proof.dll’
    Unloading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-proof.dll’
    INIT: gui_restore_callback
    clipboard: writable pixbuf format: image/png
    clipboard: writable pixbuf format: image/bmp
    clipboard: writable pixbuf format: image/x-bmp
    clipboard: writable pixbuf format: image/x-MS-bmp
    clipboard: writable pixbuf format: image/x-icon
    clipboard: writable pixbuf format: image/x-ico
    clipboard: writable pixbuf format: image/x-win-bitmap
    clipboard: writable pixbuf format: image/tiff
    clipboard: writable pixbuf format: image/jpeg
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\sessionrc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\dockrc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\toolrc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\contextrc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-rect-select-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-ellipse-select-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-free-select-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-fuzzy-select-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-by-color-select-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-iscissors-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-foreground-select-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-vector-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-color-picker-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-zoom-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-measure-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-move-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-align-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-crop-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-rotate-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-scale-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-shear-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-perspective-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-flip-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-cage-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-text-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-bucket-fill-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-blend-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-pencil-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-paintbrush-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-eraser-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-airbrush-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-ink-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-clone-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-heal-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-perspective-clone-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-convolve-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-smudge-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-dodge-burn-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-desaturate-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-color-balance-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-hue-saturation-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-colorize-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-brightness-contrast-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-threshold-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-levels-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-curves-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-posterize-tool’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\tool-options\gimp-gegl-tool’
    INIT: gimp_real_restore
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\pluginrc’
    Querying plug-in: ‘c:\Program Files\GIMP 2\lib\gimp\2.0\plug-ins\pyconsole.py’
    Writing ‘C:\Users\Alexandre\.gimp-2.8\pluginrc’
    Starting extension: ‘extension-script-fu’
    INIT: gui_restore_after_callback
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\menurc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\devicerc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\controllerrc’
    Parsing ‘C:\Users\Alexandre\.gimp-2.8\colorrc’
    loading menu ‘c:\Program Files\GIMP 2\share\gimp\2.0\menus\image-menu.xml’ for /image-menubar
    Loading module ‘c:\Program Files\GIMP 2\lib\gimp\2.0\modules\libdisplay-filter-lcms.dll’
    No batch interpreter specified, using the default ‘plug-in-script-fu-eval’.
    batch command executed successfully

  • Thanks so much! This is perfect! πŸ™‚

  • Any way of running this script with the -i command or using the console EXE only? I am using this to batch merge hundreds of lightmap files for a video game and I do not want to have to constantly close the Gimp window after it finishes each group of files (I execute all the commands from a batch file)

    If I try to use the console exe or use the -i command I get “Procedure execution of gimp-display-new failed” error instead and it won’t do anything. It works fine if I allow the interface to come up, but it’s a huge time waster and I would like to see this go through my files faster without the interface getting in the way. πŸ™

  • Ok I solved it! I only had to comment out the gimp-display-delete and the gimp-display-new image.

    Then I switch my batch file to use the console exe, then tack on -b “(gimp-quit 0)” (includes quotes) to the end of each command. This tells the console to exit after the script is processed. So finally, I can get this thing to run completely untouched while I do other things. πŸ˜€

  • Fantastic script. Thank you. I processed 125 files in under 6 mins. Just 1 question — how do I know which number represents what layer mode? Please share if you have a list of that. for example I want to blend normal with 60% opacity — what number should I give.

    Thanks and Regards

  • tested but I got a error:
    batch command experienced a execution error: Error: ( : 1 ) evel: unbound variable: migee-add-watermark

    please any idea?

  • For Linux users out there, you will need to adjust the script by hand. To get it working on Linux, I needed to just replace all “\\” with “/”.

    Would be great if this could be done in the code automatically, I tried finding out how to hack this but the script-fu documentation is pretty poor IMO.

    Also, FYI, to install scripts on linux, put the scm file under ~/.gimp/scripts

  • @Michael – that error sounds like the script was not put in the correct folder. I had the same error on linux until I put the script into the correct folder.

  • For the “Watermark Layer Mode” setting, below is a list of layer modes in GIMP. I tested one usecase and made notes on the output quality.

    For more info see http://docs.gimp.org/en/gimp-concepts-layer-modes.html

    0. Normal
    – No transparency
    1. Dissolve
    – bad
    2. Multiply
    – not work
    3. Divide
    – poor
    4. Screen
    – quite lite
    5. Overlay
    – lite but ok
    6. Dodge
    – poor
    7. Burn
    – poor
    8. Hard light
    – poor
    9. Soft light
    – poor
    10. Figure
    – very light
    11. Grain extract
    – poor
    12. Grain merge
    – poor
    13. Difference
    – poor
    14. Addition
    – poor
    15. Subtract
    – poor
    16. Darken only
    – poor
    17. Lighten only
    – poor
    18. Hue
    – not too bad
    19. Saturation
    – light but decent
    20. Color
    – poor
    21. Value
    – good

  • Super useful and hilarious thankyou!

  • Great script but it seems that PNG doesn’t work.

  • Yes I confirm, this script doesn’t support PNG format for the watermark file. Otherwise it works very well ! Thank you so much

  • Excellent resource, Mike! Thanks for the work you put into this!

  • I have no experience with scripts or run from cmd. Just needed multiple watermark for batch of photos. I did search for more than a month. I did not believe I will find what I need. Just downloaded GIMP as the last hope, tried if any watermark plugin exists, found yours. I learned how to run progs from cmd, finally learned how to work with cmd. I can not say how happy I am right now, thanks to your work. Thank you so much! You all, who shares your creations with others, thank you, because you are keeping the internet real.

  • First time GIMP and script user here so bear with,

    this is what I’m running in cmd;
    “c:\Program Files\GIMP 2\bin\gimp-2.8.exe” -b “(migee-add-watermark \”C:\\Users\\Migee\\Desktop\\Locals\\watermark.xcf\” \”C:\\Users\\Migee\\Desktop\\Locals\original\Monday 20th – Preconvocation\\*.jpg\” .05 .01 0 4 \”C:\\Users\\Migee\\Desktop\\Locals\watermarked\”)”

    And this is the error that it spits out (GIMP opens then does nothing);
    (gimp-2.8.exe:4008): LibGimpBase-WARNING **: gimp-2.8.exe: gimp_wire_read(): error
    batch command executed successfully

    Any thoughts or solutions? Thanks

  • Hi, I just wanted to let you know that I found your script very useful and your explanation to execute was perfect. Thank you for your efforts

  • Thank you so much! it works for me, not so easy with all the backslashes but give it enough attention all will go well!!!

  • Tshepiso take a look at the code file if you thought that was a headache :S

    Thanks for the feedback, glad its still providing value πŸ™‚

  • C:\Program Files\GIMP 2\bin>gimp-2.10.exe -b “(migee-add-watermark watermark-path C:\Users\Jordan\Documents\watermark.xcf inputfiles D:\Nikon_WU\101D7200.NEF watermark-size 0.10 watermark-padding 0.10 watermark-layer-mode 0 position 3 output-dir D:\Nikon_WU\101D7200)”

    I get “access is denied”

  • Mike, many thanks, I had flowcharted this in my mind and was about to start writing when I decided to Google first! It worked essentially first time (note to all – make sure you don’t have an active instance of Gimp running!)
    Greatly appreciated! Many of my images have been stolen over the years and this will help me out tremendously.