Redimensionner les images à la volée à l'aide de Nginx et LuaJIT (OpenResty)

Depuis un certain temps déjà, inspiré par l'article Redimensionnement de l'image à la volée le redimensionnement de l'image a été configuré à l'aide de ngx_http_image_filter_module et tout a fonctionné comme il se doit. Mais un problème est survenu lorsque le gestionnaire avait besoin de recevoir des images aux dimensions exactes pour les télécharger sur certains services, car... c'étaient leurs exigences techniques. Par exemple, si nous avons une image originale de taille 1200 × 1200, et lors du redimensionnement, nous écrivons quelque chose comme ?redimensionner=600×400, nous obtenons alors une image proportionnellement réduite le long du plus petit bord, taille 400 × 400. Il est également impossible d'obtenir une image avec une résolution supérieure (upscale). Ceux. ?redimensionner=1500×1500 renverra la même image 1200 × 1200

Cet article est venu à la rescousse OpenResty : transformer NGINX en un serveur d'applications à part entière comprendre comment Nginx fonctionne avec Lua et la bibliothèque elle-même pour Lua isage/lua-imagick - Liaisons Lua pure-c à ImageMagick. Pourquoi cette solution a-t-elle été choisie, et non, disons, quelque chose en python - parce qu'elle est rapide et pratique. Vous n'avez même pas besoin de créer de fichiers, tout se passe bien dans la configuration Nginx (facultatif).

Alors de quoi avons-nous besoin

Des exemples seront donnés basés sur Debian.

Installation de nginx et nginx-extras

apt-get update
apt-get install nginx-extras

Installation de LuaJIT

apt-get -y install lua5.1 luajit-5.1 libluajit-5.1-dev

Installation d'imagemagick

apt-get -y install imagemagick

et bibliothèques baguette magique à cela, dans mon cas pour la version 6

apt-cache search libmagickwand
apt-get -y install libmagickwand-6.q16-3 libmagickwand-6.q16-dev

Construire Lua-Imagick

Nous clonons le référentiel (ou prenons le zip et le décompressons)

cd ~
git clone https://github.com/isage/lua-imagick.git
cd lua-imagick
mkdir build
cd build
cmake ..
make
make install

Si tout s'est bien passé, vous pouvez configurer Nginx.

Je vais donner un exemple de configuration de l'hôte backend, qui, en fait, est responsable du redimensionnement. Il est mandaté par le serveur frontal, également avec Nginx, où la mise en cache se produit pendant une certaine période (jours) et d'autres choses.

configuration du backend nginx

# Backend image server
server {
    listen       8082;
    listen [::]:8082;
    set $files_root /var/www/example.lh/frontend/web;
    root $files_root;
    access_log off;
    expires 1d;

    location /files {
        # дефолтные значения ресайза
        set $w 700;
        set $h 700;
        set $q 89;

        #1-89 allowed
        if ($arg_q ~ "^([1-9]|[1-8][0-9])$") {
            set $q $arg_q;
        }

        if ($arg_resize ~ "([d-]+)x([d+!^]+)") {  
            set $w $1;
            set $h $2;
            rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
        }

        rewrite  ^(.*)$   /resize/$w/$h/$q$uri     last;
    }

    location ~* ^/resize/([d]+)/([d+!^]+)/([d]+)/files/(.+)$ {
        default_type 'text/plain';

        set $w $1;
        set $h $2;
        set $q $3;
        set $fname $4;

        # Есть возможность вынести весь Lua код в отдельный файл
        # content_by_lua_file /var/www/some.lua;
        # lua_code_cache off; #dev
        content_by_lua '
        local magick = require "imagick"
        local img = magick.open(ngx.var.files_root .. "/files/" .. ngx.var.fname)
        if not img then ngx.exit(ngx.HTTP_NOT_FOUND) end
        img:set_gravity(magick.gravity["CenterGravity"])

        if string.match(ngx.var.h, "%d+%+") then
            local h = string.gsub(ngx.var.h, "(%+)", "")
            resize = ngx.var.w .. "x" .. h
            -- для png с альфа каналом
            img:set_bg_color(img:has_alphachannel() and "none" or img:get_bg_color())
            img:smart_resize(resize)
            img:extent(ngx.var.w, h)
        else
                img:smart_resize(ngx.var.w .. "x" .. ngx.var.h)
        end

        if ngx.var.arg_q then img:set_quality(ngx.var.q) end

        ngx.say(img:blob())
        ';
    }
}

# Upstream
upstream imageserver {
    server localhost:8082;
}

server {
    listen 80;
    server_name examaple.lh;

    # отправляем все jpg и png картинки на imageserver
    location ~* ^/files/.+.(jpg|png) {
        proxy_buffers 8 2m;
        proxy_buffer_size 10m;
        proxy_busy_buffers_size 10m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_pass     http://imageserver;  # Backend image server
    }
}

Ce qui était nécessaire (agrandir l'image sur les bords) se produit en utilisant img:extent() et est défini à l'aide du paramètre resize signé + à la fin.

Les options suivantes sont disponibles :

  • LxH (Conserver le rapport hauteur/largeur, utiliser une dimension plus élevée)
  • LxH^ (Conserver le rapport hauteur/largeur, utiliser la dimension inférieure (recadrage))
  • LxH ! (Ignorer le rapport hauteur/largeur)
  • WxH+ (Conserver le rapport hauteur/largeur, ajouter des bordures latérales)

Tableau récapitulatif avec les résultats du redimensionnement

Demander le paramètre uri
Taille de l'image de sortie

?redimensionner=400×200
200 × 200

?redimensionner=400×200^
400 × 400

?redimensionner=400×200 !
400×200 (Non proportionnel)

?redimensionner=400×200+
400×200 (proportionnel)

Redimensionner les images à la volée à l'aide de Nginx et LuaJIT (OpenResty)

Total

Compte tenu de la puissance et de la simplicité de cette approche, vous pouvez implémenter des choses avec une logique assez complexe, par exemple ajouter des filigranes ou implémenter une autorisation avec un accès limité. Afin de connaître les capacités de l'API pour travailler avec des images, vous pouvez vous référer à la documentation de la bibliothèque isage/lua-imagick

Source: habr.com

Ajouter un commentaire