Redimensionnez les images à la volée avec Nginx et LuaJIT (OpenResty)

Il y a quelque temps, inspiré par un article Redimensionnement d'images à la volée la redimension des images a été configurée à l'aide de ngx_http_image_filter_module et tout fonctionnait comme prévu. Mais un problème est apparu lorsque le responsable a eu besoin d'obtenir des images avec des dimensions précises pour des téléchargements sur certains services, car c'étaient leurs exigences techniques. Par exemple, si nous avons l'original de l'image mesurant 1200×1200, et en redimensionnant, nous écrivons quelque chose comme ?resize=600×400, nous obtiendrons une image réduite proportionnellement par le côté le plus court, d'une taille de 400×400. Il est également impossible d'obtenir une image avec une résolution supérieure (upscale). En d'autres termes, ?resize=1500×1500 cela renverra la même image. 1200×1200

Un article est venu à la rescousse OpenResty : transformons NGINX en véritable serveur d'applications pour comprendre comment Nginx fonctionne avec Lua et la bibliothèque elle-même pour Lua isage/lua-imagick — liaisons pures en C de Lua à ImageMagick. Pourquoi une telle solution a-t-elle été choisie, plutôt qu'une autre en python, par exemple — parce que c'est rapide et pratique. Vous n'aurez même pas besoin de créer de fichiers, tout se fait directement dans la configuration de Nginx (ce n'est pas obligatoire).

Alors, de quoi avons-nous besoin ?

Les exemples seront 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 de imagemagick

apt-get -y install imagemagick

et des bibliothèques magickwand pour lui, dans mon cas pour la version 6

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

Compilation de lua-imagick

Clonons le dépôt (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é, il est possible de configurer Nginx.

Je vais donner un exemple de configuration du backend, qui, en fait, s'occupe du redimensionnement. Il est proxifié par le serveur frontal également avec Nginx, où le caching se déroule pour un certain temps (un jour) et d'autres choses.

nginx backend config

# 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 (l'extension de l'image sur les bords) se fait à l'aide de img:extent() et est défini grâce à un paramètre resize avec un signe + à la fin.

Les paramètres suivants sont disponibles :

  • WxH (Garder le rapport d'aspect, utiliser la dimension supérieure)
  • WxH^ (Garder le rapport d'aspect, utiliser la dimension inférieure (crop))
  • WxH! (Ignorer le rapport d'aspect)
  • WxH+ (Garder le rapport d'aspect, ajouter des bordures latérales)

Tableau récapitulatif des résultats de redimensionnement

Paramètre uri de la requête
Taille de l'image de sortie

?resize=400×200
200×200

?resize=400×200^
400×400

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

?resize=400×200+
400×200 (Proportionnel)

Redimensionnez les images à la volée avec Nginx et LuaJIT (OpenResty)

Conclusion

En tenant compte de toute la puissance et de la simplicité de cette approche, il est possible de réaliser des choses avec une logique assez complexe, comme ajouter des filigranes ou mettre en place une authentification avec des accès différenciés. Pour connaître les capacités de l'API pour travailler avec des images, vous pouvez consulter la documentation de la bibliothèque. isage/lua-imagick

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster