Page 1 of 2

Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T05:26:57-07:00
by chaoscarnage
I've been working on batching my imagemagick commands in my program into an exec script and want to do as few writes to disk as possible.
Currently I have chained a simple combination as follows and it works great.

Code: Select all

convert \
  	img.png \
		\( img_1.png  -composite \) \
		\( img_2.png  -composite \) \
		...
		\( img_n.png  -composite \) \
  	target.png
 
What I would like to be able to do is something like the following but i am unsure of how to do so

Code: Select all

convert \
	img.png \
  		\( img_1.png  -composite \) \
  		\( convert \
  			img_2.png \
  				\( out_1.png  -compose Dst_Out -composite \) \
  				\( out_2.png  -compose Dst_Out -composite \) \
  			[I dont want to write this out, but use the result for the span of the exec].png \) \
		...
  		\( img_n.png  -composite \) \
  	target.png
  

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T05:46:47-07:00
by snibgo
IM "convert" syntax doesn't have "convert" as a possible keyword.

Bash has a syntax for embedding commands within other commands: backtick or $(...). The output of these inner commands are then substituted into the corresponding position in the outer commands. The output of a convert command, using "-" as the output filename, is usually an image -- a load of binary. A convert command usually expects an image name, not a load of binary. Perhaps this can be done using "-" as the input of the outer command. I'm not a bash expert.

Piping works with no problem, in Unix and Windows, eg:

Code: Select all

convert rose: -negate - | convert - x.png
Also possibly useful to you: images can be written to "mpr:", then all images in the list can be deleted, effectively starting the convert command again, and this can use any saved "mpr:" as inputs. "mpr:" saves to memory, not disk.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T06:01:22-07:00
by chaoscarnage
So something like this would work then? Also how do I clear out the mpc file when im done with it? I would like to clear it asap.

Code: Select all

convert \
	img_2.png \
		\( out_1.png  -compose Dst_Out -composite \) \
		\( out_2.png  -compose Dst_Out -composite \) \
	mpr:convert_n
|
convert \
	img.png \
		\( img_1.png  -composite \) \
		\( mpr:convert_n -composite \) \
		...
		\( img_n.png  -composite \) \
	target.png
 

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T06:15:08-07:00
by snibgo
That won't work. "mpr:" will exist only within a single convert command. But merging the two converts into one should work:

Code: Select all

convert \
   img_2.png \
      \( out_1.png  -compose Dst_Out -composite \) \
      \( out_2.png  -compose Dst_Out -composite \) \
   +write mpr:convert_n \
   +delete \
   img.png \
      \( img_1.png  -composite \) \
      \( mpr:convert_n -composite \) \
      ...
      \( img_n.png  -composite \) \
   target.png
EDIT: Added "+write" to the above.

The following bash command works:

Code: Select all

convert inline:$(convert rose: -crop 10x10+0+0 +repage inline:) x.png
"Inline:" is an IM format that represents an image as text that can be embedded in a command. This builds a large command, perhaps with millions of bytes. I wouldn't recommend it.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T07:55:58-07:00
by chaoscarnage
I thought the initial script in the OP worked but It looks like it does not. I can't seem to get it to run without the following error.
I tried running the following using PHP exec().

Code: Select all

convert \
     img.png \
      \( img_1.png -composite \) \
      \( img_2.png -composite \) \
     target.png
Spits back the following at me
convert: unable to open image ` img.png (': No such file or directory @ error/blob.c/OpenBlob/2695.
convert: no decode delegate for this image format `PNG (' @ error/constitute.c/ReadImage/501.
convert: unable to parse expression `)' @ error/convert.c/ConvertImageCommand/603.

It seems to be angry about the parenthesis. I'm not to sure what to do.

EDIT: I removed the parenthesis and backslashes and it seems to work fine. Not sure what negative effects this could have any advice appreciated.
EDIT2: The combined version does not seem to work not sure if this is related to the parenthesis issue.

Code: Select all

convert 
   img_2.png 
      out_1.png -compose Dst_Out -composite 
      out_2.png -compose Dst_Out -composite 
   +write mpr:convert_1 
   +delete 
   img_3.png 
      out_3.png -compose Dst_Out -composite 
      out_4.png -compose Dst_Out -composite 
   +write mpr:convert_2 
   +delete 
   img.png 
      img_1.png -composite 
      mpr:convert_1 -composite 
      mpr:convert_2 -composite 
   img.png
convert: no images defined `img.png' @ error/convert.c/ConvertImageCommand/3230.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T09:12:54-07:00
by snibgo
Sorry, I forgot to use "+write" above. Now corrected.

I don't know PHP. Is "\" a line-continuation character?

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T09:18:16-07:00
by chaoscarnage
snibgo wrote:Sorry, I forgot to use "+write" above. Now corrected.

I don't know PHP. Is "\" a line-continuation character?
Currently in order to get it to work I removed the '\' too. I Didn't note that properly :? Apologies.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T09:27:52-07:00
by chaoscarnage
Still no luck with mpr version even with +write.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T10:15:53-07:00
by snibgo
The error message "convert: no images defined `img.png'" usually means there are, at the end, no images to write. But that is usually because of an earlier problem, which will have been reported.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T12:34:17-07:00
by chaoscarnage
Even just trying to straight run in linux through command line I cannot get the expected result with parenthesis. With the code below

Code: Select all

convert \
     img.png \
      \( img_1.png -composite \) \
      \( img_2.png -composite \) \
     img.png
This however works fine

Code: Select all

convert \
     img.png \
      img_1.png -composite \
      img_2.png -composite \
     img.png
I'm sure its a matter of syntax I just dont understand.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T13:03:45-07:00
by fmw42
In your parenthesis processing, the -composite only has one image to work on, so that is why it fails. You do not need the parentheses to do what you want. You would need the parenthesis if you needed to combine your image_1 in the first parentheses with some other image, or if you wanted to do some processing that is different on image_1 that image_2 before compositing with img.

see for example:

http://www.imagemagick.org/Usage/basics/#parenthesis
http://www.imagemagick.org/Usage/layers/#convert

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T13:13:37-07:00
by chaoscarnage
fmw42 wrote:In your parenthesis processing, the -composite only has one image to work on, so that is why it fails. You do not need the parentheses to do what you want. You would need the parenthesis if you needed to combine your image_1 in the first parentheses with some other image, or if you wanted to do some processing that is different on image_1 that image_2 before compositing with img.

see for example:

http://www.imagemagick.org/Usage/basics/#parenthesis
http://www.imagemagick.org/Usage/layers/#convert
Makes sense. Does that mean that there needs to be some parenthesis added to get the following to work

Code: Select all

convert \
   img_2.png \
      out_1.png -compose Dst_Out -composite \
      out_2.png -compose Dst_Out -composite \
   +write mpr:convert_1 \
   +delete \
   img_3.png \
      out_3.png -compose Dst_Out -composite \
   +write mpr:convert_2 \
   +delete \
   img.png \
      img_1.png -composite \
      mpr:convert_1 -composite \
      mpr:convert_2 -composite \
   img.png \
   

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T15:23:43-07:00
by 246246
chaoscarnage wrote: Makes sense. Does that mean that there needs to be some parenthesis added to get the following to work
Because of your odd usage of parenthesis (of the first post), I cannot figure it out what you want to accomplish.
It looks you have 7 input files (img.png, img_1.png, img_2.png, img_3.png, out1_1.png, out_2.png, out_3.png) and want to get 1 output file. Or you have 4 input files and want 3 output files?

I suggest If you write your code with using temporary files so as to make your output clear.
So someone can rewrite it without using temporary files.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T16:02:01-07:00
by chaoscarnage
246246 wrote:
chaoscarnage wrote: Makes sense. Does that mean that there needs to be some parenthesis added to get the following to work
Because of your odd usage of parenthesis (of the first post), I cannot figure it out what you want to accomplish.
It looks you have 7 input files (img.png, img_1.png, img_2.png, img_3.png, out1_1.png, out_2.png, out_3.png) and want to get 1 output file. Or you have 4 input files and want 3 output files?

I suggest If you write your code with using temporary files so as to make your output clear.
So someone can rewrite it without using temporary files.
Thank you for your time and post.
I changed the names some and have added a list of goals and have added more details to try to make it clearer what I wish to accomplish

I am programmatically creating a string to call using PHP Exec() to combine a bunch of images together sometimes in a specific way.
I want to write to the disk as little as possible to keep the process quick.
The overall goal and basic premise was to be able to combine images onto a blank image, which thanks to the help of snibgo I was able to get working.
However, I need to go a step further and modify a couple of the images before they get added to the overall image. Snibgo reccommended using mpc files to do so and after reading about them seemed like the best fit for what I stated above.

As far as how to describe how I want the code to run:
I want to load source2.png, apply subsource1 and subsource2 ONLY to source2.png using Dst_Out algorithm and then store it in memory for the overall combine to come later.
I wish to do something similar with source3 but instead I only want to apply one subsource layer to it.
Then after Ive taken care of the above I wish to combine them together with a mix of mpc and images from disk onto the blank image.
Once combined, I wish to write the result to disk and do not wish to keep the mpc files in any way after the command.

Code: Select all

convert \
   source2.png \
      subsource1.png -compose Dst_Out -composite \
      subsource2.png -compose Dst_Out -composite \
   +write mpr:convert_result_1 \
   +delete \
   
   source3.png \
      subsource1.png -compose Dst_Out -composite \
   +write mpr:convert_result_2 \
   +delete \
   
   blank.png \
      img_1.png -composite \
      mpr:convert_result_1 -composite \
      mpr:convert_result_2 -composite \
   everything-combined.png \
  
Thanks again! I am welcome to any improvements and even a different direction altogether if it helps me accomplish what I've explained above.

Re: Convert inside convert, want to use result of inner converts without writing to disk

Posted: 2015-08-23T16:29:08-07:00
by snibgo
"-compose Dst_Out" is a setting that applies to all subsequent "-composite" operations (and some other operations), until changed by another "-compose". So the second and third "-compose Dst_Out" are redundant, but harmless.

At the end, you have "-composite" with no "-compose" setting, so this will also be "Dst_Out".

The default setting of "-compose" is "Over".