tags:

views:

834

answers:

7

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?

+2  A: 

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.

Austin Platt
A: 

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

goldenmean
+3  A: 

A common formula to convert RGB to greyscale is:

Gray scale intensity = 0.30R + 0.59G + 0.11B
nickf
Common, yes; Correct? No. See my answer.
Jive Dadson
Why does this still have the green check-mark? It is not correct, as I explained in another answer. I posted code for the correct way to do it.
Jive Dadson
@Jive Perhaps this solution was good enough for him. It's certainly a lot less code.
nickf
+6  A: 

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');
Stefan Gehrig
A: 

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

imagefilter($im, IMG_FILTER_GRAYSCALE);
imagefilter($im, IMG_FILTER_CONTRAST, -1000);
Mark
+3  A: 

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);
    );
}
Jive Dadson