Ridimensionamento delle immagini al volo con Nginx e LuaJIT (OpenResty)

È passato un po' di tempo, ispirato da un articolo Ridimensionamento delle immagini al volo è stato configurato il ridimensionamento delle immagini utilizzando ngx_http_image_filter_module e tutto funzionava come previsto. Ma è emerso un problema, quando il manager ha avuto bisogno di ottenere immagini con dimensioni esatte per il caricamento su alcuni servizi, poiché erano i loro requisiti tecnici. Ad esempio, se abbiamo l'originale dell'immagine di dimensioni 1200×1200, e durante il ridimensionamento scriviamo qualcosa come ?resize=600×400, otterremo un'immagine ridimensionata proporzionalmente per il lato più corto, delle dimensioni 400×400. Inoltre, non è possibile ottenere un'immagine con una risoluzione maggiore (upscale). Cioè, ?resize=1500×1500 restituirà la stessa immagine 1200×1200

Un articolo è venuto in aiuto OpenResty: trasformiamo NGINX in un server applicativo completo per comprendere come Nginx lavora con Lua e la stessa libreria per Lua isage/lua-imagick — collegamenti pure-c di Lua a ImageMagick. Perché è stata scelta questa soluzione, piuttosto che, diciamo, qualcosa in python — perché è veloce e comoda. Non è necessario creare alcun file, tutto direttamente nella configurazione di Nginx (non obbligatorio).

Quindi, di cosa abbiamo bisogno

Gli esempi saranno forniti sulla base di Debian.

Installazione di nginx e nginx-extras

apt-get update
apt-get install nginx-extras

Installazione di LuaJIT

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

Installare imagemagick

apt-get -y install imagemagick

e librerie magickwand ad esso, nel mio caso per la versione 6

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

Compilare lua-imagick

Cloniamo il repository (oppure scarichiamo il zip e lo estraiamo)

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

Se tutto è andato a buon fine, si può configurare Nginx.

Ecco un esempio di configurazione del backend host, che si occupa effettivamente del ridimensionamento. Viene proxy passato dal server frontale sempre con Nginx, dove avviene anche la cache per un certo periodo (un giorno) e altre cose.

configurazione 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
    }
}

Ciò che era richiesto (espansione dell'immagine ai bordi) avviene tramite img:extent() ed è definito dal parametro resize con segno + alla fine.

I seguenti parametri sono disponibili:

  • WxH (Mantieni il rapporto d'aspetto, usa la dimensione maggiore)
  • WxH^ (Mantieni il rapporto d'aspetto, usa la dimensione minore (ritaglia))
  • WxH! (Ignora il rapporto d'aspetto)
  • WxH+ (Mantieni il rapporto d'aspetto, aggiungi bordi laterali)

Tabella riassuntiva con i risultati del ridimensionamento

Parametro uri della richiesta
Dimensione dell'immagine di uscita

?resize=400×200
200×200

?resize=400×200^
400×400

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

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

Ridimensionamento delle immagini al volo con Nginx e LuaJIT (OpenResty)

Risultato

Data la potenza e la semplicità di questo approccio, è possibile realizzare operazioni con logiche piuttosto complesse, come aggiungere watermark o implementare l'autenticazione con accesso differenziato. Per scoprire le possibilità dell'API per la gestione delle immagini, è possibile consultare la documentazione della libreria. isage/lua-imagick

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS | ProHoster