Аватары без искажений
Уже поднималась тема про искажения в аватарах, возникающие, если исходная картинка не квадратная. Что-то мне это сильно не нравилось, и решил я это исправить.
Ниже даю решение, как создавать квадратные аватары из неквадратных картинок.
«Оквадрачивание» возможно по одному из трех алгоритмов (на выбор):
1) Пропорциональное уменьшение картинки по бОльшей стороне и вписывание ее квадрат. На выходе имеем квадратную аватару, но само изображение уменьшается пропорционально и не искажается.
2) Пропорциональное уменьшение по максимальной стороне.
3) Пропорциональное уменьшение по минимальной стороне.
4) Уменьшение с обрезкой: сначала выполняется п.2, а потом выполняется обрезка: если W>H, то обрезка по бокам, если W<H, то обрезка снизу.
Теперь сам код. Чтобы не ломать файл с системными функциями, создаем в папке include свой файл, в котором прописываем такую функцию:
В файле ActionSettings.class.php в методе protected function EventProfile() вызовы функций func_img_resize при загрузке аватар меняем на func_img_avatar.
Все!
UPD Внимание! Уже залитые аватары никуда не денутся и автоматически не изменятся! Их можно исправить только повторной заливкой!
Ниже даю решение, как создавать квадратные аватары из неквадратных картинок.
«Оквадрачивание» возможно по одному из трех алгоритмов (на выбор):
1) Пропорциональное уменьшение картинки по бОльшей стороне и вписывание ее квадрат. На выходе имеем квадратную аватару, но само изображение уменьшается пропорционально и не искажается.
2) Пропорциональное уменьшение по максимальной стороне.
3) Пропорциональное уменьшение по минимальной стороне.
4) Уменьшение с обрезкой: сначала выполняется п.2, а потом выполняется обрезка: если W>H, то обрезка по бокам, если W<H, то обрезка снизу.
Теперь сам код. Чтобы не ломать файл с системными функциями, создаем в папке include свой файл, в котором прописываем такую функцию:
<?php
define('IMG_RESIZE_FIT', 0); // вписывание в квадрат (уменьшение по максимальной стороне)
define('IMG_RESIZE_MAX', 1); // уменьшение по максимальной стороне
define('IMG_RESIZE_MIN', 2); // уменьшение по минимальной стороне
define('IMG_RESIZE_CROP', 3); // обрезка исходной картинки:
// если W>H, то обрезка по бокам, если W<H, то снизу
function func_img_avatar($sFileSrc, $sDirDest, $sFileDest, $iWidthMax, $iHeightMax,
$iWidthDest=null, $iHeightDest=null, $iResizeMode=0) {
if (!($aSize=getimagesize($sFileSrc))) {
return false;
}
$img_src=false;
switch ($aSize['mime']) {
case 'image/png':
$img_src=imagecreatefrompng($sFileSrc);
$sFileDest.='.png';
break;
case 'image/gif':
$img_src=imagecreatefromgif($sFileSrc);
$sFileDest.='.gif';
break;
case 'image/jpeg':
$img_src=imagecreatefromjpeg($sFileSrc);
$sFileDest.='.jpg';
break;
default:
return false;
break;
}
if (!$img_src) {
return false;
}
if (($aSize[0]>$iWidthMax) or ($aSize[1]>$iHeightMax)) {
return false;
}
if ($iWidthDest) {$iScaleW=$iWidthDest/$aSize[0];} else {$iScaleW=1;}
if ($iHeightDest) {$iScaleH=$iHeightDest/$aSize[1];} else {$iScaleH=1;}
if ($iResizeMode==IMG_RESIZE_MAX) {
$iSizeRelation=(($iScaleW<$iScaleH)?$iScaleW:$iScaleH);
$iWidthNew=round($aSize[0]*$iSizeRelation);
$iHeightNew=round($aSize[1]*$iSizeRelation);
$iSizeW=$iWidthNew;
$iSizeH=$iHeightNew;
$iDestX=0;
$iDestY=0;
} elseif ($iResizeMode==IMG_RESIZE_MIN) {
$iSizeRelation=(($iScaleW>$iScaleH)?$iScaleW:$iScaleH);
$iWidthNew=round($aSize[0]*$iSizeRelation);
$iHeightNew=round($aSize[1]*$iSizeRelation);
$iSizeW=$iWidthNew;
$iSizeH=$iHeightNew;
$iDestX=0;
$iDestY=0;
} elseif ($iResizeMode==IMG_RESIZE_CROP) {
$iSizeRelation=(($iScaleW>$iScaleH)?$iScaleW:$iScaleH);
$iWidthNew=round($aSize[0]*$iSizeRelation);
$iHeightNew=round($aSize[1]*$iSizeRelation);
$iSizeH=$iSizeW=(($iWidthNew<$iHeightNew)?$iWidthNew:$iHeightNew);
$iDestX=round(($iSizeW-$iWidthNew)/2);
$iDestY=0;
} else {
$iSizeRelation=(($iScaleW<$iScaleH)?$iScaleW:$iScaleH);
$iWidthNew=round($aSize[0]*$iSizeRelation);
$iHeightNew=round($aSize[1]*$iSizeRelation);
$iSizeH=$iSizeW=(($iWidthNew>$iHeightNew)?$iWidthNew:$iHeightNew);
$iDestX=round(($iSizeW-$iWidthNew)/2);
$iDestY=round(($iSizeH-$iHeightNew)/2);
}
$sFileFullPath=DIR_SERVER_ROOT.'/'.$sDirDest.'/'.$sFileDest;
@func_mkdir(DIR_SERVER_ROOT,$sDirDest);
if ($iWidthDest and $iWidthDest!=$aSize[0]) {
$img_dest=imagecreatetruecolor($iSizeW,$iSizeH);
imagesavealpha($img_dest,true);
imagealphablending($img_dest,false);
if (imagecopyresampled($img_dest, $img_src, $iDestX, $iDestY, 0, 0,
$iWidthNew, $iHeightNew, $aSize[0], $aSize[1])) {
imagedestroy($img_src);
switch ($aSize['mime']) {
case 'image/png':
if (imagepng($img_dest,$sFileFullPath)) {
chmod($sFileFullPath,0666);
}
break;
case 'image/gif':
if (imagegif($img_dest,$sFileFullPath)) {
chmod($sFileFullPath,0666);
}
break;
case 'image/jpeg':
if (imagejpeg($img_dest,$sFileFullPath)) {
chmod($sFileFullPath,0666);
}
break;
}
imagedestroy($img_dest);
return $sFileDest;
}
} else {
if (copy($sFileSrc,$sFileFullPath)) {
return $sFileDest;
}
}
return false;
}
?>
В файле ActionSettings.class.php в методе protected function EventProfile() вызовы функций func_img_resize при загрузке аватар меняем на func_img_avatar.
Все!
UPD Внимание! Уже залитые аватары никуда не денутся и автоматически не изменятся! Их можно исправить только повторной заливкой!
44 комментария
Подскажите пожалуйста работает ли эта метода для 0.31 версии?
решал ли кто-либо вопрос с аватарами, поблема в том, что при масштабировании картинки дико искажаются.
речь идет про работу с неквадратными картинками, я же говорю про кривое масштабирвание и квадратных аватаров тоже
Они делаются неквадратными?
Карму уже когда-то плюсовал — больше не могу.
Этот топик надо в Tips&Tricks :-)
Еще рах кратко порядок действий:
1. В папке include создаем файл, скажем, my_function.php с функцией func_img_avatar, которая описана выше.
2. В файле ActionSettings.class.php в методе protected function EventProfile() вызовы функций func_img_resize меняем на func_img_avatar.
Больше ничего настраивать не надо, все должно работать
Что не так делаю? Спасибо!
avadim, может быть проще исправить пост, чтобы не было таких вопросов? Сразу указать что нужно вставить в новый файл и все — новичкам будет проще :)
Вот теперь кусок кода, как есть, можно вставлять в файл
залил аватарку формата *.gif (не анимация) на локалхост — получил чёрные полоски справа и слева :(, первоначальный размер аватары был 82х100
С наилучшими пожеланиями
Играешь с последним параметром $iResizeMode. Можно прямо в описание функции воткнуть, напр., так:
Будет пропорциональное уменьшение по максимальной стороне.
спасибо, фокусник :)
Поэтому и возник такой вопрос.
Сейчас почти нет времени расписать нормально, НО!
Рассмотрим все 4 варианта уменьшения изображений:
1. после ресайза она станет квадратной, да только с черными полосами по бокам (если начальное изображение было не квадратным)
2,3. изображение уменьшается, но не становится квадратным — все аватары будут разными по ширине.
4. из всего загруженного изображения вырезается средняя часть размера 100 на 100 и потом она ресайзится.
На данный момент лучший вариант — п.4 — получается квадрат без каких либо черных полос по-бокам. Но!
п.4. так же не до конца верен, потому как если взять картинку 200х600, на который я в полный рост, то после ресайза на аватаре будет область промежности, что конечно удручает.
Есть выход! Какой?
п.4 — самый приемлемый
Я код не разбирал, но на деле получилась не средняя облвсть, а кроп сверху:
1) Ресайз по ширине до 100px,
2) Кроп сверху вниз на 100px.
Там обычно лицо.
Автору спасибо.
мне кажется там рес до 100, а потом вырез середины, а не сверху.
автору, бесспорно, спасибо
Ответ прост и банален — верстка практически всех шаблонов предусматривает квадратные аватары. А писать софт, который будет автоматом распознавать на фотке лицо и именно его вырезать для аватары, это отдельная задача для системы программного распознавания образов. :)
Почему у меня высокие картинки ресайзятся до 100*100 (метод IMG_RESIZE_CROP), а широкие до 67*67?
Входными параметрами я говорю сделать рес. до 100*100 в любом случае.
livestreet.ru/blog/16608.html