Комментарии 29
Наши предложения в комментариях:
$new_dir = null;
$dir_files = opendir($dir);
while(false !== ($file = readdir($dir_files)))
{
if($file != '.' && $file != '..')
$new_dir[] = $dir."/".$file;
}
->
$new_dir[] = glob("$dir/*");
Никогда так не делайте, ни на коленке, ни на станке с программным управлением:
$new_dir = null;
Если переменная содержит массив, то и должна быть инициализирована, как массив.
Заодно пропадет необходимость в лишнем условии if($new_dir)
Ну и разделить эту кучу-малу не помешало бы.
одна функция собирает в массив абсолютные пути ко всем файлам в дереве, а вторая накладывает водяной знак. И в аккуратном цикле вызывает вторую для результатов первой.
Если есть ещё, прямо кусочки кода которые стоит заменить, сообщите.
Я не претендую на идеальный продукт, но нужно учиться и стремиться к совершенству.
$new = str_replace("img","img2",$check); //Заменяем имя папки
У вас очевидно ни когда не было под папок с именами img* (например img123), так можно изображения потерять, так как они будут по пути img2*
compose over -quality 100 -geometry +x+y watermark_file src_file dst_file (где x & y позиция куда втыкать ватермарк)
будет в 100 раз быстрее.
Да и opendir/readdir тоже сомнительно.
$scanned_directory = array_diff(scandir($directory), array('..', '.'));
Решает все чтение папки одной строкой
За $scanned_directory = array_diff(scandir($directory), array('..', '.')); большое спасибо, в этом направлении я не думал…
Кусок кода для расчета позиции знака ровно посередине
// размеры картинки и водяного знака
// ( если размеры знака известны заранее, можно и не получать их вообще)
$imagesize = getimagesize($sourceFile);
$wmsize = getimagesize($watermarkfile);
// размеры картинки
$width = $imagesize[0];
$height = $imagesize[1];
// размеры знака
$w = $wmsize[0];
$h = $wmsize[1];
//центральная позиция
$x = $width/2 - $w/2;
$y = $height/2 - $h/2;
$command = '/usr/local/bin/composite -compose over -quality 93 -geometry +'.$x.'+'.$y.' '.$watermarkfile.' "'.$sourceFile.'" "'.$destinationFile.'"';
exec ($command,$out,$exitcode);
// проверка $exitcode уже кому как нравится
Скрипт обхода писать конечно придется. И целевые папки, если вам нужна копия тоже создавать придется. И, для качества, лучше не ресайзить марку, а накладывать разные готовые марки в зависимости от размера картинки.
А вообще в общем и целом — марки отлично накладываются при желании на лету в том же nginx. И хранить придется только оригиналы картинок
А вообще в общем и целом — марки отлично накладываются при желании на лету в том же nginx. И хранить придется только оригиналы картинок
Вопрос нагрузки, у клиента на странице открывается сразу 40 фотографий. И если все 40 будут на лету обрабатываться и ещё и клиентов будет 100 как бы наш дешевый сервак не упал.
Интересное решение у Eureka выше, это при запросе создавать файл и уже потом его хранить. Так работает движок OpenCart с кэшированием картинок.
Кусок кода для расчета позиции знака ровно посередине
Это просто шикарно, обязательно протестирую!
Вопрос нагрузки, у клиента на странице открывается сразу 40 фотографий. И если все 40 будут на лету обрабатываться и ещё и клиентов будет 100 как бы наш дешевый сервак не упал.
В nginx + resize умеет обработанное кешировать. На столько, на сколько скажете. Хотя обычно это применяется только для ресайза, генерации более мелких вариантов оригинальной картинки.
В следующем проекте, обязательно воспользуюсь этим.
А вот про SPL первый раз слышу… Я правильно понял что это: php.net/manual/ru/book.spl.php и как его можно применить?
cp -R img_cat1 img_cat2
for i in `ls *.jpg -R`
do
echo $i
composite -resize 800 -watermark 10.0 watermark.png $i $i
done
К чему танцы с бубном в гамаке?
Мы же старались создать решение для обычного или начинающего пользователя.
И как уже писали, скорее всего, в этом коде вы не учитываете что картинки будут разного размера, и watermark нужно менять.
Исходя из php что-то вроде:
exec('cp -R img_cat1 img_cat2');
Будет сильно предпочтительней этого:
$fileName = basename($check); //Определяем имя файла
$new = str_replace("img","img2",$check); //Заменяем имя папки
$put = substr($new,0,-strlen($fileName)); //Определяем путь до папки
if (!file_exists($put)) {
mkdir($put, 0777, true); //Если папки нет, то создаем
}
Совет: никогда не нужно прикрываться воображаемым "начинащим пользователем", ради которого все ваши старания :)
Во-первых, это никак не может объяснить плохой код.
Во-вторых, начинающему тоже надо когда-то начинать расти, и получать эти самые "специальные знания".
1) При добавлении новых изображений не придется прогонять ваш скрипт по новой, заставлять контент-менеджеров лепить на изображения водяные знаки (они сделают это криво) или писать отдельный скрипт, который делает это автоматически при загрузке каждого нового изображения.
2) Вы предлагаете, если я правильно понимаю, заменить старые изображения без водяных знаков на новые с ними. А старые, «пустые», забэкапить. И после не загружать на сервер изображения без водяного знака (как это у вас будет реализовано — не совсем понятно). А теперь представьте, что сменились требования к размещению или виду водяного знака. В результате вы получите бэкап с некоторой частью изображений без знаков + (возможно) некоторое количество изображений для которых нет копии без знака. И это станет куда большей головной болью, чем ваша изначальная задача.
И, кстати, бэкапы с «какая-то часть старых данных» теряются обычно в первую очередь.
Идея хранить исходные изображения без каких-либо водяных знаков и добавлять эти знаки уже только при выводе мне кажется более дальновидной.
Оригиналы Изображения хранятся в папке, и работа ведётся с ними, при добавлении новых картинок, стоит прогнать скрипт заново и перегегирировать все картинки.
При изменении требований к водяному знаку, так же можно внести коррективы в скрипт и прогнать. У нас на проекте в 10к картинок это занимает минуты 2.
Скрипт, выполняет задачу: добавить ко всем картинкам водяной знак, он ее выполняет. И требует минимальных временных затрат.
Да почитав комментарии, есть желание его улучшить, ускорить, добавить функций и вариантов.
Большое спасибо, за развитие идеи.
Идея прогонять скрипт каждый раз, да еще и по полной (если я все правильно понял) при появлении каждого нового изображения… Это может быть приемлемым решением, если у вас раз в полгода одно изображение добавляется. Но откуда тогда 10K изображений? Это ведет к:
- Появлению на некоторый срок на сайте изображений без водяных знаков: пока скрипт не доработает или если его забыли запустить
- Увеличению сложности обслуживания. Контент-менеджеры (мой личный опыт) вечно забывают делать дополнительные действия, если они не совсем очевидны.
- Уменьшение надежности всей системы. Ой-ей, храните бэкапы ваших «чистых» картинок. При таких массовых перезаписях однажды может случиться неприятный сюрприз
- Создание периодических пиков нагрузки в момент исполнения вашего скрипта
- Необходимость хранить два полных комплекта изображений одновременно: комплект с и комплект без водяных знаков.
- С ростом количества изображений все неприятные последствия выбранного вами решения будут расти: будет увеличиваться нагрузка на сервер, время обработки и т.д.
Поэтому я бы рекомендовал применить такой механизм (в общем виде, конкретная реализация зависит от того, какой у вас там стек):
- Создаем каталог для хранения кэша изображений. Т.е. изображений с водяными знаками
- При запросе изображения на выдачу выясняем есть ли уже готовое изображение в «кэше»
- Если есть — отдаем его. Если нет — обрабатываем изображение, сохраняем результат в кэш и отдаем пользователю
- Периодически чистим кэш. Самый простой вариант — удаляем раз в X минут/часов все файлы старше некоторого N. Но в идеале, наверное, стоит учитывать все-таки не время создания файла, а время последнего его использования. Не запрашивалось ни разу за последние X часов? Удаляем из кэша. Тут надо быть аккуратным, чтобы не сделать какую-нибудь ресурсозатратную жуть в качестве системы учета времени последнего использования.
Думаю, такой вариант решения задачи будет лучше выбранного вами по практически всем параметрам.
Это все делаеться в nginx — зачем городить в скрипте? Лишняя работа по обновлению, как было написано раньше.
Добавление водяного знака на все картинки сайта