Resizing animated GIF in image creates artifacts - image-processing

I'm trying to add a blank area around some animated GIFs using imagemagick, but in many cases the resulting larger animations have artifacts. For example, if I start with this image
And run the following command (which has the dispose and coalesce flags which I've thrown in after seeing them online in the hopes they'll help)
convert input.gif -gravity center -dispose previous -extent 500x500 -coalesce output.gif
The result is the following
Is there a different command I can run that wouldn't gave the green splotches invade the original image?

You have your syntax wrong for ImageMagick and also need to use -dispose none. You are adding a new color to your animation which likely already used 256 colors.
Input:
convert -dispose none input.gif -coalesce -gravity center -background green -extent 500x500 -layers optimize output.gif
Change the background color as desired, which you left out of your command.

Related

ImageMagick gif background not moving with png overlays

I am trying to change the background layer of a batch of png images to include a moving gif. I'm running on MacOs and imagemagick version 7.1.0-19.
There are two types of images I want to merge:
Overlay static images A*.png
Background image Moving#40.gif
The background gif takes 120 frames.
So far I have managed to build the images and create GIFs. However the animated gifs are not moving. I have tried including delay and loop but this does nothing. The code is as follows:
magick mogrify -format gif -delay 10 -draw 'image Dst_Over 0,0 0,0 "Moving#40.gif"' A*.png -loop 0
I have been looking for days for similar use cases but have not found a solution,I just recently got into ImageMagick so advice is much appreciated.
any ideas on how this can be accomplished?
One way would be to process them one at a time in a script loop, since one is a gif animation. Then you would use a null: separator and -layers composite. For example for one PNG.
Transparent PNG:
Animation:
magick logot.png null: \( glitter.gif -coalesce \) -gravity center -compose dstover -layers composite -layers optimize result1.gif
See https://legacy.imagemagick.org/Usage/anim_mods/#composite
Alternately, you can use -draw, but in the reverse with the png inside -draw and the GIF after magick.
magick glitter.gif -gravity center -draw 'image Over 0,0 0,0 "logot.png"' -layers optimize result2.gif

How can I specify a background in Imagemagick mogrify based on the colour of an existing pixel?

I want to use mogrify to set the background colour of a large number of images to be whatever colour is at a specific pixel, to make them square.
The vast majority have a single colour in the image background, or are photos in front of a single colour (so with only slight variations from shadows, etc.).
(The specific purpose in this case is to make the images all the same size and square for StyleGAN2-ADA training, so I want to avoid big "letterbox" rectangles where possible as it would be seen by the discriminator as relevant to the image, where a more faded-in background that approximately matches would be more likely to be ignored. Specifically, I have thousands of pictures of single dolls and action figures from various sources, some of which are "trimmed out" to have a truly solid colour background, others of which are against solid colour tables/walls/etc, for instance, from eBay images and such.)
Since they do not all have the same colour in the image background (the colour in the image, as opposed to the 'background colour' setting as per ImageMagick's jargon), I need to sample a pixel and set the background, but I can't figure out how. I tried things based on methods used to set the whole image to one colour, to no avail.
I have tried:
mogrify -verbose -resize 1024x1024 -gravity center -background 'p{10,10}' -extent 1024x1024 -resize 256x256 *.jpg
and
mogrify -verbose -resize 1024x1024 -gravity center -background "%[pixel:p{10,10}]" -extent 1024x1024 -resize 256x256 *.jpg
and neither works. I can't find any other possibilities in the documentation.
EDITED TO ADD: While testing various commands I came across a way to modify your original command to make it work on ImageMagick versions as far back as IMv6.8.
mogrify -resize 1024x1024 -set background "%[pixel:p{10,10}]" \
-gravity center -extent 1024x1024 -resize 256x256 *.jpg
The significant difference is setting the background color in an unusual way. Instead of the normal option -background <color>, this command uses -set background <color>. Then it behaves as expected using that +10+10 color as the background in the "mogrify" command.
For ImageMagick v7 use magick mogrify instead of just mogrify.
The following was my original answer. The suggestion for IMv6 "convert" may be quite useful for some workflows, but the answer above seems to be the simplest, most direct route.
PREVIOUS ANSWER:
ImageMagick v6 won't do that inline parsing of the color, but there are ways to get the same result, usually with IM's "convert" in a "for" loop in your shell. I don't know which shell you're using so I don't know how you'd write a "for" loop, but running this command inside the loop on each image should give you the results you described...
convert $image -resize 1024x1024 ( +clone -crop 1x1+10+10 ) +swap \
-resize 1024x1024 -gravity center -composite -resize 256x256 $image
That reads in the image, resizes it, makes a clone inside the parentheses, and extracts that pixel at +10+10. After the parentheses that single pixel get resized to a 1024x1024 square. Then setting the gravity to "center" and compositing the input image over that colored square gives you the result you described.

Preserving PNG transparency during a simple transformation in imagemagick

Task: i have an input png file (many actually, but i'll just loop the solution). It is 16x16 PNG, 32bit with partial transparency along edges.
It so happens that toolbar of a certain stupid platform requires 17x17 files. My problem is that imagemagick kills transparency when doing simple transformations.
So:
Sanity check:
convert add.png PNG32:add_COPIED.png
creates another 16x16#32bpp file. So far so good.
Transformation (gravity is fine):
convert add.png -extent 17x17 PNG32:add_17.png
creates a file with solid white background. That's not good.
What doesn't work:
I tried a serious number of combinations of transparent, transparent-color, background, alpha and flatten. Got nowhere.
What does work:
convert address_book.png -alpha Extract address_book_MASK.png
convert address_book.png -extent 17x17 PNG32:address_book_17.png
convert address_book_MASK.png -background black -extent 17x17 address_book_MASK17.png
composite -compose CopyOpacity address_book_MASK17.png address_book_17.png PNG32:address_book_FIN.png
While i have a working set of commands and I can get through the day, I honestly believe that this is the wrong way to do things - four commands that create 3 intermediate files that i need to delete later. Surely it can be done in a better way?
Set the background colour before changing the extent:
convert input.png -background none -extent WxH result.png

ImageMagick: Distort and Overlay

I have several pictures of a landscape.
Using the ImageMagick CLI on OSX, I would like to distort and overlay them properly.
I have looked for distortion coordinates between several of the pictures and a reference picture. I fail to understand the diference between -distort and +distort and how it plays with +repage. When I use -distort, the output has the desired offset but it's incomplete (it needs to be bigger). When I use +distort, I get the full image but it's missing the offset.
Reading the documentation I understand that I could do without the offset if I did the overlay composition in the same command before the offset information is lost but what's happening is that the distort is being applied to both the reference and the distorted images.
This is the result of using -distort:
This is the result of using +distort:
The offset of the -distort result would work once I apply it as an overlay (here using the composite in a separate command, but it's missing a big chunk of the picture.
When I tried to consolidate it in a single command this is the result I get:
This is the command I'm currently using:
convert base.jpg overlay.jpg
-matte -virtual-pixel transparent -distort Perspective '961,1695 1856,2461 2279,1520 3185,2303 3564,2173 4441,2970 1547,2817 2441,3594'
-compose blend -define compose:args=50,100 -composite result.jpg
I understand I could use parenthesis there but I fail to see where should I put them.
Thanks!
Update: this is the result of the overlay when using +distort either in two steps or in a single step as recommended by Mark.
The solution was to use -flatten instead of -composite.
convert base.jpg \( b.jpg -matte -virtual-pixel transparent +distort Perspective '961,1695 1856,2461 2279,1520 3185,2303 3564,2173 4441,2970 1547,2817 2441,3594' \) -compose blend -define compose:args=100,50 -flatten result.jpg
Turns out that -composite ignores the image offsets whereas -flatten works with layers and uses the offset information.
The suggestion came from this thread: http://www.imagemagick.org/discourse-server/viewtopic.php?t=20157
This is the documentation to flatten (link broken in the discussion above): http://www.imagemagick.org/Usage/layers/#flatten
Not sure I understand the issues, but would suggest you try this (untested):
convert base.jpg \
\( overlay.jpg -matte -virtual-pixel transparent -distort Perspective '961,1695 1856,2461 2279,1520 3185,2303 3564,2173 4441,2970 1547,2817 2441,3594' \) \
-define compose:args=50,100 -compose blend -composite result.jpg
That would mean that the perspective distortion is only applied to the overlay, not the base. So, in the code above, the first line only processes the base image, the second line only processes the overlay, and the final line blends the two.

ImageMagick: lay a partly transparent tile over an image

I have a wallpaper.jpg (size: 1920x1280) and a partly transparent tile.gif (size: 16x16).
On a website I want to have the tile as a x- and y-repeated overlay over the wallpaper.
Right now, this overlay is realized using CSS. I want to save one request and merge the (repeated) tile.png with the wallpaper.jpg using ImageMagick. The wallpaper.jpg is generated via ImageMagick anyway.
Following the Documentation of the -tile option, I came up with the following command:
convert wallpaper.jpg -size 1920x1280 tile:tile.gif -compose over -composite result.jpg
The result, however, is a 1920x1280 jpg filled with the tile, but no wallpaper shining through. Instead, the transparent part of the tile seem to be white.
The documentation says:
If the tile image is partially transparent then a 'Over' "-compose" method will need to be specified.
So what's wrong?
I also tried -flatten instead of -composite... same result.
edit:
I realize, there is also another -tile option documentation. It seems to follow the concept of overloading. Unfortunately, I cannot figure out how to use it correctly.
This should do the trick:
convert wallpaper.jpg -background none -size 1920x1280 tile:tile.gif -composite result.jpg
(you can also add -compose over, but that should not make any difference).
Not sure if it will help, but have you tried converting your tile.gif to a 24-bit PNG file with Alpha/Transparency? - Scratch that....
I found some example showing but am unsure about the full command line:
composite -tile tile.gif netscape: wallpaper.jpg
Source: http://www.imagemagick.org/Usage/compose/#tile

Resources