How to include a loop instead of several clone/crop commands

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-23T17:17:23-07:00

Hello to all, if I have some coordinates in a variable like this:

Code: Select all

coords=$(echo "264x40+1609+111 
         423x145+69+203  
         423x145+990+203 
         423x145+529+203 
         423x145+1450+203")
How can I do a loop to join these five images in a singles one without to send 5 clone/crop commands like this.

Code: Select all

convert input.png 
\( -clone 0 -crop 264x40+1609+111  -bordercolor "#990000" -border 4x4 -repage 858x360+293+0  \) 
\( -clone 0 -crop 423x145+69+203   -bordercolor "#990000" -border 4x4 -repage 858x360+0+62 \) 
\( -clone 0 -crop 423x145+990+203  -bordercolor "#990000" -border 4x4 -repage 858x360+0+208  \) 
\( -clone 0 -crop 423x145+529+203  -bordercolor "#990000" -border 4x4 -repage 858x360+427+62 \) 
\( -clone 0 -crop 423x145+1450+203 -bordercolor "#990000" -border 4x4 -repage 858x360+427+208  \) \
-delete 0 -flatten -resize 1150 -transparent white output.png
Thanks for any help.

snibgo
Posts: 11444
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to include a loop instead of several clone/crop commands

Post by snibgo » 2018-10-23T18:20:31-07:00

I'm not sure what you are asking. Does your command do what you want? If you want to write a shell script that creates the command from the lines in "coords", you can, but where do the "-repage" numbers come from?
snibgo's IM pages: im.snibgo.com

User avatar
fmw42
Posts: 24732
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to include a loop instead of several clone/crop commands

Post by fmw42 » 2018-10-23T18:57:44-07:00

You will likely have to parse the list in a for loop and then do the convert multiple times saving to temp files and then after the loop do the flattening. In unix, this can be done using a subshell and saving to miff:, then pipe the results from the subshell to a convert to flatten them. That way you do not need to save the temps.

cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

Re: How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-23T19:58:45-07:00

snibgo wrote:
2018-10-23T18:20:31-07:00
I'm not sure what you are asking. Does your command do what you want? If you want to write a shell script that creates the command from the lines in "coords", you can, but where do the "-repage" numbers come from?
Actually I have this image.

Image

I know their coordinates and sizes and they are stored in a variable.
110x16+255+175 (The small area)
178x59+29+65
178x59+223+65
178x59+417+65
178x59+611+65

And want to organize them in this way with a green border of 2 pixels and transparent background.The resulting image size is given by the size of the 5 areas plus the borders.

Image

I'd like to know a better way that have all those repeated commands in case I need to do something similar with more areas.

Thanks

User avatar
fmw42
Posts: 24732
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to include a loop instead of several clone/crop commands

Post by fmw42 » 2018-10-23T20:17:18-07:00

What is your scheme for organizing the output? What should happen if the larger 4 images are not the same size or if you have more smaller or larger images? How did you determine the -repage coordinates? Please clarify enough so we understand what your goal actually is.

cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

Re: How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-23T20:36:52-07:00

fmw42 wrote:
2018-10-23T20:17:18-07:00
What is your scheme for organizing the output? What should happen if the larger 4 images are not the same size or if you have more smaller or larger images? How did you determine the -repage coordinates? Please clarify enough so we understand what your goal actually is.
The mode to organize the 4 larger boxes is always the same. From left to right, the first and second box would be the "first column" and 3rd and 4th boxes would be the "second column". If we see the resulting image as 2x2 matrix.

The 4 larger boxes are always the same size and the smaller box I only want to put it in the center at the top with the borders you see and transparent background.

Actually I do not know too much of IM, the previous code is about an old and hard coded script that I'm trying to make a kind of dynamic.

I hope make sense and thanks again.

User avatar
fmw42
Posts: 24732
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to include a loop instead of several clone/crop commands

Post by fmw42 » 2018-10-23T22:03:34-07:00

try the following:

The
(
...
)

means do it in a subshell and do a for loop to crop every coord into one multipage miff in memory

Then I pipe the result to a new convert and put the miff from stdin into mpr:img in-memory and delete the stdin image. Then I use the mpr:img to append the pairs and then append the appended pairs with the one oddball first crop and write to result.png

Code: Select all

coords="110x16+255+175 178x59+29+65 178x59+223+65 178x59+417+65 178x59+611+65"
(
for coord in $coords; do
echo >&2 "$coord"
convert areas.png +repage -crop $coord +repage -bordercolor green1 -border 2x2 miff:-
done
) | \
convert - -write mpr:img -delete 0--1 \( mpr:img[1,2] -append \) \( mpr:img[3,4] -append \) +append mpr:img[0] +swap -gravity center -background white -append areas_result.png
Image

cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

Re: How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-24T08:55:05-07:00

fmw42 wrote:
2018-10-23T22:03:34-07:00
try the following:

The
(
...
)

means do it in a subshell and do a for loop to crop every coord into one multipage miff in memory
I didn't know about the "subshell" concept. We always learn, thank you.

Your code it works pretty nice, my issue is I almost don't understand the logic to make few changes. For example I added at the -transparent white but doen't change the background to transparent.

I changed from this:

Code: Select all

... -background white -append areas_result.png
to this, but anything happens.

Code: Select all

... -transparent white -append areas_result.png
Help in 2 more things I cannot change for my own please. Your code generates borders of 4 pixels between boxes and I'd like to have 2 pixels between boxes too but I don't know where to change hehe. And I'd like the small box that goes at the top be separated 2 pixels from the rest. Maybe you can see the sample output I posted before.

Thanks agaian.

User avatar
fmw42
Posts: 24732
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to include a loop instead of several clone/crop commands

Post by fmw42 » 2018-10-24T09:45:26-07:00

Does this do what you want? Note that when you put a border of 1 around each object and then append, the result will have 2 pixel border between the two but only 1 pixel border outside the other sides. If you need something else, the please explain. It should be possible to get the same borders around all sides using -smush rather than -append.

Code: Select all

coords="110x16+255+175 178x59+29+65 178x59+223+65 178x59+417+65 178x59+611+65"
(
for coord in $coords; do
echo >&2 "$coord"
convert areas.png +repage -crop $coord +repage -bordercolor green1 -border 1x1 miff:-
done
) | \
convert - -write mpr:img -delete 0--1 \( mpr:img[1,2] -append \) \( mpr:img[3,4] -append \) +append mpr:img[0] +swap -gravity center -background none -append areas_result2.png
Image



If you use a border of 2 so that you have 4 pixels between and smush by -2, you get 2 pixel overlap so that you end up with 2 pixels border everywhere.

Code: Select all

coords="110x16+255+175 178x59+29+65 178x59+223+65 178x59+417+65 178x59+611+65"
(
for coord in $coords; do
echo >&2 "$coord"
convert areas.png +repage -crop $coord +repage -bordercolor green1 -border 2x2 miff:-
done
) | \
convert - -write mpr:img -delete 0--1 \( mpr:img[1,2] -smush -2 \) \( mpr:img[3,4] -smush -2 \) +smush -2 mpr:img[0] +swap -gravity center -background none -smush -2 areas_result3.png
Image

cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

Re: How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-24T10:27:12-07:00

fmw42 wrote:
2018-10-24T09:45:26-07:00
Does this do what you want? Note that when you put a border of 1 around each object and then append, the result will have 2 pixel border between the two but only 1 pixel border outside the other sides. If you need something else, the please explain. It should be possible to get the same borders around all sides using -smush rather than -append.
Hi fmw42, Thanks so much. It does what I want. The last thing, how to put a separation, let say 3 pixels between top box and the other 4 like this?

Image

User avatar
fmw42
Posts: 24732
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to include a loop instead of several clone/crop commands

Post by fmw42 » 2018-10-24T11:07:59-07:00

Change the last -smush from -2 to +3

Code: Select all

coords="110x16+255+175 178x59+29+65 178x59+223+65 178x59+417+65 178x59+611+65"
(
for coord in $coords; do
echo >&2 "$coord"
convert areas.png +repage -crop $coord +repage -bordercolor green1 -border 2x2 miff:-
done
) | \
convert - -write mpr:img -delete 0--1 \( mpr:img[1,2] -smush -2 \) \( mpr:img[3,4] -smush -2 \) +smush -2 mpr:img[0] +swap -gravity center -background none -smush +3 areas_result5.png
Image

cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

Re: How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-24T12:37:23-07:00

Excellent fmw42. It works perfect.

I'm trying to understand your code and have some doubts, I hope you have some time to explain a bit how it works.

About the code below:

Code: Select all

convert areas.png +repage -crop $coord +repage -bordercolor green1 -border 2x2 miff:-
1- I understand crop crops each region from areas.png and adds the border storing the five images in memory (I understan miff is memory variable). Is correct?
2- What does +repage do? since I've tried removing both repage and the output it seems to be the same.
3- What does it mean ":-" after miff

About this code:

Code: Select all

convert - -write mpr:img -delete 0--1 \( mpr:img[1,2] -smush -4 \) \( mpr:img[3,4] -smush -4 \) +smush -4 mpr:img[0] +swap -gravity center -background none -smush +3 areas_result7.png
1- How can convert command work without an input image but takes "- -write" as input?
2- mpr:img is a call to the images stored in miff?
3- What does "-delete 0--1" mean?

Thanks so much for all.

User avatar
fmw42
Posts: 24732
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to include a loop instead of several clone/crop commands

Post by fmw42 » 2018-10-24T14:22:05-07:00

1) correct

2) +repage removes the virtual canvas offset that may be left in a miff or png image that might make the image display different from expected. Alway add +repage after -trim or -crop to remove that, especially for PNG, GIF and TIFF

3) the :- means direct to stdout


1) - in the convert command means get the image from stdin (sent by the miff:-) via a pipe |

2) - reads from stdin, I then write to a new mpr:image and delete all the frames in the original - (send from miff:-). Subsequent use of mpr:img is like a clone by name rather than by number.

3) -delete 0--1 means delete all the frames contained in - (sent from miff:-). I do that so I can use mpr:img to reference the different frames that were collected in the miff:-

See

https://imagemagick.org/Usage/crop/#crop_page
https://imagemagick.org/Usage/files/#miff
https://imagemagick.org/Usage/files/#mpr
https://imagemagick.org/Usage/basics/#delete

cgkas
Posts: 42
Joined: 2018-10-10T23:36:52-07:00
Authentication code: 1152

Re: How to include a loop instead of several clone/crop commands

Post by cgkas » 2018-10-24T16:09:37-07:00

Excellent fmw42. Thanks a lot for the explanation, your help, time and kind support for help me and others in this and many other posts.

Best regards

Post Reply