При копировании материалов, ссылка на источник ОБЯЗАТЕЛЬНА!!!

четверг, 11 октября 2012 г.

Колорируем фото при помощи php

Не так давно, взял за идею попробовать повторить урок колорированния фото как в уроке на сайте: http://www.photoshop-master.ru Но что самое интересное, решил я это сделать не в фотошопе, а с помощью PHP и библиотеки GD, которая предназначена для работы с изображениями.

Если разглядеть данный урок, то можно заметить, что все изменения фотографии придаются простыми режимами наложения. Так что теперь надо было бы найти алгоритмы этих самых режимов наложения. В уроке их используется четыре:
  1. Исключение (Exclusion)
  2. Перекрытие (Overlay)
  3. Мягкий свет (Soft Light)
  4. Жесткий свет (Hard Light)
Порыскав немного интернет, нашел алгоритмы к ним:

Исключение (Exclusion)

$color = 255-(((255-$bottom_color)*(255-$top_color)/255)+($bottom_color*$top_color/255));

Перекрытие (Overlay)

$color = $bottom_color<128?(2*$bottom_color*$top_color)/255:255-(2*(255-$bottom_color)*(255-$top_color)/255);

Мягкий свет (Soft Light)

$color = (255-2*$top_color)*pow(($bottom_color/255),2)+2*$top_color*($bottom_color/255);

Жесткий свет (Hard Light)

$color = $top_color<128?(2*$bottom_color*$top_color)/255:255-((2*(255-$bottom_color)*(255-$top_color))/255);

Здесь, $bottom_color – цвет пикселя, на который происходит наложение, а $top_color – цвет пикселя, который налаживается.

Но теперь возникла проблема придания изображению, которое налаживается, прозрачности. Здесь все решилось подбором другого цвета. Например, вместо цвета #0000ff, как в уроке, был использован цвет #1b007e, вместо #ffcc99 – #c1a991, вместо #000000 – #404040. Что из всего этого получилось можно увидеть ниже. А теперь перейдем непосредственно к самому коду (прикрепляю комментарии, чтобы было понятнее):
// 1. Получаем размеры загруженного изображения $uploadfile
$size = getimagesize($uploadfile);

// 2. Создаем новое изображение из нашего загруженного 
$source = imagecreatefromjpeg($uploadfile);

//3. Создаем изображение true color с шириной и высотой как у нашей оригинальной картинки 
$im = imagecreatetruecolor($size[0], $size[1]);

//4. Запускаем цикл с перебором каждого пикселя по ширине 
for ($x = 0; $x < $size[0]; $x++) {
 
 //5. Запускаем вложенный цикл с перебором каждого пикселя по высоте 
 for ($y = 0; $y < $size[1]; $y++) {
  
  //6. Получаем индекс цвета изображения-оригинала и переводим его в RGB 
  $colors = imagecolorsforindex($source, imagecolorat($source, $x, $y));
  
  //7. Присваиваем переменным значения каналов red, green и blue 
  $r = $colors['red'];
  $g = $colors['green'];
  $b = $colors['blue'];
  
  //8. Дублируем каналы. Это надо для финального шага, как в уроке фотошоп 
  $r_dub = $r;
  $g_dub = $g;
  $b_dub = $b;
  
  //9. Налаживаем цвет #1b007e (R=27 G=0 B=126) на пиксель с изображения-оригинала 
  //Режим наложения Исключение (Exclusion)
  //Присваиваем новые значения каналов red, green и blue переменным
  $r = ceil(255 - (((255 - $r) * (255 - 27) / 255) + ($r * 27 / 255)));
  $g = ceil(255 - (((255 - $g) * (255 - 0) / 255) + ($g * 0 / 255)));
  $b = ceil(255 - (((255 - $b) * (255 - 126) / 255) + ($b * 126 / 255)));

  //10. Налаживаем цвет #c1a991 (193, 169, 145), режим наложения Перекрытие (Overlay)
  if ($r <= 128) { $r = intval((2 * $r * 193) / 255); } 
  else { $r = intval(255 - ((2 * (255 - $r) * (255 - 193)) / 255)); }
  
  if ($g <= 128) { $g = intval((2 * $g * 169) / 255); }
  else { $g = intval(255 - ((2 * (255 - $g) * (255 - 169)) / 255)); }
  
  if ($b <= 128) { $b = intval((2 * $b * 145) / 255); }
  else { $b = intval(255 - ((2 * (255 - $b) * (255 - 145)) / 255)); }
  
  //11. Налаживаем цвет #404040 (64, 64, 64), режим наложения Мягкий свет (Soft Light)
  $r = intval((255 - 2 * 64) * pow(($r / 255),2) + 2 * 64 * ($r / 255));
  $g = intval((255 - 2 * 64) * pow(($g / 255),2) + 2 * 64 * ($g / 255));
  $b = intval((255 - 2 * 64) * pow(($b / 255),2) + 2 * 64 * ($b / 255)); 
  
  //12. Налаживаем пиксель изображения-оригинала на ранее обработанный пиксель
  //Режим наложения Жесткий свет (Hard Light)
  if ($r_dub < 128) { $r = intval((2 * $r * $r_dub) / 255); }
  else { $r = intval(255 - ((2 * (255 - $r) * (255 - $r_dub)) / 255)); }
  
  if ($g_dub < 128) { $g = intval((2 * $g * $g_dub) / 255); }
  else { $g = intval(255 - ((2 * (255 - $g) * (255 - $g_dub)) / 255)); }
  
  if ($b_dub < 128) { $b = intval((2 * $b * $b_dub) / 255); }
  else { $b = intval(255 - ((2 * (255 - $b) * (255 - $b_dub)) / 255)); }
  
  //13. Возвращаем идентификатор цвета для изображения из наших каналов
  $color = imagecolorallocate($im, $r,$g,$b);
  
  //14. Устанавливаем полученный цвет для нужного пикселя в изображении $im 
  imagesetpixel($im, $x, $y, $color);
 }
}

//15. Сохраняем полученное изображение $im в файл $uploadfile с качеством 100%
imagejpeg($im, $uploadfile, 100);

//16. Уничтожаем изображение $im 
imagedestroy($im);
Вот такой незамысловатый код. Возможно, он несет большую нагрузку, но писался исключительно в ознакомительных целях. И, в конце концов, посмотрим результат его выполнения:


Может не точно попал в цвет, но, согласитесь, очень похоже.

Комментариев нет:

Отправить комментарий