Regrandigi bildojn sur la flugo uzante Nginx kaj LuaJIT (OpenResty)

Jam de sufiĉe da tempo, inspirite de la artikolo Regrandigi bildojn sur la muŝo bildo regrandigo estis agordita uzante ngx_http_image_filter_module kaj ĉio funkciis kiel ĝi devus. Sed unu problemo aperis kiam la administranto bezonis ricevi bildojn kun precizaj dimensioj por alŝuto al iuj servoj, ĉar... ĉi tiuj estis iliaj teknikaj postuloj. Ekzemple, se ni havas originalan bildon de grandeco 1200 × 1200, kaj regrandigante ni skribas ion kiel ?regrandigi=600×400, tiam ni ricevas proporcie reduktitan bildon laŭ la plej malgranda rando, grandeco 400 × 400. Ankaŭ estas neeble akiri bildon kun pli alta rezolucio (altskala). Tiuj. ?regrandigi=1500×1500 redonos la saman bildon 1200 × 1200

Ĉi tiu artikolo venis al la savo OpenResty: turnante NGINX en plentaŭgan aplikaĵoservilon por kompreni kiel Nginx funkcias kun Lua kaj la biblioteko mem por Lua isage/lua-imagick - Lua pure-c ligadoj al ImageMagick. Kial oni elektis ĉi tiun solvon, kaj ne, ekzemple, ion en python - ĉar ĝi estas rapida kaj oportuna. Vi eĉ ne bezonas krei ajnajn dosierojn, ĉio estas ĝuste en la Nginx-agordo (laŭvola).

Kion do ni bezonas

Ekzemploj estos donitaj surbaze de Debiano.

Instalante nginx kaj nginx-extras

apt-get update
apt-get install nginx-extras

Instalante LuaJIT

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

Instalante imagemagick

apt-get -y install imagemagick

kaj bibliotekoj magiĉevalo al ĝi, en mia kazo por versio 6

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

Konstruanta lua-imagick

Ni klonas la deponejon (aŭ prenu la zipon kaj malpakigas ĝin)

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

Se ĉio iris bone, vi povas agordi Nginx.

Mi donos ekzemplon de la agordo de la backend-gastiganto, kiu, fakte, respondecas pri regrandigo. Ĝi estas proksita de la antaŭa servilo, ankaŭ kun Nginx, kie kaŝmemoro okazas dum certa tempodaŭro (tagoj) kaj aliaj aferoj.

nginx backend agordo

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

Kio estis postulata (vastigi la bildon ĉirkaŭ la randoj) okazas uzante img:extent() kaj estas difinita uzante la parametron resize kun signo + en la fino.

La jenaj opcioj disponeblas:

  • WxH (Konservu aspekto-proporcion, uzu pli altan dimension)
  • WxH^ (Konservu aspekto-proporcion, uzu pli malaltan dimension (tondado))
  • WxH! (Ignoru aspekto-proporcion)
  • WxH+ (Konservu aspekto-proporcion, aldonu flankajn randojn)

Resuma tabelo kun regrandigorezultoj

Petu uri-parametron
Eligo Bilda Grandeco

?regrandigi=400×200
200 × 200

?regrandigi=400×200^
400 × 400

?regrandigi=400×200!
400×200 (Ne proporcia)

?regrandigi=400×200+
400×200 (Proporcia)

Regrandigi bildojn sur la flugo uzante Nginx kaj LuaJIT (OpenResty)

La rezulto

Konsiderante la potencon kaj simplecon de ĉi tiu aliro, vi povas efektivigi aferojn kun sufiĉe kompleksa logiko, ekzemple, aldonante akvomarkojn aŭ efektivigante rajtigon kun limigita aliro. Por ekscii la kapablojn de la API por labori kun bildoj, vi povas raporti al la biblioteko dokumentado isage/lua-imagick

fonto: www.habr.com

Aldoni komenton