skip to Main Content

I am looking for help on how to adjust the color channel levels of a black and white (or grayscale) image. In photoshop this feature is called the Black and White filter.

The examples below demonstrate my process. The red shirt (which is a perfect mid-gray) is black in the final image.

Original Image
enter image description here

Changed Hue to Green
enter image description here

Final Image Now Black and White (with mid-gray/red shirt black)
enter image description here

2

Answers


  1. With Imagemagick, you would use the -level operator to adjust the black & white end points, which in turn, can be applied to a specific color channel.

    Example:

     convert source.png -level 45%,80% out.png
    

    With PHP’s Imagick library, you would use the Imagick::levelImage method.

    $img = new Imagick('source.png');
    $quantum = $img->getQuantumRange()['quantumRangeLong'];
    $img->levelImage(0.45 * $quantum, 1.0, 0.80 * $quantum, Imagick::CHANNEL_ALL);
    

    Update

    To generate the intermediate image (green shirt), you would use the “red -> green” hue modulation with -modulate. Examples in Hue Modulation docs.

    convert source.jpg -modulate 100,100,166.6 green.png
    // or in PHP
    Imagick::modulateImage ( float $brightness , float $saturation , float $hue )
    

    Red to Green modulate

    Now for swapping the color for black, simply use -fuzz and -opaque. But honestly, all the green hues remind me of Chroma Key which is defined as…

    chroma key

    Once you have a mask isolated, it pretty simple to swap colors, backgrounds, or more complex images.

    convert green.png -fx '1 * b - 1 * g + 1' mask.png
    

    shirt mask

    The main benefit of the mask approach is that the color details (shadows, highlights, & lines) will be preserved in the final image. Pulling this all together in PHP:

    $img = new Imagick("source.jpg");
    $org = clone $img; // Copy source for final composite
    $img->modulateImage(100,100,166.6); // Convert hues from red to green
    /*
     Apply fx operations. Remember: K0, K1, & K2 are constants
     that need to be adjusted to match the chroma-key that you
     want to knockout.
     */
    $mask = $img->fxImage('1.35 * b - 0.95 * g + 1');
    // Copy the mask as the new alpha channel
    $org->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0, Imagick::CHANNEL_ALPHA);
    

    original image with alpha mask applied

    For populating the shirt with black 80% (or gray 20%). Compose the new image over a color-only image, and drop to grayscale.

    $fin = new Imagick();
    $fin->setSize($org->width, $org->height);
    $fin->readImage("xc:gray20");
    $fin->compositeImage($org, Imagick::COMPOSITE_DEFAULT, 0, 0);
    $fin->setImageColorspace(Imagick::COLORSPACE_GRAY);
    $fin->writeImage('fin.jpg');
    

    Black 80% with highlights

    Here’s example with populating the shirt with a pattern.

    $pattern = new Imagick();
    $pattern->setSize($org->width, $org->height);
    $pattern->readImage("pattern:VERTICALSAW");
    $pattern->negateImage(false);
    $pattern->compositeImage($org, Imagick::COMPOSITE_DEFAULT, 0, 0);
    $pattern->setImageColorspace(Imagick::COLORSPACE_GRAY);
    $pattern->writeImage('pattern.jpg');
    

    Pattern Example

    Again, this is ideal if you want to preserve details. If you want to do a full knockout (eg. all green to black 80%), just use -fill, -opaque & -fuzz.

    Example:

    convert green.png  -fill gray20 -fuzz 30% -opaque hsl(33%,100%,50%) black80.png
    convert black80.png -colorspace Gray bw_shirt.png
    

    final shirt

    Login or Signup to reply.
  2. Is it this command you are looking for?

    convert                              
      http://i.stack.imgur.com/QW5M0.jpg 
     -colorspace gray                    
      b+w.jpg
    

    Result (original red shirt on the left, black+white image on the right):

      

    Or is it that you want the different red shades from the original to become (almost) pure black? — In this case add some -gamma adjustment, maybe:

    convert                              
      http://i.stack.imgur.com/QW5M0.jpg 
     -colorspace gray                    
     -level 0%,100%,0.5                  
      b+w-2.jpg
    

    or

    convert                              
      http://i.stack.imgur.com/QW5M0.jpg 
     -colorspace gray                    
     -level 0%,80%,0.5                   
      b+w-3.jpg
    

    Here are the two resulting images:

      

    Of course you can play a bit more with the exact parameters I used here…

    Update

    The following commands change the color level for the red channel first, then converts this intermediate result to grayscale:

    convert              
       red---QW5M0.jpg   
      -channel R         
      -level 0%,40%      
      -colorspace gray   
      -level 0%,100%,0.5 
       b+w-4.jpg
    

    or

    convert              
       red---QW5M0.jpg   
      -channel R         
      -level 0%,80%      
      -colorspace gray   
      -level 0%,100%,0.5 
       b+w-5.jpg
    

      

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search