The.Anti.9
The.Anti.9

Reputation: 44648

Making an Image Greyscale with GD Library

My mission is to create a little app where you can upload a picture, and the app will turn it into ASCII art. I'm sure these exist already but I want to prove that I can do it myself.

This would involve taking an image, making it greyscale and then matching each pixel with a character depending on how dark the picture is and how full the character is.

So my question is, Using the GD Library (or i guess some other means if necessary) how do I make an image black and white?

Upvotes: 4

Views: 9782

Answers (6)

Jive Dadson
Jive Dadson

Reputation: 17026

The answer from nickf, although quite common, is wrong. (Sorry, Nick.) For starters, those are the luminosity numbers for NTSC RGB, not sRGB, which is what computer images use. The right numbers are 0.21, 0.72, 0.07. Secondly, the weightings must be applied to the un-gamma-corrected RGB values, then the gamma correction re-applied. Gamma for sRGB is approximately, 2.2. Precisely, it is a composite function that approximates exponentiation by 1/2.2. Here it is in C++. (I do not speak php. Sorry, you'll need to translate.)

// sRGB luminance(Y) values
const double rY = 0.212655;
const double gY = 0.715158;
const double bY = 0.072187;

// Inverse of sRGB "gamma" function. (approx 2.2)
double inv_gam_sRGB(int ic) {
    double c = ic/255.0;
    if ( c <= 0.04045 )
        return c/12.92;
    else 
        return pow(((c+0.055)/(1.055)),2.4);
}

// sRGB "gamma" function (approx 2.2)
int gam_sRGB(double v) {
    if(v<=0.0031308)
        v *= 12.92;
    else 
        v = 1.055*pow(v,1.0/2.4)-0.055;
    return int(v*255+.5);
}

// GRAY VALUE
int gray(int r, int g, int b) {
    return gam_sRGB(
            rY*inv_gam_sRGB(r) +
            gY*inv_gam_sRGB(g) +
            bY*inv_gam_sRGB(b)
    );
}

Upvotes: 5

Mark Lalor
Mark Lalor

Reputation: 7887

To make it purely black and white (as you wrote) use this

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

Upvotes: 7

Stefan Gehrig
Stefan Gehrig

Reputation: 83622

As pointed out by nickf in his comment, the simple formula (pixel.r + pixel.g + pixel.b) / 3 is not correct. Use the GD-included function imagefilter() (no need to iterate over all pixels in an image using PHP loops) instead:

$im = imagecreatefrompng('dave.png');
imagefilter($im, IMG_FILTER_GRAYSCALE);
imagepng($im, 'dave.png');

Upvotes: 23

nickf
nickf

Reputation: 545995

A common formula to convert RGB to greyscale is:

Gray scale intensity = 0.30R + 0.59G + 0.11B

Upvotes: 3

goldenmean
goldenmean

Reputation: 18956

Typically in a RGB color space, value of 128 for each color component(RG and B) will give a medium gray. You might as well put any value lower or greater than 128 to get different intensities(shades) of gray.

-AD

Upvotes: 0

Austin Platt
Austin Platt

Reputation: 119

You don't have to convert it to grayscale... the result would be the same if you just calculated how close a pixel is to a certain colour (in your case a series of gray points), which you would have to have done anyway when comparing your grayscale image, and then chosing the appropriate character.

Upvotes: 1

Related Questions