Русское сообщество fluxbb

Быстрый лёгкий надёжный форумный движок

Вы не вошли.

Объявление

Вы можете внести свой вклад в содержание сайта. Жертвователи попадут в почетную группу "Спонсоры". Поддержать сайт.

#1 2012-04-07 08:42:37

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 881
Сайт

Превьюшки от artoodetoo

Для портала мне захотелось сделать автоматическую генерацию превьюшек. Какой портал без картинок?!
Сколько уже было разных генераторов, сам писал чуть ли не для каждого проекта заново. Вот еще один:

  1. Главная особенность: превью создается в момент первого обращения по URL превьюшки.  Второе и все последующие обращения по URL будет обрабатывать уже Apache, теперь это статика.

  2. Размер и способ обрезания картинки задаются самим URL. Например /img/thumb/c100x100/12.jpg означает картинку 100 на 100 пикселей с обрезанием длинной стороны, а /img/thumb/240x240/12.jpg означает 240 на 240 без обрезания. Админу надо создать соответствующие папки и дать право на запись. Никакой другой  конфигурации не требуется.

  3. Если исходная картинка "битая" или слишком "тяжелая" для обработки, то на место превьюшки ляжет иконка "плохая картинка". Скрипт не будет пытаться заново прокачать это изображение, т.к. см. п.1

В рамках этого расширения никак не описывается способ загрузки исходных файлов на сервер. Права не проверяются. Все это пусть решается другими способами. Я просто ожидаю, что исходные картинки будут по адресу /upload/ и все.

Итак, поехали:
Во первых мы должны обнаружить факт отсутствия превьюшки. Кладем в корень форума файл
.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+) not_exists.php?alias=$1

на хостинге должен быть включен модуль mod_rewrite, обычно так оно и есть. Наш .htaccess перенаправит запросы к отсутствующим файлам на скрипт

not_exists.php

<?php

define('PUN_ROOT', dirname(__FILE__).'/');

function fileNotFound()
{
    header('HTTP/1.0 404 Not Found');
    die('File not found');
}

$uri = $_SERVER['REQUEST_URI'];
if (($p = strpos($uri, '?')) !== FALSE) {
    $query = substr($uri, $p);
    $uri = substr($uri, 0, $p);
} else {
    $query = '';
}

if (substr($uri, -1) == '/') {
    $uri .= 'index.html';
} elseif (substr($uri, -11) == '/index.html') {
    $uri = substr($uri, 0, -11);
    header("Location: {$uri}/{$query}");
    exit;
}

if (strrchr($uri, '.') === FALSE) {
    header("Location: {$uri}/{$query}");
    exit;
}

$prefixLength = strlen(dirname($_SERVER['SCRIPT_FILENAME'])) - strlen($_SERVER['DOCUMENT_ROOT']) + 2;
$uri = substr($uri, $prefixLength);
if (substr($uri, 0, 10) == 'img/thumb/')
    require PUN_ROOT .'include/user/thumb_url.php';
else
    require PUN_ROOT . 'include/user/page_url.php';

Как я уже написал, превьюшки мне понадобились для портала, поэтому скрипт делает некоторые проверки и преобразования с адресом для портальных нужд. В конце концов он подключает либо превьюшковый обработчик, либо страничковый )))
Нас сейчас интересует только превьюшковый.

include/user/thumb_url.php

<?php

if (!preg_match('#img/thumb/(?<crop>c)?(?<width>\d+)x(?<height>\d+)/(?<id>\d+)\.jpg$#', $uri, $matches)) 
    fileNotFound();
extract($matches);

$src = "upload/{$id}.jpg";
$dst = "img/thumb/{$crop}{$width}x{$height}/{$id}.jpg";

if (!file_exists(PUN_ROOT.$dst)) {
    if (!is_dir(dirname($dst)))
        fileNotFound();
    set_time_limit(120);
    copy(PUN_ROOT.'img/thumb/wrong.jpg', PUN_ROOT.$dst);
    makeThumbnail(PUN_ROOT.$src, PUN_ROOT.$dst, intval($width), intval($height), !empty($crop));
}

header('Content-Type: image/jpeg'); 
readfile(PUN_ROOT.$dst);
exit();


function makeThumbnail($srcFile, $dstFile, $thumbWidth, $thumbHeight, $crop = FALSE)
{
    $rgb = 0xFFFFFF;
    $quality = 80;
    $size = @getimagesize($srcFile);
    $offsetX = $offsetY = 0;

    if ($size === FALSE) return FALSE;

    $format = strtolower(substr($size['mime'], strpos($size['mime'], '/') + 1));
    $icfunc = 'imagecreatefrom' . $format;
    if (!function_exists($icfunc)) return FALSE;

    $origImg = $icfunc($srcFile);
    if (($size[0] <= $thumbWidth) && ($size[1] <= $thumbHeight)) {
        // use original size
        $width  = $size[0];
        $height = $size[1];
    } else {
        $width  = $thumbWidth;
        $height = $thumbHeight;

        // calculate fit ratio
        $ratioX = $size[0] / $thumbWidth;
        $ratioY = $size[1] / $thumbHeight;

        if ($ratioX < $ratioY) {
            if ($crop) {
                $offsetY = ($size[1] - $thumbHeight * $ratioX) / 2;
                $size[1] = $thumbHeight * $ratioX;
            } else {
                $width  = $size[0] / $ratioY;
                $height = $thumbHeight;
            }
        } else {
            if ($crop) {
                $offsetX = ($size[0] - $thumbWidth * $ratioY) / 2;
                $size[0] = $thumbWidth * $ratioY;
            } else {
                $width  = $thumbWidth;
                $height = $size[1] / $ratioX;
            }
        }
    }

    $thumImg = imagecreatetruecolor($width, $height);
    imagefill($thumImg, 0, 0, $rgb);
    imagecopyresampled($thumImg, $origImg, 0, 0, $offsetX, $offsetY, $width, $height, $size[0], $size[1]);

    imagejpeg($thumImg, $dstFile, $quality);
    imagedestroy($origImg);
    imagedestroy($thumImg);

    return TRUE;
}

Надеюсь по тексту все понятно. Если нет — спрашивайте.

img/thumb/wrong.jpg — это иконка "плохая картинка". Она появляется, если генератор превью обломался создавать превью. Нарисуйте картинку сами и положите на хостинг. Также вам понадобится создать сколько надо под-папок в img/thumb/ с именами вида
#x# и/или
с#x#
где "#" - число — длина в пискселях. "c" означает "crop" — обрезать что не влезло в заданный прямоугольник. Без обрезания картинка подгоняется по размеру поменьше так, чтобы вписаться полностью.
Необходимо дать права на запись в эти папки!


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

#2 2012-04-07 09:12:02

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 881
Сайт

Re: Превьюшки от artoodetoo

Тестовый прогон:

исходная картинка upload/11.jpg
38812385.png

img/thumb/240x240/11.jpg
11240x240.jpg

img/thumb/100x100/11.jpg
11100x100.jpg

img/thumb/c100x100/11.jpg
11c100x100.jpg


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

#3 2012-04-07 14:16:26

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,203
Сайт

Re: Превьюшки от artoodetoo

Думаю, что можно классную нагрузку на сервер создать с помощью gd перебирая размеры превьюшек wink

Offline

#4 2012-04-08 06:52:33

artoodetoo
Admin by chance
Зарегистрирован: 2008-09-09
Сообщений: 881
Сайт

Re: Превьюшки от artoodetoo

это как раз учтено: они создаются один раз и только для существующих папок-размеров
когда сервер отдает готовую картинку это не особо большая нагрузка. особенно если сайт стоит за прокси типа nginx


There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors.

Offline

#5 2012-04-08 07:17:19

Visman
Administrator
Из Сибирь
Зарегистрирован: 2009-06-08
Сообщений: 2,203
Сайт

Re: Превьюшки от artoodetoo

@artoodetoo, ясно. Я просмотрел, что он папки размеров проверяет, а не создает сам.

Offline

Подвал доски

Под управлением FluxBB. Хостинг Hostens