Canviar la mida de les imatges sobre la marxa mitjançant Nginx i LuaJIT (OpenResty)

Des de fa força temps, inspirat en l'article Canvi de mida de la imatge sobre la marxa El canvi de mida de la imatge es va configurar amb ngx_http_image_filter_module i tot va funcionar com calia. Però un problema va sorgir quan el gestor necessitava rebre imatges amb dimensions exactes per pujar a alguns serveis, perquè... aquests eren els seus requisits tècnics. Per exemple, si tenim una imatge original de mida 1200 × 1200, i quan canviem de mida escrivim alguna cosa així ?resize=600×400, llavors obtenim una imatge proporcionalment reduïda al llarg de la vora més petita, la mida 400 × 400. També és impossible obtenir una imatge amb una resolució més alta (upscale). Aquells. ?resize=1500×1500 retornarà la mateixa imatge 1200 × 1200

Aquest article va venir al rescat OpenResty: convertir NGINX en un servidor d'aplicacions complet per entendre com funciona Nginx amb Lua i la pròpia biblioteca per a Lua isage/lua-imagick - Enllaços Lua pure-c a ImageMagick. Per què es va triar aquesta solució, i no, per exemple, alguna cosa a Python, perquè és ràpida i còmoda. Ni tan sols cal que creeu cap fitxer, tot està bé a la configuració de Nginx (opcional).

Aleshores, què necessitem

Es donaran exemples basats en Debian.

Instal·lant nginx i nginx-extras

apt-get update
apt-get install nginx-extras

Instal·lació de LuaJIT

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

Instal·lació d'imagemagick

apt-get -y install imagemagick

i biblioteques màgia màgica a això, en el meu cas per a la versió 6

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

Construcció lua-imagick

Clonem el repositori (o agafem el zip i el desempaquetem)

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

Si tot ha anat bé, podeu configurar Nginx.

Posaré un exemple de la configuració de l'amfitrió del backend, que, de fet, s'encarrega de canviar la mida. El servidor frontal, també amb Nginx, l'envia aproximadament, on la memòria cau es produeix durant un període de temps determinat (dies) i altres coses.

configuració del 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
    }
}

El que es necessitava (ampliar la imatge per les vores) passa amb img:extent() i es defineix mitjançant el paràmetre resize amb un rètol + al final.

Les opcions següents estan disponibles:

  • WxH (Mantenir la relació d'aspecte, utilitzar una dimensió més alta)
  • WxH^ (Mantenir la relació d'aspecte, utilitzar una dimensió inferior (retallar))
  • WxH! (Ignora la relació d'aspecte)
  • WxH+ (Mantenir la relació d'aspecte, afegir vores laterals)

Taula resum amb resultats de canvi de mida

Sol·licita el paràmetre uri
Mida de la imatge de sortida

?resize=400×200
200 × 200

?resize=400×200^
400 × 400

?resize=400×200!
400×200 (no proporcional)

?Resize=400×200+
400×200 (proporcional)

Canviar la mida de les imatges sobre la marxa mitjançant Nginx i LuaJIT (OpenResty)

Total

Tenint en compte la potència i la senzillesa d'aquest enfocament, podeu implementar coses amb una lògica força complexa, per exemple, afegint marques d'aigua o implementant autorització amb accés limitat. Per conèixer les capacitats de l'API per treballar amb imatges, podeu consultar la documentació de la biblioteca isage/lua-imagick

Font: www.habr.com

Afegeix comentari