Моя миссия – создать небольшое приложение, в котором вы можете загрузить изображение, и приложение превратит его в искусство 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, чтобы получить разную интенсивность (оттенки) серого.
-ОБЪЯВЛЕНИЕ