Создание оттенков серого с помощью библиотеки GD

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

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

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

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

  Интенсивность шкалы серого = 0.30R + 0.59G + 0.11B 

Как отметил nickf в своем комментарии , простая формула (pixel.r + pixel.g + pixel.b) / 3 . Используйте функцию imagefilter() -функции imagefilter() (не нужно итерации по всем пикселям изображения с использованием петель PHP):

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

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

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

Ответ от 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) ); } 

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

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

-ОБЪЯВЛЕНИЕ