imagemagickimagemagick-convertmogrify

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.


Solution

  • 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.