7

I'm looking for a way of converting an image so that all non-transparent pixels (those that have alpha != 1) into black and transparent pixels untouched (or converted to white). The closest I got was with the below imagemagick command:

convert <img> -colorspace Gray <out>

However this still gives me some gray colors instead of a complete black. I have tried all colorspace options and none does the job.

Any idea how I could achieve this with imagemagick or with similar tools (or with a PHP library if it exists)

CraigTeegarden
  • 8,173
  • 8
  • 38
  • 43
Max
  • 12,794
  • 30
  • 90
  • 142

3 Answers3

27

I know this question is old, but now I've stumbled on it I might as well answer it.

The ImageMagick command you want is:

convert <img> -alpha extract -threshold 0 -negate -transparent white <out>

I'll breakdown what it's doing as well.

  1. -alpha extract - Take the alpha mask of the image. Completely transparent pixels will be black, completely opaque ones white.
  2. -threshold 0 - Increase all channels to their maximum value if they are greater than zero. In this case, it will make every pixel white except the ones that are completely black.
  3. -negate - Invert the image. Now our blacks are white and our whites are black.
  4. -transparent white - Set white pixels to be transparent. This can be excluded if you'd prefer your originally transparent pixels to be white.

Before

PNG image with alpha channel

After

Previous image after running the convert command

Milan Babuškov
  • 59,775
  • 49
  • 126
  • 179
Alex Barrett
  • 16,175
  • 3
  • 52
  • 51
2

Well, you could do it with GD and a pair of loops:

$img = imagecreatefromstring(file_get_contents($imgFile));
$width = imagesx($img);
$hieght = imagesy($img);

$black = imagecolorallocate($img, 0, 0, 0);
$white = imagecolorallocate($img, 255, 255, 255);

for ($x = 0; $x < $width; $x++) {
    for ($y = 0; $y < $width; $y++) {
        $color = imagecolorat($img, $x, $y);
        $color = imagecolorforindex($color);
        if ($color['alpha'] == 1) {
            imagesetpixel($img, $x, $y, $black);
        } else {
            imagesetpixel($img, $x, $y, $white);
        }
    }
}

Or, you could replace colors (this may or may not work):

$img = imagecreatefromstring(file_get_contents($imgFile));
$maxcolors = imagecolorstotal($img);
for ($i = 1; $i <= $maxcolors; $i++) {
    $color = imagecolorforindex($i);
    if ($color['alpha'] == 1) {
        imagecolorset($img, $i, 0, 0, 0);
    } else {
        imagecolorset($img, $i, 255, 255, 255);
    }
}
ircmaxell
  • 163,128
  • 34
  • 264
  • 314
1

I'm not sure whether it'll help you (i.e. whether the methods presented will leave the transparent pixels alone) but check out the answers to this question: PHP/ImageMagic Get the “shadow” of an image

Community
  • 1
  • 1
Pekka
  • 442,112
  • 142
  • 972
  • 1,088