How to use an external command to make an edit of pic in the gimp and then return the result to the stage in a plugin or script.
Example in shell script.:
magick label.gif +matte
( +clone -shade 110x90 -normalize -negate +clone -compose Plus -composite )
( -clone 0 -shade 110x50 -normalize -channel BG -fx 0 +channel -matte )
-delete 0 +swap -compose Multiply -
The command above (imagemagick app) create a gif and i want put back in gimp stage. May be other simple option or application, but i need of return the edited back to gimp. Python, script fu? Thanks so much.
enter image description here
There is a shellout.py Gimp plugin floating around from which you can borrow code. Typically:
you export the layer to a temp file (if you work on the whole image, you likely have to do a pdb.gimp_layer_new_from_visible())
call the executable with subprocess.Popen() and a list of arguments
load the result as a new layer with pdb.gimp_file_load_layer()
If GIMP will take stdin, then pipe from ImageMagick to GIMP using the GIMP XCF file format.
magick label.gif +matte
( +clone -shade 110x90 -normalize -negate +clone -compose Plus -composite )
( -clone 0 -shade 110x50 -normalize -channel BG -fx 0 +channel -matte )
-delete 0 +swap -compose Multiply XCF:- | GIMP -
How can I create an Image using Imagemagick in which I stick for example 6 images next to each other, thus the background shall be transparent(.png file).
It shall look something like this: ( The black rectangles shall represent images )
How do I achieve this ?
Edit (Update)
So far I have done this image:
using this command:
montage img1.jpg img2.jpg img3.jpg img4.jpg img5.jpg img6.jpg -geometry +10+10 -resize 720x480 output.jpg
but I am not sure how to proceed further.
You are almost there! Take your montage command and output the resulting 3x2 montage to stdout as a PNG into a new convert which appends it below your top.jpg image:
montage im*jpg -geometry +10+10 png:- | convert -gravity north top.jpg png:- -append result.png
If you are on Windows, you probably need:
montage *.jpg ...
or you can type it out in full:
montage img1.jpg img2.jpg img3.jpg img4.jpg img5.jpg img6.jpg -geometry +10+10 png:- | convert -gravity north top.jpg png:- -append result.png
This is just another way of doing this. I think it may be a little simpler than Mark's solution. Note the parentheses that groups commands into single image ouput. Also remember that IM requires space before and after the openining brackets.
magick -gravity center -background none -bordercolor none ( f1.jpg -border 10 ) ( f2.jpg f3.jpg f4.jpg -border 10 +append ) ( f5.jpg f6.jpg f7.jpg -border 10 +append ) -append output.png
More on appending is here however in most cases I prefer montage command.
In here I found a piece of code that finds and resizes all images within a folder with applescript
Now I need to apply a stamp to those images one by one. I already have a transparent jpg prepared with the same size and ready to be pasted on all of them.
I just lack the knowledge to do it on terminal so I could mix it with applescript.
Does anyone know how to do this without making a workflow? Because it takes a lot of time and keeps the laptop busy
Updated Again :-)
You can get the height of an image like this:
identify -format "%h" image.jpg
500
and the width like this:
identify -format "%w" image.jpg
800
If you want to find the lesser of the height and the width, and then take 10% of that for your logo size and make it integer, you would do:
identify -format "%[fx:int(0.1*min(h,w))]" image.jpg
50
If you want to put that in a variable, you would do
logosize=$(identify -format "%[fx:int(0.1*min(h,w))]" image.jpg)
echo $logosize
50
You could then use that in the original command below like this:
convert image.jpg -gravity southeast \
\( copyright.png -resize "${logosize}x${logosize} \) \
-composite result.jpg
I suspect you are going to want to run that with the find command, aren't you? :-)
find . -iname \*.jpg -exec bash -c 'echo Processing {};logosize=$(identify -format "%[fx:int(0.1*min(h,w))]" "{}"); echo $logosize;convert "{}" -gravity southeast \( copyright.png -resize "$logosizex$logosize" \) -composite "{}"' \;
Updated Answer
If you want to resize your original image before compositing the logo unchanged on top, use a command like this:
convert image.jpg -resize 2000x1000 -gravity southeast copyright.png -composite result.jpg
If you want to resize the logo before compositing it on top of the unchanged original image, use a command like this:
convert image.jpg -gravity southeast \( copyright.png -resize 700x200! \) -composite result.jpg
Original Answer
I would use ImageMagick. It is extremely powerful and simple to install if you use homebrew. Ask if you don't know how...
Let's assume you have an image called image.jpg and a transparent logo/copyright called copyright.png.
image.jpg
copyright.png
Then the command to do a single image would be:
convert image.jpg copyright.png -composite result.jpg
If your logo/copyright and image are different sizes, and you want to force the logo to, say, the bottom right corner, just set the -gravity accordingly like this:
convert image.jpg -gravity southeast copyright.png -composite result.jpg
If you wanted to do all the JPEGs in the folder, you would need a loop:
#!/bin/bash
shopt -s nullglob
shopt -s nocaseglob
for f in *.jpg; do
convert "$f" copyright.png -composite "$f"
done
By the way, you cannot have a transparent JPEG - that format doesn't support transparency.
If you are really intent on using Applescript - I don't know why anyone would be - you can call the above using do shell script - make the file executable first. Ask if unsure how.
If you want to recurse down into all directories (folders) starting at the one you are currently located in and add the logo/copyright to all images, I would make a copy of them somewhere else first and do a trial run. The command would be:
find . -iname "*.jpg" -exec convert "{}" copyright.png -composite "{}" \;
That says... "find, starting at the current directory (.), disregarding upper/lower case (-iname), all files ending in "JPG", and apply the logo/copyright to them, resaving on top of the original file".
I had same issue years ago, and the only way I found is an Applescript using Photoshop (duplicate layer containing the logo on the photo and flatten file).
the script loops to all file of a folder.
... but you need Photoshop for this script !
I can share that script if it helps
I have a script that takes 4 pictures and duplicates them to produce 8 small pictures in one. The script also adds a background to the output.
Here is what I expect:
http://img11.hostingpics.net/pics/831624stack.png
I have a code that works well. But it needs to save multiple temporary images.
So I was looking if I could merge the commands of my script to get only one image saving operation. The goal is to make the script complete faster.
//Make image smaller:
convert /home/pi/images/*.png -resize 487x296 -flop \
-set filename:f "/home/pi/imagesResized/%t%p" '%[filename:f]'.png
//Make one column from 4 images:
montage /home/pi/imagesResized/*.png -tile 1x4 \
-geometry +0+15 -background none /home/pi/line.png
//Duplicate to two columns:
montage /home/pi/line.png /home/pi/line.png -tile 2x1 \
-geometry +45+0 -background none /home/pi/photos.png
//Add the background image:
suffix=$(date +%H%M%S)
montage /home/pi/photos.png -geometry +20+247 \
-texture /home/pi/data/background_photo.png \
/home/pi/photo_${suffix}.jpg
First, let me say this:
you'll save only significant processing time by putting the separate commands into one single ImageMagick command chain if your input images are quite large.
You may however save disk I/O time by skipping the need to write out and read in the intermediate result images.
Your code uses two different montage commands plus one convert command in order to achieve a first montage.
Finally you use one montage to place the previous result on the background.
From the top of my head, I can quickly come up with a way to combine the first three commands into a single one.
The last montage step to place the intermediate results onto the background is not so easy to get right, and very likely will not save much time either.
Hence, I will leave that open for now.
Unfortunately you did not provide any link to your source images.
I had to create my own ones in order to answer this question.
They can also serve to demo the validity of my answer.
To create four 800x600 pixel sized PNGs, I used Ghostscript with a little bit of PostScript code on the command line:
for i in 1 2 3 4 ; do
gs -o t${i}.png \
-g800x600 \
-sDEVICE=pngalpha \
-c "0.5 setgray" \
-c "0 0 800 600 rectfill" \
-c "1 0 0 setrgbcolor" \
-c "3 setlinewidth" \
-c "10 10 780 580 rectstroke" \
-c "0 setgray" \
-c "/Helvetica-Bold findfont" \
-c "560 scalefont setfont" \
-c "230 60 moveto" \
-c "(${i}) show " \
-c "showpage" ;
done
Then I first tested your code with my images.
Here is the result from the OP's commands. The result is complete, including montage on a background image from my own stock (updated), created with a command inspired by Mark Setchell's answer:
convert -size 200x200 xc:gray +noise gaussian background.png
Merging the first two commands:
The following was my first shot in order to come up with a single command.
It should achieve the same result as your first two commands outputting line.png.
I already knew it wouldn't work exactly as expected in some aspects, but I still tried.
I tried it in order to see if there are other places of the command that would show problems that I didn't expect.
No worries, the explanation of the complete, final code will be at the end of the answer.
You can try to figure out how the following command works once you read the complete answer:
_col1=blue ;
_col2=red ;
convert t*.png -flop -resize 487x296\! \
\( -size 15x15 \
-clone 0 xc:${_col1} \
-clone 1 xc:${_col1} \
-clone 2 xc:${_col1} \
-clone 3 \
-append \
+write f.png \
\) null:
Here is the result of my command (right) compared to the intermediate result after your second command (left):
So, one thing I had expected happened: there is a blue spacer between each image.
I colorized it for debugging reasons.
This can be fixed by setting the color variable to none (transparent).
Things I hadn't expected and which I only discovered after opening the resulting image f.png:
My background was white instead of transparent.
This can be fixed by adding -background none at the right place.
My spacing of the individual images in the columns is too narraw, being 15 pixels only.
This is because in the intermediate file line.png of the OP the spacing is not 15 pixels, but 30 pixels.
His parameter -geometry +0+15 for the montage creating the columns does add the 15 pixels on top as well as on bottom of each image.
My command (using convert ... -append instead of montage) does not allow for additional -geometry settings which would have the same effect.
But his can be fixed by adding more xc:{_col1} spacers into my command.
Merging the first three commands:
So here is the next iteration.
It integrates the effect of the third command from the OP.
This is achieved by adding +duplicate for duplicating the first created column.
Then it adds +append to append the duplicate column horizontally (-append would do so vertically):
_col1=blue ;
_col2=red ;
convert t*.png -flop -resize 487x296\! \
\( -size 15x15 \
-background none \
xc:${_col1} \
-clone 0 xc:${_col1} xc:${_col1} \
-clone 1 xc:${_col1} xc:${_col1} \
-clone 2 xc:${_col1} xc:${_col1} \
-clone 3 \
xc:${_col1} \
-append \
+duplicate \
-size 45x45 xc:${_col2} \
+append \
+write f2.png \
\) null:
Again one thing I had expected happened:
The red spacer between the two columns was on the right instead of sitting in between the columns.
We can fix that by swapping the last two images that get +append-ed.
This can be done by adding the +swap operator at the right place.
Also, the same thing as with the inter-image spacing in the first column will apply to the spacing in bewteen the columns: I have to double it.
I will not care at the moment that the same space (45 pixels) is not added to the +append-ed columns left and right.
So here is one more iteration:
_col1=red ;
_col2=blue ;
convert t*.png -flop -resize 487x296\! \
\( -background none \
-size 15x15 \
xc:${_col1} \
-clone 0 xc:${_col1} xc:${_col1} \
-clone 1 xc:${_col1} xc:${_col1} \
-clone 2 xc:${_col1} xc:${_col1} \
-clone 3 \
xc:${_col1} \
-append \
+duplicate \
-size 90x90 xc:${_col2} \
+swap \
+append \
+write f3.png \
\) null:
Here is the result:
On the right is the intermediate photos.png created by the OP code after the third command.
On the left is the image montage created by my command.
What's missing now is an explanation with a breakdown of the individual operations I packed into a single command:
\( :
This opens a "sideways" processing of some of the images.
The result of this sideway processing is then again inserted into the main ImageMagick process.
The backslashes are required so the shell does not try to interpret them.
\) :
This closes the sideways processing.
-size 15x15 :
This sets the size of a canvas to be filled next.
xc:${_col1} :
This fills the canvas with color specified.
xc: is just an alias to canvas:, but it is faster to type.
-clone 0 :
This creates a copy of the first image that is currently in the loaded image stack.
In this case it is a copy of t1.png.
-clone 1 copies t2.png, -clone 2 copies t3.png, etc.
-clone or +clone work best inside sideway processing chains, hence the previously explained use of \( and \).
-append :
This operator appends all currently loaded images vertically.
In this case these are the 4 copies of t1.png, ... t4.png.
+duplicate :
This operator similar to +clone.
It copies the last image in the currently loaded image stack.
In this case the last image (and only remaining one inside the sideways pipeline) is the result of the previous -append operation.
This operation had created the first column of 4 images, spaced apart by the red spacers.
+append :
This operator appends all currently loaded images horizontally.
There are currently three images: the result of the -append operation, its copy created by +duplicate, and the 90x90 sized xc:-canvas.
+swap :
This operator swaps the last two images on the currently loaded stack.
+write :
This operator writes out all of the images from the currently loaded stack.
When there are multiple images, it will write these images with the given name, but with a number appended.
It's a great tool for debugging complex ImageMagick commands.
It is great because after the +write operation is finished, the previously loaded images remain all on the stack.
These images remain unchanged, and processing can continue.
However, we are finished now and won't continue in this case.
Hence we close the side-way process with a \).
null :
Now that we closed the sideway process, ImageMagick puts the resulting image from the sideway into the main pipeline again.
Remember, +write didn't finish the processing, it wrote an file to disk that is meant to be an intermediate result.
In the main pipeline, there are now still the original t1.png ... t4.png plus the result from the sideway processing.
However we will not do anything with them.
We will take the intermediate result from +write as our final one.
But the convert command expects to now see an output filename.
If it doesn't see one, it will complain and show us an error message.
Hence we tell it to write off all it has loaded and discard all images from the stack.
To achieve this, we use null: as output filename.
(If you feel adventurous, use out.png as a filename instead of null:.
You will see that ImageMagick actually creates multiple out-0.png, out-1.png,...out-3.png filenames.
You will find that out-4.png is the same as f.png, and out-{0,1,2,3}.png are the same as the input images. --
You could also replace null: by -append output.jpg and see what happens then...)
Update
Now for the speed comparison...
For a first rough benchmark, I did run the OP's first three commands in a loop with 100 iterations.
Then I did run my own command 100 times as well.
Here are the results:
OP first three commands, 100 times: 61.3 seconds
My single command replacing these, 100 times: 48.9 seconds
So my single command saved roughly 20% time over the original commands from the OP.
Given that my disk I/O performance can be assumed to be pretty fast (the test system has an SSD) in comparison with a spinning harddisk, the speed gain from the merged command (which avoids too many temporary file write/reads) may be more distinct on a system with a slower disk.
To check if a little re-architecture of the command (where not so many loaded images are simply discarded at the end, as can be seen by the null: output file name) would gain more improvements, I also tried this:
convert t*.png -flop -resize 487x296\! \
-background none \
-size 0x15 \
xc:red \
-duplicate 7 \
-insert 0 \
-insert 2 \
-insert 3 \
-insert 5 \
-insert 6 \
-insert 8 \
-insert 9 \
-append \
\( +clone -size 45x0 xc:blue +swap \) \
+append \
f4.png
The architecture of this command is a bit different.
First, it loads all the images. It -flops them and it -resizes them.
Second, it creates a single 15x15 pixels canvas, which then is also placed on the image stack.
Third, it creates 7 additional copies of that canvas.
Now there are 12 images on the stack:
the 4 input files, 1 xc:-canvas, and 7 copies of the canvas.
Then, it uses a series of -insert N operations.
The -insert N operation manipulates the order of the image stack.
It removes the last image from the stack and inserts it into image index position N.
When the -insert series of operations starts, there are 4 images (t1, t2, t3, t4) on the stack, plus 8 "spacers" (s).
This is their original order:
index: 0 1 2 3 4 5 6 7 8 9 10 11
image: t1 t2 t3 t4 s s s s s s s s
I've picked the index numbers in a way so that from above original order the changed new order after all -insert N operations are finished is:
index: 0 1 2 3 4 5 6 7 8 9 10 11
image: s t1 s s t2 s s t3 s s t4 s
Since all spacers s are 15 pixels wide, this achieves the same spacing as my initial command.
Next, a similar sideway processing happens: this time to +clone the result of the previous -append operation and to create the horizontal spacer.
Last, the +append (which operates on the result from the previous -append and from the sideway-process) creates the final result, f4.png.
When I benchmarked this last command, I got the following results for 100 repetitions of each command:
My first command before the update, 100 times: 48.3 seconds
My last command explained after the update, 100 times: 46.6 seconds
So the speed gain is not quite so notable, roughly 3% better if you want to trust these numbers.
(It should be noted, that I did run both loops in parallel on the same machine to create more fairness in the benchmarking competition.
By running in parallel, they both have to deal with the same CPU and I/O load which may be caused by themselves as well as by other processes happening on the machine concurrently.)
As I don't have your images or your texture or their sizes, I will show you something similar for you to adapt...
Make some input images:
convert -size 500x400 xc:black 1.png
convert -size 500x400 xc:red 2.png
convert -size 500x400 xc:green 3.png
convert -size 500x400 xc:blue 4.png
and a background texture:
convert -size 2000x2000 xc:gray +noise gaussian background.png
Now do what you asked, but without intermediate files to disk:
montage [1234].png -background none -tile 1x4 -geometry +0+15 miff:- |
convert -background none :- -size 15 xc:none -clone 0 +append png: |
convert -gravity center background.png :- -composite z.png
The first line lays out the 4 images one above the other, and sends the combined result in a MIFF (Mutiple Image File Format) through a pipe to the next command. The second command reads an image from the pipe and appends a 15 pixel wider "spacer" and then duplicates the first column of images (with clone) and writes as a PNG to the next command through another pipe. The final command reads the 8 small images combined and puts them on a background, centred.
If the right hand column of images is supposed to be the left column reflected - it's hard to tell from your poor example which shows flat black boxes - you may need to change the second line of the command from
convert -background none :- -size 15 xc:none -clone 0 +append png: |
to
convert -background none :- -size 15 xc:none \( -clone 0 -flop \) +append png: |
Here is another answer. It took inspiration from Mark Setchell's approach. Here I come up with a new command pipeline. The difference is, that I...
...use exclusively 3 montage commands in a pipeline (Mark used 1 montage and 2 converts in his pipeline), and I
...reproduce exactly the output of the OP's 3 different commands.
As input I used the four images created by the Ghostscript command in my other answer, t{1,2,3,4}.png.
To create a suitable background image I used the command from Mark, though modified: I made the image a tad bit smaller, so that the -texture operator from the OP could by meaningfully used:
convert -size 200x200 xc:gray +noise gaussian background.png
Then I benchmarked all three commands/scripts,...
...the OP commands as a shell script,
...the approach of Mark, albeit modified as outlined above,
...my initial approach, amended with adding the background image.
For benchmarking, I did run 100 repetitions each.
When doing so, I started each script/command in a separate terminal window, roughly at the same time.
The CPU on the test machine has 4 cores.
So when the commands were running in parallel, they had to deal with the same CPU- and I/O-load each, competing with each other for resources.
This is the most "fair" ad-hoc performance testing setup I could come up with.
I also confirmed that the output files created by the 3 tests (photo_test1.jpg, ms+kp_test2.jpg and kp_test3.jpg) are pixelwise (almost) identical.
If the output is switched to PNG (instead of JPEG, how the OP asked for), then these small differences also disappear between the 3 approaches.
Here are the results:
Script using 4 commands from the original post (OP):
mkdir ./imagesResized
time for i in {1..100}; do
convert t*.png -resize 487x296\! -flop \
-set filename:f "./imagesResized/%t%p" '%[filename:f]'.png
montage ./imagesResized/*.png -tile 1x4 -geometry +0+15 \
-background none line.png
montage line.png line.png -tile 2x1 -geometry +45+0 \
-background none photos.png
montage photos.png -geometry +20+247 \
-texture background.png \
photo_test1.jpg
done
Results:
real 2m13.471s
user 1m54.306s
sys 0m14.340s
Roughly 133 seconds in real time.
Take this as 100% time consumption.
Modified command pipeline inspired by Mark's answer:
time for i in {1..100}; do
montage t[1234].png -resize 487x296\! -flop -background none \
-tile 1x4 -geometry +0+15 miff:- \
| montage :- -background none -clone 0 -tile 2x1 -geometry +45+0 miff:- \
| montage :- -geometry +20+247 -texture background.png ms+kp_test2.jpg ;
done
Results:
real 1m50.125s
user 1m32.453s
sys 0m16.578s
Roughly 110 seconds.
About 83% time consumption compared to original commands.
My original command, now completed with missing background compositing:
time for i in {1..100}; do
convert t*.png -flop -resize 487x296\! \
-background none \
-size 0x15 \
xc:white \
-duplicate 7 \
-insert 0 \
-insert 2 \
-insert 3 \
-insert 5 \
-insert 6 \
-insert 8 \
-insert 9 \
-append \
\( +clone -size 90x0 xc:white +swap \) \
+append \
-transparent white \
miff:- \
| montage :- -geometry +65+247 -texture background.png kp_test3.png
done
Results:
real 1m34.786s
user 1m20.595s
sys 0m13.026s
Roughly 95 seconds.
About 72% time consumption compared to original commands.
The example shown on the website is:
convert koala.gif blur_map_gradient.gif \
-compose blur -define compose:args=3 -composite \
blur_koala_gradient.gif
http://www.imagemagick.org/Usage/mapping
I'd like to do this for a whole directory of images.
I've looked into using mogrify, but can't figure out how to set the file input/output to run the process on a whole directory.
Thanks for any help.
You're on the right track with mogrify. To use your command as an example, you could do this:
mogrify -compose blur -define compose:args=3 -composite *.gif
This will apply the changes to all the images in the current directory. This will overwrite the images. If you do not want to overwrite the original images, you can either make a new directory (let's call it '/home/user/new/') or use the -format option to append a suffix to the files.
Here's an example with both options:
`mogrify -path /home/user/new/ -compose blur -define compose:args=3 -composite -format "blur.gif" *.gif
This will place originalimagename.blur.gif files in /home/user/new/, leaving the originals intact.
I was sure that it was possible to use -compose with mogrify. In actuality, mogrify does not recognize the -compose argument.. I think that your best bet is to use a script to loop through each image in the directory and use convert on them.