Redimensionați imaginile din mers folosind Nginx și LuaJIT (OpenResty)

De ceva vreme, inspirat de articol Redimensionarea imaginii din mers redimensionarea imaginii a fost configurată folosind ngx_http_image_filter_module și totul a funcționat așa cum trebuia. Dar o problemă a apărut când managerul a trebuit să primească imagini cu dimensiuni exacte pentru încărcare în unele servicii, deoarece... acestea erau cerințele lor tehnice. De exemplu, dacă avem o imagine originală de dimensiune 1200 × 1200, iar la redimensionare scriem ceva de genul ?resize=600×400, apoi obținem o imagine proporțional redusă de-a lungul celei mai mici margini, dimensiune 400 × 400. De asemenea, este imposibil să obțineți o imagine cu o rezoluție mai mare (upscale). Acestea. ?resize=1500×1500 va returna aceeași imagine 1200 × 1200

Acest articol a venit în ajutor OpenResty: transformarea NGINX într-un server de aplicații cu drepturi depline pentru a înțelege cum funcționează Nginx cu Lua și biblioteca în sine pentru Lua isage/lua-imagick - Legături Lua pure-c la ImageMagick. De ce a fost aleasă această soluție și nu, să zicem, ceva în python - pentru că este rapidă și convenabilă. Nici măcar nu trebuie să creați fișiere, totul este corect în configurația Nginx (opțional).

Deci de ce avem nevoie

Vor fi date exemple pe baza Debian.

Instalarea nginx și nginx-extras

apt-get update
apt-get install nginx-extras

Instalarea LuaJIT

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

Instalarea imagemagick

apt-get -y install imagemagick

și biblioteci baghetă magică la el, în cazul meu pentru versiunea 6

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

Construirea lua-imagick

Clonăm depozitul (sau luăm zip-ul și îl despachetăm)

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

Dacă totul a mers bine, puteți configura Nginx.

Voi da un exemplu de configurație a gazdei backend, care, de fapt, este responsabilă de redimensionare. Este proxy de către serverul frontal, tot cu Nginx, unde are loc memorarea în cache pentru o anumită perioadă de timp (zile) și alte lucruri.

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

Ceea ce a fost necesar (extinderea imaginii în jurul marginilor) se întâmplă folosind img:extent() și este definit folosind parametrul resize cu un semn + la sfarsit.

Sunt disponibile următoarele opțiuni:

  • LxH (Păstrează raportul de aspect, folosește dimensiunea mai mare)
  • WxH^ (Păstrați raportul de aspect, utilizați dimensiunea inferioară (decupare))
  • LxH! (Ignorați raportul de aspect)
  • LxH+ (Păstrați raportul de aspect, adăugați margini laterale)

Tabel rezumat cu rezultatele redimensionării

Solicitați parametrul uri
Dimensiunea imaginii de ieșire

?resize=400×200
200 × 200

?resize=400×200^
400 × 400

?resize=400×200!
400×200 (nu proporțional)

?resize=400×200+
400×200 (proporțional)

Redimensionați imaginile din mers folosind Nginx și LuaJIT (OpenResty)

Total

Având în vedere puterea și simplitatea acestei abordări, puteți implementa lucruri cu o logică destul de complexă, de exemplu, adăugarea de filigrane sau implementarea autorizației cu acces limitat. Pentru a afla capabilitățile API-ului pentru lucrul cu imagini, puteți consulta documentația bibliotecii isage/lua-imagick

Sursa: www.habr.com

Adauga un comentariu