Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ImageMagick "color to alpha" (like The GIMP)

I'm trying to do what The GIMP does when selecting "color to alpha" with an actual colour.

I've got an image that has the color #a0132e in it, and I want that converted to transparency. Not only that exact colour, but any colour diverting from it, must become that much semi-transparent. That is what "color to alpha" does in GIMP.

I've tried a million different things, but I can't get my head around it. I've been frustrating myself for a couple of hours trying the -fx parameter and it's absolutely weird syntax, so that didn't help at all. Perhaps some of the options for convert will do the trick, but I haven't yet found the right thing to do, and really, I've tried all the things google got me.

Ideally I want to create a script that I can call like this:

color-to-alpha.cmd original.png output.png #a0132e

Or similar. How can I do this?

like image 316
Thany Avatar asked Oct 16 '14 15:10

Thany


People also ask

What is color to Alpha?

The Color to Alpha command makes transparent all pixels of the active layer that have a selected color. It attempts to preserve anti-aliasing information by using a partially intelligent algorithm that replaces weak color information with weak alpha information.

What is XC in ImageMagick?

Yes it is purely an alias for xc: which stood for "X window color", which came from the extreme early days of ImageMagick (long before my time).


1 Answers

1. Basics about ImageMagick command line parameters

First off: Please read also my answer "ImageMagick Command-Line Option Order (and Categories of Command-Line Parameters)". It explains a few basics about ImageMagick's command line structure. Specifically, it explains the major differences between:

  1. Image Settings
  2. Image Operators and
  3. Image Sequence Operators

These differences are a crucial concept to understand in order to be able to dissect complex ImageMagick command lines.

2. Basics about ImageMagick 'aside' processing

The suggested command is a rather advanced one. It uses parentheses to separate out two different sections of the complete command line.

Parenthesized command sections allow to process images "aside" the main command: It allows you to do some work on a separate image list, and then place the result of that separate processing to the end of the previous list. (You can use multiple, and even use nested parenthesized image processing operations within a single ImageMagick command line.) In a way, it serves as a scratch pad where you work on a subset of images and put the result back into the main image list.

Any opening of a pair of parentheses (" ( ") starts a new image list. All consecutive parameters inside the parentheses apply only to the new image list. The closing (" ) ") part of a respective parenthesis pair finalizes all 'aside' processing and places the resulting image list from the "aside" (this may consist of zero, one or multiple images) onto the main image list.

The only slight change I make to @dlemstra's original command: I escape the ( and ) occurrences with a backslash and replace these by \( and \). This is required so a shell like Bash will not try to mis-interpret these characters as indicating start and end of a sub-shell.

Important to note: when you use the ( and ) delimiters for aside processing, you MUST leave blanks around them -- otherwise they will not work!

3. Re-format the original command

First, I'll do some re-formatting to @dlemstra's originally proposed command. This does not change it's meaning, by and large. It only puts each setting and each operation on a line of its own.

(This applies for Mac OSX and Linux -- for Windows just replace all \ line continuation signs by ^.)

convert                        \
    original.png               \
    \(                         \
       -clone 0                \
       -fill "#a0132e"         \
       -colorize 100           \
    \)                         \
    \(                         \
       -clone 0,1              \
       -compose difference     \
       -composite              \
       -separate               \
       +channel                \
       -evaluate-sequence max  \
       -auto-level             \
    \)                         \
     -delete 1                 \
     -alpha off                \
     -compose over             \
     -compose copy_opacity     \
     -composite                \
    output.png

4. Now Dis-sect this monster command, line by line

  1. Line 1: convert
    This is the ImageMagick command to run.

  2. Line 2: original.png
    This is the first input image to process. At this moment in time, this is the only image in the main image list.

  3. Line 3: \(
    Open a new (empty) image list, to be processed "aside" from the main image list.

  4. Line 4: -clone 0
    "-clone" is an image stack operator. It asks to make a clone of that image from the last 'pushed' image sequence. The last image from the last pushed image sequence has index 0. In other words: put a copy of original.png into the current "aside" image list.

  5. Line 5: -fill "#a0132e"
    "-fill" is an image setting. It defines the fill color to use when filling a graphic primitive. "#a0132e" is a kind of red.

  6. Line 6: -colorize 100
    "-colorize" is an image operation. It colorizes the image, by the amount specified, (here: 100), using what color was specified by the most recent -fill setting. The result now is an image of the same size as original.png. This image has the uniform color "#a0132e". In other words: the newly created image is a reddish patch with the same size as original.png.

  7. Line 7: \)
    This closes the aside processing and puts the resulting image at the end of the main image list. Now there are 2 images in the main image list: first, original.png; second, the reddish, uniformly-colored one of the same size that was created in the "aside" process.

  8. Line 8: `(
    Open another new image list for another "aside" processing.

  9. Line 9: -clone 0,1
    "-clone" is (still :) an image stack operator. Here it asks to make a clone of each of the images with indexes 0 and 1. In other words: put a copy of original.png and a copy of the uniformly-colored "reddish" into the current "aside" list.

  10. Line 10: -compose difference
    "-compose" is an image setting. It defines the specific composite operator algorithm to be used later, in our case difference.

  11. Line 11: -composite
    "-composite" is an image sequence operator. It performs alpha composition on two images and an optional mask. After this operator was applied, there will be only 1 image left in the "aside" image sequence. This image is the result of composing the clone of original.png with the uniformly-colored "reddish" image, using the "difference" algorithm.

  12. Line 12: -separate
    "-separate" is another image sequence operator. It separates an image channel into a grayscale image. After this operator is finished, there will be a number of grayscale images left inside the "aside" image sequence. That number depends on the actual -channel setting that was active at the time of -separate was applied.

  13. Line 13: +channel
    "-channel" is an image setting. Normally it appears as -channel <type> to specify which channels should be used. (Examples: -channel Red for red, or -channel GB for green+blue, or -channel Alpha, or -channel CMY or -channel Cyan,Magenta,Yellow both for cyan+magenta+yellow). The special +-prefix with +channel means: reset the value back to its defaults. These defaults ...

  14. Line 14: -evaluate-sequence max
    "-evaluate-sequence" is an image sequence operator. It alters channel pixels by evaluating an arithmetic, relational, or logical expression over a sequence of images. In our case it sets "max". The "max" method gets the maximum (lighter) values values for each pixel from the sequence. As a result of this operator there will be one image left, where each position's pixel uses the lightest value after comparing the respective pixels of each of the images from the sequence.

  15. Line 15: -auto-level
    "-auto-level" is an image operator. It automagically adjusts color levels of an image.

  16. Line 16: \)
    This closes the aside processing. The resulting image of the aside processing is now placed into the main image list. The main image list currently consists of 3 images: original.png, the "reddish" image, plus the one created by the previous "aside" processing.

  17. Line 17: -delete 1
    "-delete" is an image sequence operator. It deletes images by index from an image sequence. Index 1 indicates the second image in the sequence (remember: indexing is 0-based). After this operator is finished, there will only be 2 out of the previous 3 images left in the current "aside" image sequence (because the second of the three images was deleted). If my count is correct so far, the deleted image should be the uniformly-colored "reddish" one produced by the first "aside" process. After that operation is done, 2 images will be left in the main image list.

  18. Line 18: -alpha off
    "-alpha" is an image setting. Here it switches off the alpha channel for the image(s). Note, this only disables the image's transparency channel. It does not delete or change the existing data. It just turns off the use of that data for subsequent processing. (If it changed existing data by itself, it would qualify as an image operator not an image setting.)

  19. Line 19: -compose over
    "-compose" is (still :) an image setting. It sets the algorithm to be used by a subsequent -composite image operator to "over". This algorithm composites the source over the destination. It is the default alpha blending compose method.

  20. Line 20: -compose copy_opacity
    "-compose" is (still :) an image setting. Here it sets the composite algorithm to "copy_opacity". Since it follows directly the -compose over setting, it invalidates this setting!

    In other words: you can as well skip the -compose over setting (line 19) from the complete command. That omission should make no difference to the end result.

  21. Line 21: -composite
    "-composite" is (still :) an image sequence operator. In our case this will apply the algorithm "copy_opacity" to the composited image. This copies the specified channel, opacity, from the source image to the same channel in the destination image.

  22. Line 22: output.png
    This line sets the name of the output image.

5. Visualize each step of command -- insert +write filename

In case you are not familiar with it, here is an additional hint.

You may insert

 +write output-destination

(almost) anywhere on the command line -- even multiple times. The write operator will then write out the currently loaded image (or the currently loaded image sequence) in its currently processed state to the given output destination.

This output destination can be a file, or show: or whatever else is valid for IM outputs. After writing to the output, processing of the original command will resume and continue.

Of course, it only makes sense to insert +write after the first (or any other) image (sequence) operator (not after any image settings) -- otherwise the current image list will not have changed.

Should there by multiple output images (because the current image list consists of more than one image), then ImageMagick will automatically assign index numbers to the respective filename.

This is a great trick! If you start using it for your own ImageMagick command development, you will soon find it indespensable. It helps enormously with debugging (or optimizing, streamlining, simplifying...) complex command setups.

6. Modified command line with appropriate +write filename

If you want 'visually enhanced' understanding about the above line-by-line explanation of image settings, image operations and image sequence operations, then run this modified command. Look at each of the images created by the +write commands, and compare them with the respective explanations in the 4th section of this answer:

convert                                 \    
    original.png                        \    
    \(                                  \    
       -clone 0                         \    
       -fill "#a0132e"                  \    
       -colorize 100                    \    
    \)                                  \    
    +write 0---after-aside1.png         \    
    \(                                  \    
       -clone 0,1                       \    
       +write 1---aside2-cloned.png     \    
       -compose difference              \    
       -composite                       \    
       +write 2---aside2-composite.png  \
       -separate                        \    
       +write 3---aside2-separate.png   \
       +channel                         \    
       -evaluate-sequence max           \    
       +write 4---aside2-evaluate.png   \
       -auto-level                      \    
       +write 5---aside2-autolevel.png  \   
    \)                                  \    
     +write 6---after-aside2.png        \    
     -delete 1                          \    
     +write 7---main-after-delete.png   \
     -alpha off                         \    
     -compose over                      \    
     -compose copy_opacity              \    
     -composite                         \    
     +write 8---main-composite.png      \    
    output.png

7. Original, intermediate and output images displaying below

Ok, meanwhile I've run the previous commands on an input image. The following picture shows it side by side with the original. Maybe the original.png which I picked for the test was not really suitable to test alongside the color '#a0132e'. But since @Thany didn't respond to @MarkSetchells comment asking for an example image, you'll have to live with my choice:

Original (left) and Output image (right)

Here are the results of the modified command which used the multiple +write additions to the original command line.

As is to be expected, original.png looks identical to its clone, as well as a few other cloned images do.

Multiple filenames with identical prefixes 1---, 2---,... result from the same +write command, which found multiple images to save in the currently loaded image list.

Original image (top left), intermediate processing results and output image (bottom right)

8. Excercise for the reader

Check, if my statement about Line 19 above being invalidated by Line 20 is correct. Remove -compose over from the command line and test if the result is still the same.


Update

This answer I wrote originally in order to explain in detail the command line @dlemstra has given. Dirk's answer is based on an ImageMagick script, color2alpha, which was written by Fred Weinhaus. I only now looked more closely at Fred's script:

  • http://www.fmwconcepts.com/imagemagick/color2alpha/index.php

Fred's script provides some additional and very nifty options:

  1. It can specify any color in the input image to be used as the base for creating the ramped alpha channel.
  2. It can specify another color to replace the alphacolor in the output.
  3. It implements a 'gain' control which lets influence the transition of white to black in the alpha channel.
like image 54
Kurt Pfeifle Avatar answered Sep 25 '22 10:09

Kurt Pfeifle