Resize billeder i realtid med Nginx og LuaJIT (OpenResty)

For længe siden, inspireret af en artikel Resizing Images on the Fly blev der konfigureret resizing af billeder ved hjælp af ngx_http_image_filter_module og det fungerede som det skulle. Men der opstod et problem, da en medarbejder havde brug for at hente billeder med præcise dimensioner til upload til visse tjenester, da det var deres tekniske krav. For eksempel, hvis vi har det originale billede i størrelsen 1200×1200, og når vi resize, skriver vi noget i retning af ?resize=600×400, så får vi et proportionalt reduceret billede langs den mindste kant, som måler 400×400. Det er heller ikke muligt at få et billede med en større opløsning (upscale). Det vil sige, ?resize=1500×1500 vil returnere det samme billede 1200×1200

En artikel hjalp mig OpenResty: Forvandler NGINX til en fuldgyldig applikationsserver med at forstå, hvordan Nginx fungerer med Lua og selve biblioteket til Lua isage/lua-imagick — Lua pure-c bindings til ImageMagick. Hvorfor blev denne løsning valgt frem for noget på Python - fordi det er hurtigt og bekvemt. Du behøver endda ikke at oprette nogen filer, alt er direkte i Nginx-konfigurationen (hvilket ikke er nødvendigt).

Så hvad har vi brug for

Eksemplerne vil blive givet på Debian.

Installation af nginx og nginx-extras

apt-get update
apt-get install nginx-extras

Installation af LuaJIT

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

Installation af imagemagick

apt-get -y install imagemagick

og biblioteket magickwand til det, i mit tilfælde for version 6

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

Bygning af lua-imagick

Klone depotet (eller hente zip og udpakke det)

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

Hvis alt gik vel, kan du konfigurere Nginx.

Jeg vil give et eksempel på konfigurationen af backend-host, som netop beskæftiger sig med resizing. Den proxyes af frontend-serveren også med Nginx, hvor caching finder sted i et stykke tid (24 timer) og andre ting.

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

Det, der var nødvendigt (udvidelse af billedet langs kanterne), sker med hjælp af img:extent() og bestemmes ved hjælp af parameteren resize med tegn + i slutningen.

De følgende parametre er tilgængelige:

  • WxH (Behold aspektforhold, brug højere dimension)
  • WxH^ (Behold aspektforhold, brug lavere dimension (beskær))
  • WxH! (Ignorer aspektforhold)
  • WxH+ (Behold aspektforhold, tilføj sidekanter)

Oversigtstabel med resultaterne af resizing

Parameteren uri i forespørgslen
Størrelsen på det udgående billede

?resize=400×200
200×200

?resize=400×200^
400×400

?resize=400×200!
400×200 (Ikke proportionalt)

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

Resize billeder i realtid med Nginx og LuaJIT (OpenResty)

Resultat

Med al den kraft og enkelhed, som denne tilgang tilbyder, kan man implementere ret komplekse logikker, såsom at tilføje vandmærker eller realisere godkendelse med begrænset adgang. For at finde ud af API'ets muligheder for billedbehandling kan man konsultere dokumentationen for biblioteket. isage/lua-imagick

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster