How to combine 2 images?

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?".
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

How to combine 2 images?

Post by imanasya »

Is it possible write a code for ImageMagick which takes 2 images, scales them to max size (w or h) keeping aspect ratio and creates combined image placing first one on top of the second? Maintaining best possible jpg quality with bicubic automatic scaling similar to Photoshop? I have ImageMagick 7.0.8-12 Q16 x64 installed on Windows 10. Inputs are jpg without transparency. Aspect ratio, width and height of every image may vary. If h>w fill 2 holes with white.

https://i.stack.imgur.com/7gOTH.png
https://i.stack.imgur.com/xXoWF.png
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to combine 2 images?

Post by fmw42 »

red:
Image

green:
Image

This IM 7 command should work for both Unix and Windows. If in a bat file, I believe you need to double % to %5

Code: Select all

magick red.jpg green.jpg -set option:ww "%[fx:max(u.w,v.w)]" -set option:hh "%[fx:max(u.h,v.h)]" -resize "%[ww]x%[hh]" -background white -gravity center -append -quality 100 red_green.jpg
Image
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

Re: How to combine 2 images?

Post by imanasya »

Thank you very much! I put this line in my bat file:

Code: Select all

magick image_0.jpg image_1.jpg -set option:ww "%%[fx:max(u.w,v.w)]" -set option:hh "%%[fx:max(u.h,v.h)]" -filter Catrom -resize "%%[ww]x%%[hh]" -unsharp 0x1+1+0.05 -background white -gravity center -append -quality 100 combined.jpg
and it works. But it doesn't resize to max dimension. I take img0 356x800 and img1 596x770. Combined img is 569x1570. It does not scale up img1 596x770 to max value 800=max{356,800,596,770} img1 619x800. The combined image must be 619x1600 in this case.
Is it possible to add -fuzz 3% -trim +repage in the beginning? For some reason it shows error.
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

Re: How to combine 2 images?

Post by imanasya »

As I see this line scales up the first image only. How can I divide what to do with the first image and what to do with the second?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to combine 2 images?

Post by fmw42 »

I am not sure I fully understand what you want, but try this as the basic geometry command. You can add your own filtering for resize as desired and any unsharp masking. I just want to be sure I understand the resizing issue.

red:
Image

green:
Image

Unix and non-bat Windows syntax:

Code: Select all

magick red2.jpg green2.jpg -set option:dim "%[fx:max(max(u.w,v.w),max(u.h,v.h))]" -resize "%[dim]x%[dim]" -background white -gravity center -append -quality 100 red_green2.jpg
Image

This will resize both images so that both have their max dimensions set to the largest dimension of the two images (preserving aspect ratio). The complication is when one images has its largest dimension in width and the other in height.

If this is not what you want, the please clarify further or give me another example.

Is it possible to add -fuzz 3% -trim +repage in the beginning? For some reason it shows error.
What error message? That should work fine if you put that right after reading the images, if you want both trimmed. Recall that for Windows bat all % need to be doubled, so -fuzz 3% should be 3%%.
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

Re: How to combine 2 images?

Post by imanasya »

Thank you.
I have a code on windows cmd with ffmpeg which describes what I'm trying to do:

Code: Select all

if !w1! LSS !h1! (                  rem w1<h1  356<800
  set "p1=oh/mdar:h='max(ih,main_h)'"                  rem w=356:h=800
  if !w2! LSS !h2! (                  rem w1<h1 & w2<h2  356<800 & 596<770
    set "p2=oh/mdar:h='max(ih,main_h)'"                  rem w=596*800/700=619:h=800
  ) else (                  rem w1<h1 & w2>=h2
    set "p2='max(iw,main_w)':h=ow/mdar"
  )
) else (                  rem w1>=h1
  set "p1='max(iw,main_w)':h=ow/mdar"
  if !w2! LSS !h2! (                  rem w1>=h1 & w2<h2
    set "p2=oh/mdar:h='max(ih,main_h)'"
  ) else (                  rem w1>=h1 & w2>=h2
    set "p2='max(iw,main_w)':h=ow/mdar"
  )  
)
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to combine 2 images?

Post by fmw42 »

Was my last command not what you needed?

Sorry, I am not a Windows user or programmer. If you can explain what you want functionally or mathematically or in pseudocode, perhaps I can help. Otherwise, one of the Windows users might be able willing to help you further.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to combine 2 images?

Post by fmw42 »

scales them to max size (w or h) keeping aspect ratio and creates combined image placing first one on top of the second?

If h>w fill 2 holes with white.
These two requirement are not consistent as I understand it.

The first says make both images have either width or height equal to the largest width or height.

The second seems to imply that you really only want to scale the heights.

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

Re: How to combine 2 images?

Post by fmw42 »

If you need the width padded with white to the same dimension as each image's final resized height, then you can do one of these two depending upon what you want. Basically just add -extent Wx.

This resizes the larger dimension of each image to the largest dimension of both images.

Code: Select all

magick red2.jpg green2.jpg -set option:dim "%[fx:max(max(u.w,v.w),max(u.h,v.h))]" -resize "%[dim]x%[dim]" -background white -gravity center -append -gravity north -extent "%[dim]x" -quality 100 red_green3.jpg
Image

This resizes the height of each image to the largest dimension of both images.

Code: Select all

magick red2.jpg green2.jpg -set option:dim "%[fx:max(max(u.w,v.w),max(u.h,v.h))]" -resize "x%[dim]" -background white -gravity center -append -gravity north -extent "%[dim]x" -quality 100 red_green4.jpg
Image
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

Re: How to combine 2 images?

Post by imanasya »

fmw42, thank you very much, you are a genius! Half of the page windows code you wrote in one line. Could you explain a little bit: this line finding max value (w1,w2,h1,h2)

Code: Select all

-set option:dim "%%[fx:max(max(u.w,v.w),max(u.h,v.h))]"
Then how this operator

Code: Select all

-resize "%%[dim]x%%[dim]"
manages to identify which side w or h it has to increase to max value?
Finally, I stopped at this:

Code: Select all

magick image_0.jpg image_1.jpg -fuzz 2%% -trim +repage -set option:dim "%%[fx:max(max(u.w,v.w),max(u.h,v.h))]" -filter Catrom -resize "%%[dim]x%%[dim]" -unsharp 0x1+0.8+0.05 -background white -gravity center -append -quality 100 combined.jpg
Default unsharp gain seams too hard for me. Can I make resample or jpg quality better?
Is it possible to add if (w1>h1 and w2<h2 after the trim) do the line above, else do this:

Code: Select all

magick image_0.jpg -quality 100 first.jpg
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: How to combine 2 images?

Post by fmw42 »

-set option:dim "%%[fx:max(max(u.w,v.w),max(u.h,v.h))]"
In Imagemagick, the fx function max() only takes two argument. So I took the max of the two height, and the max of the two width and then the max of the two max's.
-resize "%%[dim]x%%[dim]"
This will take whichever dimension (width or height of an image is greater and resize to %[dim]. The smaller dimension will be resized to preserve aspect ratio. See https://imagemagick.org/script/command- ... p#geometry

You can do unsharp masking and control the arguments. See https://imagemagick.org/script/command- ... hp#unsharp. The sigma can be smaller than 1. So you can go down to about 0.5 before it produces no appreciable change.

Is it possible to add if (w1>h1 and w2<h2 after the trim)
Yes, you can put in conditionals, as a ternary condition. But the results of the condition can only be values or fx arguments such as w or h. You cannot easily make it do different commands. See https://imagemagick.org/script/fx.php. If you can explain what you want mathematically or pseudocode, then perhaps I can clarify further or give you the Imagemagick command.
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

Re: How to combine 2 images?

Post by imanasya »

Mathematically I'd like to check before the main magic command if (w1>h1 and w2<h2) after the trim.

If it is true then do

Code: Select all

magick image_0.jpg image_1.jpg -fuzz 2%% -trim +repage -set option:dim "%%[fx:max(max(u.w,v.w),max(u.h,v.h))]" -filter Catrom -resize "%%[dim]x%%[dim]" -unsharp 0x1+0.8+0.05 -background white -gravity center -append -quality 100 combined.jpg
If not true do this:

Code: Select all

magick image_0.jpg -fuzz 2%% -trim +repage -quality 100 first.jpg
I know how to check it (w1>h1 and w2<h2) BEFORE the trim, it will look like this:

Code: Select all

@echo off&setlocal enabledelayedexpansion

for /f "tokens=1,2 delims=:" %%x in ('identify -format %%w:%%h image_0.jpg') do set a/ w1=%%x&set a/ h1=%%y
for /f "tokens=1,2 delims=:" %%x in ('identify -format %%w:%%h image_1.jpg') do set a/ w2=%%x&set a/ h2=%%y

if !h1! LSS !w1!	(		#w1>h1
  if !w2! LSS !h2! (		#w2<h2
  ) else (
  )
)
But I don't know how can I get w1, h1, w2, h2 AFTER the trim.
Last edited by imanasya on 2018-10-07T03:59:28-07:00, edited 3 times in total.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to combine 2 images?

Post by snibgo »

I'm not sure what you are asking. The "for" loops can use "convert" instead of "identify", so can do any processing you want before calculating width and height.
snibgo's IM pages: im.snibgo.com
imanasya
Posts: 36
Joined: 2018-10-05T11:21:07-07:00
Authentication code: 1152

Re: How to combine 2 images?

Post by imanasya »

snibgo, thank you. Maybe I didn't manage to explain clearly. I use "for" loops for getting values w1, h1, w2, h2 only (parse the strings) , not for the processing. They are original files values. When the trim command ends these values are changing:

Code: Select all

magick image_0.jpg image_1.jpg -fuzz 2%% -trim +repage
And depending on these changed values

Code: Select all

if (w1>h1 & w2<h2)
do this:

Code: Select all

magick image_0.jpg image_1.jpg -fuzz 2%% -trim +repage -set option:dim "%%[fx:max(max(u.w,v.w),max(u.h,v.h))]" -filter Catrom -resize "%%[dim]x%%[dim]" -unsharp 0x1+0.8+0.05 -background white -gravity center -append -quality 100 combined.jpg
else do this:

Code: Select all

magick image_0.jpg -fuzz 2%% -trim +repage -quality 100 first.jpg
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How to combine 2 images?

Post by snibgo »

I can see you don't do any processing in the "for" commands. But you can if you want, and that may help to solve your problem. For example:

Code: Select all

for /f "tokens=1,2 delims=:" %%x in ('convert image_0.jpg -fuzz 2%% -trim +repage -format %%w:%%h +write info: tmp0.png') do set a/ w1=%%x&set a/ h1=%%y 
snibgo's IM pages: im.snibgo.com
Post Reply