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

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
User avatar
rossmcm
Posts: 28
Joined: 2012-07-26T06:10:38-07:00
Authentication code: 15
Location: Auckland, NZ

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

Post 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"?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

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

Post 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
Last edited by fmw42 on 2012-10-21T19:24:06-07:00, edited 6 times in total.
User avatar
rossmcm
Posts: 28
Joined: 2012-07-26T06:10:38-07:00
Authentication code: 15
Location: Auckland, NZ

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

Post 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?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

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

Post by fmw42 »

User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

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

Post 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.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

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

Post 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.
User avatar
rossmcm
Posts: 28
Joined: 2012-07-26T06:10:38-07:00
Authentication code: 15
Location: Auckland, NZ

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

Post 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.
Post Reply