Создание изображения в оттенках серого с помощью библиотеки GD - PullRequest
4 голосов
/ 10 ноября 2008

Моя миссия - создать небольшое приложение, в которое вы можете загрузить изображение, и приложение превратит его в ASCII-арт. Я уверен, что они уже существуют, но я хочу доказать, что могу сделать это сам.

Для этого потребуется сделать изображение, сделать его в оттенках серого, а затем сопоставить каждый пиксель с символом в зависимости от того, насколько темна картинка и насколько полон символ.

Итак, мой вопрос: используя библиотеку GD (или, я думаю, другие средства, если это необходимо), как сделать изображение черно-белым?

Ответы [ 6 ]

23 голосов
/ 10 ноября 2008

Как указал nickf в своем комментарии , простая формула (pixel.r + pixel.g + pixel.b) / 3 неверна. Вместо этого используйте включенную в GD функцию imagefilter() (нет необходимости перебирать все пиксели изображения с помощью циклов PHP):

$im = imagecreatefrompng('dave.png');
imagefilter($im, IMG_FILTER_GRAYSCALE);
imagepng($im, 'dave.png');
7 голосов
/ 24 августа 2010

Чтобы сделать его чисто черно-белым (как вы написали) используйте это

imagefilter($im, IMG_FILTER_GRAYSCALE);
imagefilter($im, IMG_FILTER_CONTRAST, -1000);
5 голосов
/ 24 августа 2010

Ответ от nickf, хотя и довольно распространенный, неправильный. (Извините, Ник.) Для начала это цифры яркости для NTSC RGB, а не sRGB, которые используются компьютерными изображениями. Правильные числа - 0,21, 0,72, 0,07. Во-вторых, весовые коэффициенты должны быть применены к значениям RGB без гамма-коррекции, затем гамма-коррекция применяется повторно. Гамма для sRGB составляет примерно 2,2. Точно, это составная функция, которая приближает возведение в степень на 1 / 2.2. Вот это в C ++. (Я не говорю на php. Извините, вам нужно будет перевести.)

// 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)
    );
}
2 голосов
/ 10 ноября 2008

Общая формула для преобразования RGB в оттенки серого:

Gray scale intensity = 0.30R + 0.59G + 0.11B
1 голос
/ 10 ноября 2008

Вам не нужно преобразовывать его в оттенки серого ... результат был бы таким же, если бы вы только вычислили, насколько пиксель близок к определенному цвету (в вашем случае это серия серых точек), которые вы бы имели в любом случае сделать это при сравнении изображения в градациях серого, а затем выбрать соответствующий символ.

0 голосов
/ 10 ноября 2008

Обычно в цветовом пространстве RGB значение 128 для каждого цветового компонента (RG и B) дает средний серый цвет. Вы можете также указать любое значение ниже или больше 128, чтобы получить различные интенсивности (оттенки) серого.

-AD

...