Combining 3 imagemagick cli parameters into one ImageMagick.NET code - imagemagick

Hey all I have these 3 imageMagick scripts (command line arguments) that I am trying to combine into Imagemagick.NET code.
First (merging 2 images together):
convert ^
( testingl.jpg -resize 610x440^^ -gravity West -extent 1080x440 ) ^
( testingr.jpg -resize 610x440^^ -gravity East -extent 1080x440 ) ^
blend_mask.png -blur 0x7 ^
-composite bothImagesMerged.jpg
Second (Create 2 round objects with photo inside):
convert lisa.jpg -resize 100x100! ^
null: ( -size 100x100 xc:black -fill white -draw "circle 50,50 50,88" ) ^
-alpha off -compose copy_opacity -layers composite ^
null: ( -size 100x100 xc:"graya(100%,0)" -fill black -draw "circle 50,50 50,90" -blur 0x5 ) ^
-compose dstover -layers composite ^
-background none -gravity center +smush -25+0 ^
roundImageLisa.png
convert homer.jpg -resize 100x100! ^
null: ( -size 100x100 xc:black -fill white -draw "circle 50,50 50,88" ) ^
-alpha off -compose copy_opacity -layers composite ^
null: ( -size 100x100 xc:"graya(100%,0)" -fill black -draw "circle 50,50 50,90" -blur 0x5 ) ^
-compose dstover -layers composite ^
-background none -gravity center +smush -25+0 ^
roundImageHomer.png
Third (Write text on top of photo):
convert -size 1080x440 xc:none -gravity center ^
-font arial -pointsize 40 ^
-stroke black -strokewidth 2 -annotate +-330+-150 "Lisa Simpson" ^
-stroke black -strokewidth 2 -annotate +330+-150 "Homer Simpson" ^
-background none -shadow 520x3+0+0 +repage ^
-stroke none -fill white -annotate +-330+-150 "Lisa Simpson" ^
-stroke none -fill white -annotate +330+-150 "Homer Simpson" ^
bothImagesMerged.jpg +swap -gravity center -geometry +0-3 ^
-composite textOverImg.jpg
If I was able to combine all 3 of those then the output would look something like this:
I've tried to put all of them into a one-liner but can not seem to find the correct way (order mainly) into doing so.
I do have some code that produces the round images in C#:
Bitmap bitmap = new Bitmap("lisa.jpg");
MagickImageCollection images = new MagickImageCollection();
IMagickImage roundImg = null;
IMagickImage mask = new MagickImage("xc:black", 100, 100);
mask.Settings.FillColor = MagickColors.White;
mask.Draw(new DrawableCircle(50, 50, 50, 90));
mask.HasAlpha = false;
roundImg = new MagickImage(bitmap);
roundImg.Resize(100, 100);
roundImg.Composite(mask, CompositeOperator.CopyAlpha);
roundImg.Draw(new DrawableStrokeColor(MagickColors.Black),
new DrawableStrokeWidth(1),
new DrawableFillColor(MagickColors.None),
new DrawableCircle(50, 50, 50, 90));
IMagickImage shadow = new MagickImage("xc:none", 100, 100);
shadow.Settings.FillColor = MagickColors.Black;
shadow.Draw(new DrawableCircle(50, 50, 50, 90));
shadow.Blur(0, 5);
roundImg.Composite(shadow, CompositeOperator.DstOver);
images.Add(roundImg);
images.First().BackgroundColor = MagickColors.None;
IMagickImage result = new MagickImage();
result = images.SmushHorizontal(-35);
result.Write("lisa_round.png");
mask.Dispose();
shadow.Dispose();
result.Dispose();
images.Dispose();
Assistance would be great! #fmw42

Related

ImageMagick Ouput GIF

How can I make this output a GIF instead of a PNG:
convert GIF.gif ( +clone -alpha extract -virtual-pixel black -spread 10 -blur 0x3 -threshold 50% -spread 1 -blur 0x.7 ) -alpha off -compose Copy_Opacity -composite torn_paper.png

Imagemagick Spotify-like duotone overlay

Is it possible to achieve this degree of color manipulation using pure imagemagick commands?
I suppose it might be done with level-color and a special transparent png for shapes.
Also is it required to change original colors to b/w before any manipulations with color levels?
This is one way to do it in Imagemagick. Yes, you need mask images. You may or may not want to convert your input to grayscale. But in this case, I suspect you want to start with grayscale.
Here is my input:
Here I create 4 simple non-overlapping rectangular region binary masks. But in your example it looks like part of the yellow overlaps with the green to make the orange color
convert -size 100x299 xc:white -size 300x299 xc:black +append mask1.png
convert -size 100x299 xc:black -size 100x299 xc:white -size 200x299 xc:black +append mask2.png
convert -size 200x299 xc:black -size 100x299 xc:white -size 100x299 xc:black +append mask3.png
convert -size 300x299 xc:black -size 100x299 xc:white +append mask4.png
Then I create 4 different color images the same size as the input and composite them successively with the one each of the masks saving over the in-memory image (mpr:img) that I created from the grayscale image.
compose method: blend (50%-50%)
(Note other blend ratios can be applied if desired using -define compose:args=50,50 by changing the two numbers, but keep the total = 100)
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img -fill red -colorize 100 \) mask1.png -compose blend -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill green1 -colorize 100 \) mask2.png -compose blend -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill blue -colorize 100 \) mask3.png -compose blend -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill yellow -colorize 100 \) mask4.png -compose blend -composite \
result1.jpg
compose method: multiply
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img -fill red -colorize 100 \) mask1.png -compose multiply -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill green1 -colorize 100 \) mask2.png -compose multiply -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill blue -colorize 100 \) mask3.png -compose multiply -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill yellow -colorize 100 \) mask4.png -compose multiply -composite \
result2.jpg
compose method: overlay
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img -fill red -colorize 100 \) mask1.png -compose overlay -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill green1 -colorize 100 \) mask2.png -compose overlay -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill blue -colorize 100 \) mask3.png -compose overlay -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill yellow -colorize 100 \) mask4.png -compose overlay -composite \
result3.jpg
compose method: colorize
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img -fill red -colorize 100 \) mask1.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill green1 -colorize 100 \) mask2.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill blue -colorize 100 \) mask3.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill yellow -colorize 100 \) mask4.png -compose colorize -composite \
result4.jpg
There are many other compose methods that you could try. See https://imagemagick.org/Usage/compose/
You can also do the same using +level-colors with either black or white as the second color.
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,red \) mask1.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,green1 \) mask2.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,blue \) mask3.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,yellow \) mask4.png -compose colorize -composite \
result5.jpg
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img +level-colors red,white \) mask1.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors green1,white \) mask2.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors blue,white \) mask3.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors yellow,white \) mask4.png -compose colorize -composite \
result6.jpg
You can do it also with -tint.
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img -fill red -tint 100 \) mask1.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill green1 -tint 100 \) mask2.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill blue -tint 100 \) mask3.png -compose colorize -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill yellow -tint 100 \) mask4.png -compose colorize -composite \
result7.jpg
The results differ with different compose methods. Here are that last 3 with compose over rather than compose colorize:
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,red \) mask1.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,green1 \) mask2.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,blue \) mask3.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors black,yellow \) mask4.png -compose over -composite \
result5b.jpg
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img +level-colors red,white \) mask1.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors green1,white \) mask2.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors blue,white \) mask3.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img +level-colors yellow,white \) mask4.png -compose over -composite \
result6b.jpg
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img -fill red -tint 100 \) mask1.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill green1 -tint 100 \) mask2.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill blue -tint 100 \) mask3.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img -fill yellow -tint 100 \) mask4.png -compose over -composite \
result7b.jpg
See also https://imagemagick.org/Usage/color_mods/#duotone for a method using a custom colored look-up table image with the -clut function. Here is that method:
convert barn.jpg -colorspace gray -write mpr:img +delete \
mpr:img \( mpr:img \( -size 1x1 xc:black xc:red xc:white +append -size 1x256 gradient: -rotate 90 +swap -interpolate Bicubic -clut \) -interpolate Bicubic -clut \) mask1.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img \( -size 1x1 xc:black xc:green1 xc:white +append -size 1x256 gradient: -rotate 90 +swap -interpolate Bicubic -clut \) -interpolate Bicubic -clut \) mask2.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img \( -size 1x1 xc:black xc:blue xc:white +append -size 1x256 gradient: -rotate 90 +swap -interpolate Bicubic -clut \) -interpolate Bicubic -clut \) mask3.png -compose over -composite -write mpr:img +delete \
mpr:img \( mpr:img \( -size 1x1 xc:black xc:yellow xc:white +append -size 1x256 gradient: -rotate 90 +swap -interpolate Bicubic -clut \) -interpolate Bicubic -clut \) mask4.png -compose over -composite \
result8.jpg
This appears to me to be the closest colorization result to that which was used in your original example.

Re-coloring image preserving luminance

Given an input image, I was thinking about how the image could be re-colored to a single new color keeping the luminance of the image similar to what it was earlier.
So I wrote a naive code:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <bits/stdc++.h>
using namespace cv;
using namespace std;
int main() {
Mat img = imread("test2.png", 1);
Mat hsv; cvtColor(img, hsv, CV_BGR2HSV);
vector<Mat > channels;split(hsv, channels);
Mat luminance; channels[2].copyTo(luminance);
Mat res; img.copyTo(res);
channels.clear(); split(res, channels);
for (int i = 0; i<res.rows; i++) {
for (int j = 0; j<res.cols; j++) {
channels[0].at<uchar>(i, j) = 0;
channels[1].at<uchar>(i, j) = 0;
channels[2].at<uchar>(i, j) = 255;
}
}
merge(channels, res);
cvtColor(res, hsv, CV_BGR2HSV);
channels.clear(); split(hsv, channels);
luminance.copyTo(channels[2]);
merge(channels, res);
cvtColor(res, res, CV_HSV2BGR);
imwrite("result.png", res);
return 0;
}
What I actually did is just extracted the luminance map of the original image, then created an image with the color I want it to be in, and replaced the luminance map of this output image with the luminance map of input image.
But resultant image seems to be darker in shade. Is there any better way to do this?
Input image:
Resulting image:
I think you are looking for "tinting". I don't have any references for how you to do it with OpenCV but there is a description in Anthony Thyssen's excellent ImageMagick notes here - search for the word "somehow". Maybe you can adapt it to OpenCV, if the effect is what you seek.
At the command-line, with ImageMagick, I did this:
convert drop.png -fill red -tint 50% result.jpg
Here is another way in Imagemagick.
convert \( input.png -colorspace gray \) \( -clone 0 -fill red -colorize 100 \) \( -clone 0 \) -compose colorize -composite result1.png
convert \( input.png -colorspace lab -channel red -separate \) \( -clone 0 -fill red -colorize 100 \) \( -clone 0 \) -compose colorize -composite result2.png
convert \( input.png -colorspace hsi -channel blue -separate \) \( -clone 0 -fill red -colorize 100 \) \( -clone 0 \) -compose colorize -composite result3.png
Choose what colorspace represents the intensity/luminance you want to use. See my script, color2gray at http://www.fmwconcepts.com/imagemagick/color2gray/index.php to see what different colorspace intensity/luminance show as gray.

ImageMagick, insert an image at a specific position / size into a larger image?

I'm firstly drawing a wide transparent image with columns, which works fine.
convert -size 5568x1920 xc:none iphone6plus.png
convert iphone6plus.png -strokewidth 0 -fill lightgray -draw "rectangle 1080,0 1121,1920 " iphone6plus.png
convert iphone6plus.png -strokewidth 0 -fill lightgray -draw "rectangle 2202,0 2243,1920 " iphone6plus.png
convert iphone6plus.png -strokewidth 0 -fill lightgray -draw "rectangle 3324,0 3365,1920 " iphone6plus.png
convert iphone6plus.png -strokewidth 0 -fill lightgray -draw "rectangle 4446,0 4487,1920 " iphone6plus.png
Then I'm rotating another image, again works fine.
convert /en-US/iPhone6Plus-main_start_multi_child.png \
-rotate -2 \
iphone6plus-new.png
However, I'm trying to insert the second (rotated image) into the first image at a specific position / size. I'm having problems, I've tried several things, the closest I've got seems to overwrite the source image.
convert iphone6plus.png \
-geometry 40x40+5+10 \
-composite \
iphone6plus-new.png
What should I be using?
Also how should I improve the speed of this operation.
EDIT: Issue shown below...
convert -size 5568x1920 xc:none -strokewidth 0 -fill lightgray \
-draw "rectangle 1080,0 1121,1920 " \
-draw "rectangle 2202,0 2243,1920 " \
-draw "rectangle 3324,0 3365,1920 " \
-draw "rectangle 4446,0 4487,1920 " \
\( iPhone6Plus-main_start_multi_child.png -background transparent -rotate -2 -gravity center -resize 1473x755 \) \
-geometry -190-50 \
\( iPhone6Plus-test_multi_child.png -background transparent -gravity center -resize 1473x755 \) \
-geometry +2000-50 \
-composite iphone6plus-new.png
convert -size 5568x1920 xc:none -strokewidth 0 -fill lightgray \
-draw "rectangle 1080,0 1121,1920 " \
-draw "rectangle 2202,0 2243,1920 " \
-draw "rectangle 3324,0 3365,1920 " \
-draw "rectangle 4446,0 4487,1920 " \
\( iPhone6Plus-test_multi_child.png -background transparent -gravity center -resize 1473x755 \) \
-geometry +2000-50 \
-composite iphone6plus-new.png
Firstly, settings such as strokewidth and fill persist until changed, so don't keep repeating them.
Secondly, just create your background once and keep adding to it rather than saving and closing and then re-opening on the next line.
convert -size 5568x1920 xc:none -strokewidth 0 -fill lightgray \
-draw "rectangle 1080,0 1121,1920 " \
-draw "rectangle 2202,0 2243,1920 " \
-draw "rectangle 3324,0 3365,1920 " \
-draw "rectangle 4446,0 4487,1920 " basic.png
Now, load in your new image that needs rotating and apply rotation to it inside parentheses so that the rest is not affected, then composite that onto the background:
convert -size 5568x1920 xc:none -strokewidth 0 -fill lightgray \
-draw "rectangle 1080,0 1121,1920 " \
-draw "rectangle 2202,0 2243,1920 " \
-draw "rectangle 3324,0 3365,1920 " \
-draw "rectangle 4446,0 4487,1920 " \
\( SomeOtherImage.png -rotate -2 -resize AxB \) \
-geometry +X+Y -composite result.png
You may need +repage after the -resize AxB.
Updated Answer
Does this get closer to what you need maybe?
#!/bin/bash
convert -size 5568x1920 xc:none -strokewidth 0 -fill lightgray -background transparent -gravity center \
-draw "rectangle 1080,0 1121,1920" \
-draw "rectangle 2202,0 2243,1920" \
-draw "rectangle 3324,0 3365,1920" \
-draw "rectangle 4446,0 4487,1920" \
\( xc:blue[1024x768] -rotate -2 -resize 1473x755 \) -geometry -190-50 -composite \
\( xc:red[1024x768] -resize 1473x755 \) -geometry +2000-50 -composite result.png

ImageMagick drawing a series of images with growing glow effect

I'm learning ImageMagick. I want to create (with ImageMagick) a series of images
that after using the command
convert -delay 0 -loop 0 frame*.gif final.gif
gives the result like the attached animated gif.
I want to program the series of commands myself, but I need a hint for which effects and drawing instructions will give me the most similar result, so I'm looking for something like:
draw a circle
blur it
save the frame
increase the radius of the circle
repeat
but, probably the above is not enough.
Is this question very vague or can somebody give me a hint?
If you are in a shell environment (OSX or Linux) you could do something like this, which creates a series of blurred circles in ever-increasing radii and saves the image in appropriately named files...
for RAD in {10,20,30,40,50,60,70,80,90}; do convert -size 400x300 xc:black -fill cyan -stroke cyan -draw "translate 200,150 circle 0,0 $RAD,0" -blur 0x8 blur_circle$RAD.gif; done
To get fancier, you could add repeated blur operations, or more blur for the larger radii.
Then, as you suggest convert those to an animated gif:
convert -delay 0 -loop 0 blur_circle*.gif final.gif
EDIT
Working version closer to original "vision"
Here is a version that uses python to generate two circles, whose transparency varies on different time scales. With the current settings, transparency over time looks like this graph, but you can generate any lists of integer values to get different effects:
Here is the image produced by the program:
And here is the program itself:
#! /usr/bin/env python
""" Using imagemagick, generate a series of .gifs with fuzzy circles in them...
When the program is done, create an animated gif with:
convert -delay 0 -loop 0 blur_circle*.gif final.gif
(P.S. I know it is not 'convention' to capitalize variable names, but it makes
it easier to distinguish my definitions from built-ins)"""
import subprocess
import sys
CanvasW = 400
CanvasH = 400
CenterX = int(CanvasW/2)
CenterY = int(CanvasH/2)
InnerDia = 75
OuterDia = 155
BaseNameString = "blur_circles"
# play with overall blur level - 2 to 8
# this is in addition to the distance fuzzing
BlurLevel = '8'
# The following three lists must be the same length
# Transparency levels of the inner circle, ramping up and down
InnerAlphaList = range(0,101,10) + range(90,9,-20) + [5,0,0,0]
print "Inner:",len(InnerAlphaList),InnerAlphaList
# Transparency of the outer circle
OuterAlphaList = range(0,51,8) + range(40,9,-12) + range(8,0,-2) + [0,0,0,0,0,0]
print "Outer:",len(OuterAlphaList), OuterAlphaList
# Add 100 so the file names get sorted properly?
NameNumberList = range(101, 101+len(InnerAlphaList))
# Changing the Euclidaan distance parameters affects how fuzzy the objects are
BaseCommand = '''convert -size {w}x{h} xc:black \
-fill "rgba( 0, 255,255 , {outal:0.1f} )" -stroke none -draw "translate {cenx},{ceny} circle 0,0 {outdia},0" -morphology Distance Euclidean:4,1000\
-fill "rgba( 0, 255,255 , {inal:0.1f} )" -stroke none -draw "translate {cenx},{ceny} circle 0,0 {india},0" -morphology Distance Euclidean:4,500 \
-blur 0x{blur} {basename}_{namenum}.gif'''
sys.stderr.write("Starting imagegen .")
for InAlpha,OutAlpha,NameNumber in zip(InnerAlphaList,OuterAlphaList,NameNumberList):
FormattedCommand = BaseCommand.format(
w = CanvasW, h = CanvasH,
cenx = CenterX, ceny = CenterY,
india = InnerDia, outdia = OuterDia,
blur = BlurLevel,
inal = InAlpha/100.0, outal = OutAlpha/100.0,
basename = BaseNameString,
namenum = NameNumber
)
sys.stderr.write(".")
# sys.stderr.write("{}\n".format(FormattedCommand))
ProcString = subprocess.check_output(FormattedCommand, stderr=subprocess.STDOUT,shell=True)
if ProcString:
sys.stderr.write(ProcString)
sys.stderr.write(" Done.\n")
""" BASE COMMANDS:
# inner circle:
convert -size 400x300 xc:black -fill "rgba( 0, 255,255 , 1 )" -stroke none -draw "translate 200,150 circle 0,0 75,0" -blur 0x8 -morphology Distance Euclidean:4,1000 blur_circle100.gif
#outer circle
convert -size 400x300 xc:black -fill "rgba( 0, 255,255 , .5 )" -stroke none -draw "translate 200,150 circle 0,0 150,0" -morphology Distance Euclidean:4,500 -blur 0x6 blur_circle100.gif
#both circles
convert -size 400x300 xc:black -fill "rgba( 0, 255,255 , .5 )" -stroke none -draw "translate 200,150 circle 0,0 150,0" -morphology Distance Euclidean:4,500 \
-fill "rgba( 0, 255,255 , 1 )" -stroke none -draw "translate 200,150 circle 0,0 75,0" -morphology Distance Euclidean:4,1000\
-blur 0x8 blur_circle100.gif
"""

Resources