graphicsmagick - tips for optimizing montage and composite? - graphicsmagick

for a little photo booth application have this problem:
I have 4 pictures, which i would like to tile together, using montage. The result get a 150px border using a transparent PNG and composite. But because the "frame" is larger than the base image, I have to add an additional convert to add artificial 150px border around the tiled image.
This is functional but very slow and seems not very elegant:
gm montage -geometry +20+20 -tile 2x2 /home/pi/dev/*.jpg miff:- | gm convert -border 150x150 miff:- miff:- | gm composite /home/pi/dev/rahmen.png miff:- /home/pi/dev/partyknipse.JPG
Is there any way I could optimize this and speed up the process? Get rid of the convert?
I guess the -geometry parameter of the composite could be useful, but didn't fully understand it so far.
This is roughly what it should look like in the end:
red border is a png, the four grey boxes are the tiled image

Not sure how long your operations take, or what you expect, but here are a couple of ideas...
Assume I have im1.jpg through m4.jpg which are the 4 small images and a larger red frame that is a "hollow" PNG with a transparent hole in the middle.
Firstly, if you were to switch to ImageMagick (rather than GraphicsMagick) you could do it all in one go with:
convert frame.png -background white -flatten \
im1.jpg -geometry +80+80 -composite \
im2.jpg -geometry +260+80 -composite \
im3.jpg -geometry +80+200 -composite \
im4.jpg -geometry +260+200 -composite result.png
Second, you could try something like this batching GraphicsMagick and storing intermediate steps in memory (MPR = Magick Program Register) which is effectively a named lump of RAM:
{ echo convert frame.png -background white -flatten mpr:frame;
echo montage -geometry +20+20 -tile 2x2 im*.jpg mpr:images;
echo composite mpr:images -geometry +100+40 mpr:frame result.png; } | gm batch -prompt off

Related

Composing a new graphic in R with magick from multiple existing images

I've created a table with the excellent gt package. Since it was a long table, my code creates the table in two halves. I save both halves to disk as png files then use the magick package's image_append() to composite them side-by-side as a new png file. All good.
Now, with magick, I'd like to compose a final graphic with a logo, some title text and source notes using image_annotate(), and my saved table, all laid out nicely.
I'm stuck trying to understand the right way to do that. I have all the graphical pieces, but I don't know how to create new, blank graphic with magick and then lay those pieces out in the locations I want them so that the finished product looks like this:
There are a lot of ways to create text images in Imagemagick. But here is likely the easiest for you to use and convert to R. The following is command line Imagemagick.
Logo:
Table Text Image:
Steps: (In subsequent command)
- Line 1: load imagemagick convert
- Line 2: create 500x500 white background image
- Line 3: insert the logo image at +20+20 relative to top left
- Line 4: add title text via -annotate
- Line 5: add sub-title text via -annotate
- Line 6: insert the preformed table image below those
- Line 7: add the source notes text via -annotate
- Line 8: save the resulting png file to disk
Command:
convert \
-size 500x500 xc:white \
rainbow_logo.png -gravity northwest -geometry +20+20 -compose over -composite \
-font arial -fill black -pointsize 48 -annotate +125+15 "TITLE TEXT" \
-font arial -fill black -pointsize 32 -annotate +125+65 "SUB-TITLE TEXT" \
lorem.png -gravity northwest -geometry +20+140 -compose over -composite \
-font arial -fill black -pointsize 18 -annotate +20+455 "SOURCE NOTES" \
result2.png
Result:

Cloud functions Circle Image Imagemagick

I would like to convert uploaded pictures to Firebase Storage into circled images using Cloud functions and resize them.
Having a look at the documentation of ImageMagick I am wondering about the syntax to use for this task. Using the below to resize the image which works like a charm. But how would I add the commands into this and which ones to use best?
return spawn('convert', [tmpFilePath, '-resize', '250x250', tmpFilePath]);
I don't know what a 'circle image' means, but perhaps applying Vignette effect?
convert -size 250x250 plasma: -background white -vignette 0x0 output.png
So your command may be...
return spawn('convert', [
tmpFilePath,
'-resize', '250x250',
'-background', 'white',
'-vignette', '0x0',
tmpFilePath
]);
emcconville probably has the simplest method. You may just need to make the background transparent and replace the plasma image with a real image.
If you want the outside to be transparent, be sure to save your output to PNG or TIFF and not JPG. JPG does not support transparency.
Input:
convert lena.jpg -background none -vignette 0x0 output.png
However, the circle's perimeter will not extend to the edges of the image.
To make it do that, you have to change the arguments as follows:
convert lena.jpg -background none -vignette 0x0+0+0 output2.png
But here is another method that is a bit longer and more complex (assuming you have a square image).
If by "circled images" you mean make the outside of a circle the size of the image transparent, you can do that in ImageMagick command line as follows:
1) Read the image (and somehow get its size)
2) Then create a new image the same size and fill with black and draw a white circle supplying the center point and any point on the perimeter
3) Put the circle image into the alpha channel of the original
Original:
Unix Syntax. (For Windows remove the \s in the following)
convert lena.jpg \( -size 256x256 xc:black -fill white -draw "circle 128,128 128,255" \) -alpha off -compose copy_opacity -composite result.png
In Unix syntax one can get the dimensions of the input image as follows:
WxH=`convert -ping lena.jpg -format "%wx%h" info:`
ww=`echo $WxH | cut -dx -f1`
hh=`echo $WxH | cut -dx -f2`
ww2=`convert xc: -format "%[fx:$ww/2]" info:`
hh2=`convert xc: -format "%[fx:$hh/2]" info:`
hhm1=$((hh-1))
convert lena.jpg \( -size ${ww}x${hh} xc:black -fill white -draw "circle $ww2,$hh2 $ww2,$hhm1" \) -alpha off -compose copy_opacity -composite result2.png
If you do not have a square image, then you must use the minimum dimension of the input image as the circle diameter. This also works for a square image.
Input:
dim=`convert -ping monet2.jpg -format "%[fx:min(w,h)]" info:`
dim2=`convert xc: -format "%[fx:$dim/2]" info:`
dimm1=$((dim-1))
convert monet2.jpg \( -size ${dim}x${dim} xc:black -fill white -draw "circle $dim2,$dim2 $dim2,$dimm1" \) -alpha off -gravity center -compose copy_opacity -composite result4.png
If we use the vignette method on a non-square image, then you will get an elliptical region.
convert monet2.jpg -background none -vignette 0x0+0+0 output3.png

How to keep the orientation number(exif) after converting from a video file to a image file by a ffmpeg command

The command below is working perfectly fine for my environment except it deletes the orientation number(exif) of the image file after being converted from a video file.
I'd like to know how to keep the orientation number(exif) of the image with the command line below(it also have to keep the original purpose of its functionality which is to convert a video to a image from one directory to another.). I'd appreciate if anyone could help me out.
for i in /path/to/inputs/*.mp4; do ffmpeg -i "$i" -frames:v 1 "/path/to/outputs/$(basename "$i" .mp4).jpg"; done
ffmpeg version 2.2.2
OS:centos-6 (x86_64)
tl;dr
Update your ffmpeg and it will automatically rotate then you won't have to deal with exif tags.
rotate side data
MP4 does not contain exif data, but it can contain rotate side data. This is information a player can use to properly orient the video (not all players or devices support this), even if the video stream itself is not oriented as such. Videos from iPhones for example have this side data.
ffmpeg auto-rotates
When encoding, ffmpeg will by default automatically rotate the output depending on the rotate side data. So you may not need to set the exif orientation tag at all. You can disable this behavior by using the -noautorotate option. Note that your ffmpeg (version 2.2) is too old for this behavior and this option, so it does not automatically rotate. I recommend you download a recent ffmpeg version and move it to /usr/local/bin.
So, given that non-ancient ffmpeg will automatically rotate do you even need to deal with the exif orientation tag? If you answer "yes" then see the sections below.
viewing rotate side data in MP4 video
You can use ffprobe to view the rotate side data of the input video:
ffprobe -loglevel error -select_streams v:0 -show_entries side_data=rotation -of csv=p=0 input.mp4
setting exif orientation tag in JPG image
You can use exiftool to write the orientation exif tag to the JPG image:
exiftool -Orientation=6 -n image.jpg
Or a human readable form:
exiftool -Orientation='Rotate 90 CW' image.jpg
Numerical Orientation values are:
1 = Horizontal (normal)
2 = Mirror horizontal
3 = Rotate 180
4 = Mirror vertical
5 = Mirror horizontal and rotate 270 CW
6 = Rotate 90 CW
7 = Mirror horizontal and rotate 90 CW
8 = Rotate 270 CW
As for implementing this in your bash script I think that's worth asking as a separate question.
viewing exif orientation tag in JPG image
You can use exiftool to view the orientation:
$ exiftool -Orientation -S image.jpg
Orientation: Rotate 90 CW
$ exiftool -Orientation -n -S image.jpg
Orientation: 6

How to colorize a black-transparent PNG icon with ImageMagick

How do I a colorize a black PNG image that has a transparent background using ImageMagick?
Use case:
You have several PNG images like this:
And I want to colorize them like this:
I want to use ImageMagick's convert command, allowing for scripting to process hundreds of icons at a time.
You can use one of the following commands:
$ convert input.png +level-colors "red", output.png
$ convert input.png +level-colors "rgb(255,0,0)", output.png
$ convert input.png +level-colors "#ff0000", output.png
Note that the , character is important here. On the left side of the , character we tell convert which color should replace black and on right side what color should replace white. Therefore nothing should be given after the , character.
Source
... how do I colorize black & transparent PNG images [...] to colorize them like this [...] using ImageMagick
The -fill <COLOR> option works fantastic for this purpose. You can replace "#1bbfc9" with a human-readable name (e.g. "red") or an HTML color code.
convert target-black.png -fill "#1bbfc9" -colorize 100 target-blue.png
... allowing to script and process hundreds of icons at a time
Using the find command, you can recurse hundreds.
Warning: This will replace the originals.
find path/to/files -iname '*.png' -exec convert "{}" -fill "#1bbfc9" -colorize 100 "{}" \;
With ImageMagick, you can process a whole folder of images at one time with mogrify rather than convert if you want all the same color. Create a new output directory to hold the colorized files. Then cd to the folder holding your images.
cd path_to/image_folder
mogrify -format png -path path_to/new_folder -fill "cyan" -colorize 100 *.png
Where replace path_to with your actual path.
You may use color names, hex colors or rgb(...) colors in the fill command, but enclose them in quotes on Linux/Mac OSX. Quotes are not needed for Windows, but should not cause any issues if double quotes.
See mogrify

Invert PNG graphics file with a non-interactive command

I'm using DruTex, which is a Drupal module to embed Latex equations. The context of the equation is marked, and a Latex interpreter will generate a PNG file:
dvipng -o [IMG_FILE] -D [DPI] -T tight [TMP_DIR]/[HASH].dvi
The dvipng utility is used to generate a PNG from Latex's DVI file. That's good so far, but I could need black background and white foreground for these equations, since otherwise they are hard to read, because they appear in a dark-themed way.
convert (from Imagemagick) doesn't have an -invert flag. Neither does dvipng. So is there a way to invert a png file? I can add something to that routine like:
batch_invert -input [IMG_FILE] -out [IMG_FILE]
However I do not know how I can implement that.
convert has a -negate option that works.
Example:
convert -negate input.png output.png

Resources