15

How does one go about converting an image to black and white in PHP?

Not just turning it into greyscale but every pixel made black or white?

RAS
  • 8,100
  • 16
  • 64
  • 86
AnnanFay
  • 9,573
  • 15
  • 63
  • 86

7 Answers7

28

Using the php gd library:

imagefilter($im, IMG_FILTER_GRAYSCALE);
imagefilter($im, IMG_FILTER_CONTRAST, -100);

Check the user comments in the link above for more examples.

Joel Wietelmann
  • 1,447
  • 1
  • 9
  • 16
12

Simply round the grayscale color to either black or white.

float gray = (r + g + b) / 3
if(gray > 0x7F) return 0xFF;
return 0x00;
Jasper Bekkers
  • 6,711
  • 32
  • 46
  • 4
    The green channel is perceived as brighter than the other two, a better equation for gray scale is: 0.299R + 0.587G + 0.114B – Null303 Oct 31 '08 at 20:16
  • We're rounding to pure black and pure white so those weights won't matter that much :-) – Jasper Bekkers Oct 31 '08 at 20:22
  • 1
    Jasper, it looks like they do indeed matter, because your conversion to either black or white is based on a threshold tested against the *gray* value. – Philipp Lenssen Apr 08 '12 at 23:41
  • All I'm saying is, the resulting image shouldn't be /that/ different. Obviously they will be different (and the added dot-product won't add much compute time). Anyway you put it, the weights are pretty much arbitrary. Anyway keep in mind that we're not really interested in the actual luminance value, just a black or white outcome. In which case this seems to simplest possible solution to the problem. Check this if you're interested (or would like to complicate this problem further); http://dcgi.felk.cvut.cz/home/cadikm/color_to_gray_evaluation/ – Jasper Bekkers Apr 12 '12 at 22:33
  • See https://en.wikipedia.org/wiki/Luma_(video)#Rec._601_luma_versus_Rec._709_luma_coefficients for a source on the coefficients for each color channel. PHP’s `imagefilter` with `IMG_FILTER_GRAYSCALE`, as suggested in another answer here, does that automatically, so that you don’t have to manipulate every single pixel yourself in PHP code. – caw Feb 21 '19 at 19:18
6

You could shell out to imagemagick, assuming your host supports it. What function do you want to use for deciding if a pixel should be black or white?

jonnii
  • 28,019
  • 8
  • 80
  • 108
2

If you intend to do this yourself, you will need to implement a dithering algorithm. But as @jonni says, using an existing tool would be much easier?

Community
  • 1
  • 1
toolkit
  • 49,809
  • 17
  • 109
  • 135
1
$rgb = imagecolorat($original, $x, $y);
        $r = ($rgb >> 16) & 0xFF;
        $g = ($rgb >> 8 ) & 0xFF;
        $b = $rgb & 0xFF;

        $gray = $r + $g + $b/3;
        if ($gray >0xFF) {$grey = 0xFFFFFF;}
        else { $grey=0x000000;}
KEL
  • 11
  • 1
1

This function work like a charm

    public function ImageToBlackAndWhite($im) {

    for ($x = imagesx($im); $x--;) {
        for ($y = imagesy($im); $y--;) {
            $rgb = imagecolorat($im, $x, $y);
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8 ) & 0xFF;
            $b = $rgb & 0xFF;
            $gray = ($r + $g + $b) / 3;
            if ($gray < 0xFF) {

                imagesetpixel($im, $x, $y, 0xFFFFFF);
            }else
                imagesetpixel($im, $x, $y, 0x000000);
        }
    }

    imagefilter($im, IMG_FILTER_NEGATE);

}
Amed
  • 191
  • 1
  • 4
0

For each pixel you must convert from color to greyscale - something like $grey = $red * 0.299 + $green * 0.587 + $blue * 0.114; (these are NTSC weighting factors; other similar weightings exist. This mimics the eye's varying responsiveness to different colors).

Then you need to decide on a cut-off value - generally half the maximum pixel value, but depending on the image you may prefer a higher value (make the image darker) or lower (make the image brighter).

Just comparing each pixel to the cut-off loses a lot of detail - ie large dark areas go completely black - so to retain more information, you can dither. Basically, start at the top left of the image: for each pixel add the error (the difference between the original value and final assigned value) for the pixels to the left and above before comparing to the cut-off value.

Be aware that doing this in PHP will be very slow - you would be much further ahead to find a library which provides this.

Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • 1
    Doing these things in PHP isn't *that* slow, I've done a complete image editing library in PHP with red-eye removal, blur filters, masks, blend filters et cetera and performance wasn't that bad. (Not enough for realtime usage, but definitely fast enough for most applications). – Jasper Bekkers Nov 01 '08 at 15:42