Page 1 of 1

Using first image in a layering op. to set output image size

Posted: 2012-10-21T14:54:46-07:00
by rossmcm
I have an image layering of the form:

Code: Select all

convert ^
     -size "100x100" xc:none ^
     ^( "a.png" -gravity center  -geometry +00+00 ^) -composite ^
     ^( "b.png" -gravity center  -geometry +50+50 ^) -composite ^
     "c.png"
but I want to modify this so that the size of the output file is not fixed at 100x100, but is the same as the dimensions of the first input file. I have looked at "-format" and could probably do it in conjunction with environment variables and the like, but is there a more direct way?

How would I then change the "+50+50" so that it was dynamically calculated to be "Width/2 x Height/2"?

Re: Using first image in a layering op. to set output image

Posted: 2012-10-21T17:17:26-07:00
by fmw42
Looks like you are on windows. If so, you do not need to escape the parentheses with ^. As to your main question, in general, you have to compute variables ahead of time and then use them in your command line. IM 6 does not have the flexibility to do what you want, except for a few options, such as distort. IM 7 should be more flexible as this was on the main things that was on the wish list.


In particular with regard to your command, why do you need the 100x100 transparent background if you want the size to be the same as a.png?

Why not just do

convert a.png b.png -gravity center -composite c.png

The output will be the same size as a.png. Then b.png will be cropped by the limits of a.png, if b.png extends beyond. And both images will be centered. If you want the b.png top left to be at the center, then you will have to compute the offset from the center as half of the b.png image.



ww=`convert b.png -format "%[fx:w/2]" info:`
hh=`convert b.png -format "%[fx:h/2]" info:`
convert a.png b.png -gravity center -geometry +${ww}+${hh} -composite c.png

Sorry the above is unix style. For windows, see http://www.imagemagick.org/Usage/windows/


P.S. This will do the latter in one command by using -distort to compute and apply the shift

convert -respect-parenthesis a.png \( b.png -virtual-pixel none -filter point \
-set option:distort:viewport "%[fx:2*w]x%[fx:2*h]+0+0" -distort SRT "0,0 1 0 %[fx:w],%[fx:h]" +repage \) \
-gravity center -compose over -composite result.png

One needs to enlarge the viewport so that the shift will not crop the image.

see
http://www.imagemagick.org/Usage/distor ... t_viewport

Re: Using first image in a layering op. to set output image

Posted: 2012-10-21T18:23:05-07:00
by rossmcm
In particular with regard to your command, why do you need the 100x100 transparent background if you want the size to be the same as a.png?

Why not just do

convert a.png b.png -gravity center -geometry +50+50 -composite c.png

The output will be the same size as a.png. Then b.png will be cropped by the limits of a.png, if b.png extends beyond.
OK, didn't realise that was the behaviour. The script was a hangover from another one when the component layers were smaller than the desired destination size.
If you want the geometry offset to be half of the size of a.png, you still need to compute that before the command as variables.

ww=`convert a.png -format "%[fx:w/2]" info:`
hh=`convert b.png -format "%[fx:h/2]" info:`
convert a.png b.png -gravity center -geometry +${ww}+${hh} -composite c.png

Sorry the above is unix style. For windows, see http://www.imagemagick.org/Usage/windows/
I guess the equivalent path for me is via environment variables. If I execute

convert a.png -format "%wx%h" info:

I get "100x100" or whatever printed, but I need to know how to get that into an environment variable. Any ideas out there from the Windoze community?

Re: Using first image in a layering op. to set output image

Posted: 2012-10-21T18:26:29-07:00
by fmw42

Re: Using first image in a layering op. to set output image

Posted: 2012-10-21T19:24:32-07:00
by anthony
fmw42 wrote:This will do the latter in one command by using -distort to compute and apply the shift

convert -respect-parenthesis a.png \( b.png -virtual-pixel none \
-set option:distort:viewport "%[fx:2*w]x%[fx:2*h]+0+0" -distort SRT "0,0 1 0 %[fx:w],%[fx:h]" +repage \) \
-gravity center -compose over -composite result.png
WARHING. that shift may blur the image when you get a 1/2 pixel shift on a odd number sized image.

Also you can set image page positions using percent escapes using -set page instead of -repage, however you must set canvas size as well if you are interested in that, or it will reset it to 'no canvas' (canvas size 0x0) The real problem with use percent escapes is getting with and high from the first image into the setting for the second image. That means you have to extract the image properity and save it into a user based global variable, so that it is a vailable when setting the page of the second image.

Re: Using first image in a layering op. to set output image

Posted: 2012-10-21T20:02:02-07:00
by fmw42
Anthony wrote:WARHING. that shift may blur the image when you get a 1/2 pixel shift on a odd number sized image.
Agreed. But there is no possibility of a half pixel shift in the example above. The shifts are integers for width and height. If you want some fraction such as w/2 or h/2, then I suppose it would best to add round() into the fx calculation for the offset coordinates.

Re: Using first image in a layering op. to set output image

Posted: 2012-10-22T21:35:28-07:00
by rossmcm
For what it's worth, what follows is a simple Windows batch file routine for getting the dimensions of an image file (in a format that can be used in a IM -geometry argument) and setting an environment variable to the result.

Code: Select all

@echo off
goto Start

:GetImageSize (filename)
:
    FOR /F %%x IN ('convert "%~1" -format "%%wx%%h" info:') DO SET ImageSize=%%x
    exit /b

:Start

    call :GetImageSize "Image.png"
    echo Image dimensions are %ImageSize%
The routine is shown used here within the same file as the caller, but it could equally well live in it's own file, in which case the "call :GetImageSize" should be replaced with "call GetImageSize.bat" (note no preceding colon) assuming that's what you also called the batch file, and it's on the path.