Загрузка GIF с сохранением анимации!

Вариант 1 — Если вы не используете ватермарки и скругление углов


Все очень просто и легко + дайте кармы выложить это tips&trics

Открываем файл \engine\modules\image\Image.class.php

Бежим взглядом по коду до вот этого места (примерно строка 148) или ищем сверху по фразе «iWidthDest»
if ($iWidthDest) {
	if ($bForcedMinSize and ($iWidthDest>$oImage->get_image_params('width'))) {
	$iWidthDest=$oImage->get_image_params('width');
	}
	/**
	* Ресайзим и выводим результат в файл.
	* Если не задана новая высота, то применяем масштабирование.
	* Если нужно добавить Watermark, то запрещаем ручное управление alfa-каналом
	*/
	$oImage->resize($iWidthDest,$iHeightDest,(!$iHeightDest),(!$aParams['watermark_use']));


Теперь словами проговорим логику этого куска (там ниже в коде посмотрите что происходит и сразу все поймете):

— Если передана максимальная ширина картинки, то {сжимаем}

/* Стоп но ведь она передается всегда!, Зачем сжимать картинки постоянно? */ -> Изменяем условие, теперь оно звучит так:

— Если передана максимальная ширина картинки (посути, всегда true) И картинка больше максимального размера — тогда {сжимаем}, иначе {сохраняем как есть}


Сам процесс


Обращаем внимание только на первое условие
if ($iWidthDest) {


Правим условие чтобы оно выглядело вот так
if ( $iWidthDest && ( $iWidthDest < $oImage->get_image_params('width')) ) {


Вот и все — теперь она «херит» все действия если картинка меньше максимального размера. Перестает ставить ватермарки и скруглять углы (ибо иначе GIF пересобирется и все бесполезно.) — Подводные камни этого метода «rarjpeg» и прочие хитрости пользователей вплоть до уничтожения вашей системы через дырку в PHP (где-то писали уже про это на хабре), но это не сравнится с радостью при зарузке смишных картинок!)



P.S. Можно проверять не только максимальную_ширину, но и тип файла или даже определять анимированная это gif-ка или нет (на сайте php валяется пример) и т.д.

Вариант 2 — Идея futubra.com

— Можно загружать оригинальный GIF-файл (дописывать в конец имени что-то типа "_orig"), делать его копию и {сжимать} в нашем случае оставлять в нем только первый кадр, а при клике на файл подгружать оригинальное изображение на место этого, делать это можно через javascript напрмер
onClick="this.img.src='/file_orig.gif'"
Навеяно все это дело вот этим: futubra.com/posts/467325
У них походу, URL оригинальной картинки передается через alt, вот код:
<img src="http://storage.futubra.com/preview/184819/448x806.gif" alt="http://storage.futubra.com/source/184819.gif">

Обработчик пака не раскопал но думаю идея правильная с фоновой подгрузкой изображения и замещением src в превьюшке.

— Вот такая вот идея, и волки сыты и овцы целы


UPD1 — а теперь про аватарки

После внесения изменений в код, фрагмент кода выше, почему то перестали уменьшатся аватарки блогов, странно, но действительно так.
Тогда я пришел вот к такому алгоритму: поскольку функции RESIZE не передается никакого флага «аватарка это или нет», только требуемый размер, то я решил схитрить вот таким макаром:

— мы знаем до какого размера надо сжимать картики для постов (у меня это 700 пикс., тема social-jquery) обычно 635 пикс., но чтобы не гадать будем цеплять это значение прямо из конфига и проверять если картинку надо сжать до этого размера — значит эта картинка встаявляется в пост и надо дальше проверить ее — стоил ли ее сжимать вообще или нет, иначе (требуемый размер явно меньше, чем значение в конфиге) значит грузим что то другое -> принудительно сжимаем!

Вот сам код его надо вставить опять в то условие
// print_r(Config::Get('view.img_resize_width')); exit;

		//if ($iWidthDest) {

/* Суть такова, если картинка грузится явно не для поста
 (проверям размер картинки из конфига) или размер
 загружаемой картинки больше чем нужно - то сжимаем */

/*PATCH*/		if ( $iWidthDest < ($oImage->get_image_params('width')) || $iWidthDest < Config::Get('view.img_resize_width') ) {


P.S. Господа, я понимаю, что делаю что то некорректно — я не знаю всей механики этого скрипта и что и как работает, я тыкаюсь в конкретные проблемы и решаю их на месте, если есть какое-то более элегантное решение я только «за» — ткните меня туда носом и я успокоюсь.
Задача ясна — надо позволить пользователям загружать анимированные GIF картинки с достаточной долей безопасности для системы. (Просто с обычными картинками все понятно, они просто пересоздаются и все сторонние вложения в них отчиняются, оставется только исходное изображение, с анимашками сложнее — в них множество заголовков кадров, а при пересоздании берется только первый кадр, остальные теряются,.)

11 комментариев

avatar
Оооо, минусы — это хорошо, я люблю минусы! Кому что не нравится?
avatar
Подводные камни этого метода «rarjpeg» и прочие хитрости пользователей вплоть до уничтожения вашей 
системы через дырку в PHP (где-то писали уже про это на хабре), но это не сравнится с радостью при 
зарузке смишных картинок!)
Интересная концепция… пусть всю систему уничтожают, но радость от загрузки анимашек то какая:) Не согласен здесь я с вами. Может кто прояснить ситуацию в чем опасность загрузки анимированных gif картинок? Было бы идеально при загрузке фото отмечать чекбокс (грузить оригинал или стандартная обработка).
avatar
Ну это я так приукрасил) на самом деле
avatar
«в чем опасность загрузки анимированных gif картинок?» — в Гифках никаких опасностей, опасность в вирусах и шеллах которые маскируются под гифки. Если схватишь шелл то с твоим сайтом юные хацкеры смогут сделать всё что угодно, начиная с заражения всех файлов сайта вредоносным кодом и заканивая полным уничтожением проекта, спасет только восстановление из здорового бекапа.
avatar
UPD!
avatar
пупсик, пробовал проверять на условие?
oImage->get_image_params('format')=='gif'
avatar
заменил на if ( $iWidthDest && ( $iWidthDest < $oImage->get_image_params('width')) ) {

GIF по прежнему не анимированный.
avatar
Я бы до условия if ($iWidthDest) поставил проверку на тип файла (?gif); и если она положительна и get_image_params('width') <= $iWidthDest, то устанавливал-бы $iWidthDest в ноль.
Т.е. гифка грузить можно без изменения, если её ширина меньше или равна требуемой.
avatar
if ( $iWidthDest && $oImage->get_image_params('format') != 'gif' ) {
avatar
Подскажите пожалуйста как точно выглядит готовая строчка кода.
avatar
Есть предложение на тему Gif-ок, а что если сделать скрипт который загружал бы гифку на специальный сервер-картинок где нет вообще Ничего, тупо директория (папка) и прикрепленный к ней домен вида images.site.ru, а в топике автоматически создавалась бы ссылка вида
<img src="...>
с искомой гифкой?
То есть все картинки мы храним на одном сайте-хранилище где просто нет Ничего что мог бы заразить вирус, ни php ни каких других файлов, а основной сайт просто транслирует их (картинки) оттуда.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.