Вчера в топике «Модификация изображений для сайта, или какие бывают превьюшки» в комментариях diGreez предложил, как мне показалось, очень интересный способ организации превьюшек изображений. Реализовал на PHP функцию, которая занимается созданием таких превьюшек.
Функция документирована комментариями.
Пример использования:
Результат работы функции:
Update. Версия 2: Еще одна версия с другим алгоритмом. Для работы этой версии требуется функция pixelate, которая была найдена мной на просторах интернета, она позволяет пикселизовать изображение. Принцип работы второй версии следующий: находим средние значения цветов каждых 5 пикселей на границах изображения и «размазываем» эти цвета до края рамки. Затем для смягчения всё это заблюривается.
А вот результат работы второй версии:
Функция документирована комментариями.
Copy Source | Copy HTML<br/>// функция создаёт "миниатюру" изображения сохраняя пропорции<br/>// и обрамляет неиспользуемое пространство в стиле Philips Ambilight<br/>// Входные параметры:<br/>// $image_from - имя файла исходного изображения<br/>// $image_to - имя файла результирующего изображения<br/>// $width - желаемая ширина результирующей "миниатюры"<br/>// $height - желаемая высота результирующей "миниатюры"<br/>// $padding - минимальная рамка в пикселях (по умолчанию = 5)<br/>// $dest_image_type - тип изображения для сохранения (по умолчанию JPG):<br/>// 2 - JPG<br/>// 3 - PNG<br/>// Возвращает:<br/>// TRUE - в случае успеха<br/>// FALSE - в случае неудачи<br/>function aidsoid_resize_image($image_from, $image_to, $width=200, $height=200, $padding=5, $dest_image_type=2) {<br/> $image_vars = getimagesize($image_from);<br/> if (!$image_vars) {<br/> return FALSE;<br/> }<br/> $src_width = $image_vars[ 0];<br/> $src_height = $image_vars[1];<br/> $src_type = $image_vars[2];<br/> if (($src_type != IMAGETYPE_JPEG) and ($src_type != IMAGETYPE_PNG)) {<br/> return FALSE;<br/> }<br/> <br/> switch ($src_type) {<br/> case IMAGETYPE_JPEG:<br/> $src_image = imagecreatefromjpeg($image_from);<br/> break;<br/> case IMAGETYPE_PNG:<br/> $src_image = imagecreatefrompng($image_from);<br/> break;<br/> default:<br/> return FALSE;<br/> break;<br/> }<br/> if (!$src_image) return FALSE;<br/> <br/> // создаем задний фон для нового изображения<br/> $dest_image = imagecreatetruecolor($width, $height);<br/> <br/> // копируем из исходного изображения в фон и растягиваем без соблюдения пропорций<br/> $result = imagecopyresized($dest_image, $src_image, 0, 0, 0, 0, $width, $height, $src_width, $src_height);<br/> if (!$result) return FALSE;<br/> <br/> // применяем к фону размытие<br/> for ($i= 0; $i<=100; $i++) {<br/> $result = imagefilter($dest_image, IMG_FILTER_SMOOTH, 6);<br/> if (!$result) return FALSE;<br/> }<br/> <br/> // деление на ноль - плохая идея<br/> if ( ($src_width == 0) or ($src_height == 0) ) {<br/> return FALSE;<br/> }<br/> <br/> // вычисляем масштабный коэффициент<br/> $ratio = min( ($width-2*$padding)/$src_width , ($height-2*$padding)/$src_height );<br/> <br/> // вычисляем новые размеры изображения<br/> $new_width = $ratio * $src_width;<br/> $new_height = $ratio * $src_height;<br/> <br/> // если новая высота или новая длина больше оригинальных,<br/> // то это значит, что изображение будет растянуто, не нужно допускать этого,<br/> // в этом случае оставим оригинальное изображение без изменения размеров<br/> if ( ($new_width >= $src_width) or ($new_height >= $src_height) ) {<br/> $new_width = $src_width;<br/> $new_height = $src_height;<br/> }<br/> <br/> // скопируем поверх фона получившееся изображение<br/> $result = imagecopyresampled($dest_image, $src_image, round(($width-$new_width)/2), round(($height-$new_height)/2), 0, 0, $new_width, $new_height, $src_width, $src_height);<br/> if (!$result) return FALSE;<br/> <br/> // сохраняем на носитель<br/> switch ($dest_image_type) {<br/> case IMAGETYPE_JPEG: // качество изображения 100<br/> $result = imagejpeg($dest_image, $image_to, 100);<br/> break;<br/> case IMAGETYPE_PNG: // максимальный уровень сжатия 9<br/> $result = imagepng($dest_image, $image_to, 9);<br/> break;<br/> default:<br/> return FALSE;<br/> break;<br/> }<br/> if (!$result) return FALSE;<br/> chmod($image_to, 0777);<br/> <br/> return TRUE;<br/>} <br/>
Пример использования:
Copy Source | Copy HTML<br/>aidsoid_resize_image("image.jpg", "i/news/image-mini.jpg", 200, 200, 5, 2); <br/>
Результат работы функции:
Update. Версия 2: Еще одна версия с другим алгоритмом. Для работы этой версии требуется функция pixelate, которая была найдена мной на просторах интернета, она позволяет пикселизовать изображение. Принцип работы второй версии следующий: находим средние значения цветов каждых 5 пикселей на границах изображения и «размазываем» эти цвета до края рамки. Затем для смягчения всё это заблюривается.
Copy Source | Copy HTML<br/>function pixelate(&$image) {<br/> $imagex = imagesx($image);<br/> $imagey = imagesy($image);<br/> $blocksize = 5;<br/> <br/> for ($x = 0; $x < $imagex; $x += $blocksize) {<br/> for ($y = 0; $y < $imagey; $y += $blocksize) {<br/> // get the pixel colour at the top-left of the square<br/> $thiscol = imagecolorat($image, $x, $y);<br/> <br/> // set the new red, green, and blue values to 0<br/> $newr = 0;<br/> $newg = 0;<br/> $newb = 0;<br/> <br/> // create an empty array for the colours<br/> $colours = array();<br/> <br/> // cycle through each pixel in the block<br/> for ($k = $x; $k < $x + $blocksize; ++$k) {<br/> for ($l = $y; $l < $y + $blocksize; ++$l) {<br/> // if we are outside the valid bounds of the image, use a safe colour<br/> if ($k < 0) { $colours[] = $thiscol; continue; }<br/> if ($k >= $imagex) { $colours[] = $thiscol; continue; }<br/> if ($l < 0) { $colours[] = $thiscol; continue; }<br/> if ($l >= $imagey) { $colours[] = $thiscol; continue; }<br/> <br/> // if not outside the image bounds, get the colour at this pixel<br/> $colours[] = imagecolorat($image, $k, $l);<br/> }<br/> }<br/> <br/> // cycle through all the colours we can use for sampling<br/> foreach($colours as $colour) {<br/> // add their red, green, and blue values to our master numbers<br/> $newr += ($colour >> 16) & 0xFF;<br/> $newg += ($colour >> 8) & 0xFF;<br/> $newb += $colour & 0xFF;<br/> }<br/> <br/> // now divide the master numbers by the number of valid samples to get an average<br/> $numelements = count($colours);<br/> $newr /= $numelements;<br/> $newg /= $numelements;<br/> $newb /= $numelements;<br/> <br/> // and use the new numbers as our colour<br/> $newcol = imagecolorallocate($image, $newr, $newg, $newb);<br/> imagefilledrectangle($image, $x, $y, $x + $blocksize - 1, $y + $blocksize - 1, $newcol);<br/> }<br/> }<br/>}<br/> <br/>// функция создаёт "миниатюру" изображения сохраняя пропорции<br/>// и обрамляет неиспользуемое пространство в стиле Philips Ambilight<br/>// Входные параметры:<br/>// $image_from - имя файла исходного изображения<br/>// $image_to - имя файла результирующего изображения<br/>// $width - желаемая ширина результирующей "миниатюры"<br/>// $height - желаемая высота результирующей "миниатюры"<br/>// $padding - минимальная рамка в пикселях (по умолчанию = 5)<br/>// $dest_image_type - тип изображения для сохранения (по умолчанию JPG):<br/>// 2 - JPG<br/>// 3 - PNG<br/>// Возвращает:<br/>// TRUE - в случае успеха<br/>// FALSE - в случае неудачи<br/>function aidsoid_resize_image($image_from, $image_to, $width=200, $height=200, $padding=5, $dest_image_type=2) {<br/> $image_vars = getimagesize($image_from);<br/> if (!$image_vars) {<br/> return FALSE;<br/> }<br/> $src_width = $image_vars[ 0];<br/> $src_height = $image_vars[1];<br/> $src_type = $image_vars[2];<br/> // деление на ноль - плохая идея<br/> if ( ($src_width == 0) or ($src_height == 0) ) {<br/> return FALSE;<br/> }<br/> // проверяем тип файла<br/> if (($src_type != IMAGETYPE_JPEG) and ($src_type != IMAGETYPE_PNG)) {<br/> return FALSE;<br/> }<br/> <br/> switch ($src_type) {<br/> case IMAGETYPE_JPEG:<br/> $src_image = imagecreatefromjpeg($image_from);<br/> break;<br/> case IMAGETYPE_PNG:<br/> $src_image = imagecreatefrompng($image_from);<br/> break;<br/> default:<br/> return FALSE;<br/> break;<br/> }<br/> if (!$src_image) return FALSE;<br/> <br/> // создаем задний фон для нового изображения<br/> $dest_image = imagecreatetruecolor($width, $height);<br/> <br/> // копируем из исходного изображения в фон и растягиваем без соблюдения пропорций<br/> $result = imagecopyresized($dest_image, $src_image, 0, 0, 0, 0, $width, $height, $src_width, $src_height);<br/> if (!$result) return FALSE;<br/> <br/> // вычисляем масштабный коэффициент<br/> $ratio = min( ($width-2*$padding)/$src_width , ($height-2*$padding)/$src_height );<br/> <br/> // вычисляем новые размеры изображения<br/> $new_width = $ratio * $src_width;<br/> $new_height = $ratio * $src_height;<br/> <br/> // если новая высота или новая длина больше оригинальных,<br/> // то это значит, что изображение будет растянуто, не нужно допускать этого,<br/> // в этом случае оставим оригинальное изображение без изменения размеров<br/> if ( ($new_width >= $src_width) or ($new_height >= $src_height) ) {<br/> $new_width = $src_width;<br/> $new_height = $src_height;<br/> }<br/> <br/> // копируем из исходного изображения в фон с соблюдением пропорций<br/> $result = imagecopyresampled($dest_image, $src_image, round(($width-$new_width)/2), round(($height-$new_height)/2), 0, 0, $new_width, $new_height, $src_width, $src_height);<br/> if (!$result) return FALSE;<br/> <br/> // пикселизуем фон<br/> pixelate($dest_image);<br/> <br/> $tmp_x = round(($width-$new_width)/2);<br/> $tmp_y = round(($height-$new_height)/2);<br/> // размазываем вверх<br/> $result = imagecopyresized($dest_image, $dest_image, $tmp_x, 0, $tmp_x, $tmp_y, $new_width, $tmp_y, $new_width, 1);<br/> if (!$result) return FALSE;<br/> // размазываем вниз<br/> $result = imagecopyresized($dest_image, $dest_image, $tmp_x, $tmp_y+$new_height, $tmp_x, $tmp_y+$new_height-1, $new_width, $tmp_y, $new_width, 1);<br/> if (!$result) return FALSE;<br/> // размазываем влево<br/> $result = imagecopyresized($dest_image, $dest_image, 0, $tmp_y, $tmp_x, $tmp_y, $tmp_x, $new_height, 1, $new_height);<br/> if (!$result) return FALSE;<br/> // размазываем вправо<br/> $result = imagecopyresized($dest_image, $dest_image, $tmp_x+$new_width, $tmp_y, $tmp_x+$new_width-1, $tmp_y, $tmp_x, $new_height, 1, $new_height);<br/> if (!$result) return FALSE;<br/> <br/> // размываем фон<br/> for ($i= 0; $i<=50; $i++) {<br/> $result = imagefilter($dest_image, IMG_FILTER_SMOOTH, 6);<br/> if (!$result) return FALSE;<br/> }<br/> <br/> // скопируем поверх фона получившееся изображение<br/> $result = imagecopyresampled($dest_image, $src_image, round(($width-$new_width)/2), round(($height-$new_height)/2), 0, 0, $new_width, $new_height, $src_width, $src_height);<br/> if (!$result) return FALSE;<br/> <br/> // сохраняем на носитель<br/> switch ($dest_image_type) {<br/> case IMAGETYPE_JPEG: // качество изображения 100<br/> $result = imagejpeg($dest_image, $image_to, 100);<br/> break;<br/> case IMAGETYPE_PNG: // максимальный уровень сжатия 9<br/> $result = imagepng($dest_image, $image_to, 9);<br/> break;<br/> default:<br/> return FALSE;<br/> break;<br/> }<br/> if (!$result) return FALSE;<br/> chmod($image_to, 0777);<br/> <br/> return TRUE;<br/>} <br/>
А вот результат работы второй версии: