Ændr størrelse på billeder i farten ved hjælp af Nginx og LuaJIT (OpenResty)

I et stykke tid nu, inspireret af artiklen Ændr størrelsen på billeder i farten billedstørrelse blev konfigureret vha ngx_http_image_filter_module og alt fungerede som det skulle. Men et problem opstod, da lederen skulle modtage billeder med nøjagtige dimensioner til upload til nogle tjenester, fordi... det var deres tekniske krav. For eksempel hvis vi har et originalt billede af størrelse 1200 × 1200, og når vi ændrer størrelse, skriver vi noget som ?ændre størrelse=600×400, så får vi et proportionalt reduceret billede langs den mindste kant, størrelse 400 × 400. Det er også umuligt at få et billede med en højere opløsning (opskalere). De der. ?ændre størrelse=1500×1500 vil returnere det samme billede 1200 × 1200

Denne artikel kom til undsætning OpenResty: gør NGINX til en fuldgyldig applikationsserver at forstå, hvordan Nginx arbejder med Lua og selve biblioteket for Lua isage/lua-imagegick - Lua pure-c bindinger til ImageMagick. Hvorfor blev denne løsning valgt, og ikke f.eks. noget i python - fordi det er hurtigt og bekvemt. Du behøver ikke engang at oprette nogen filer, alt er rigtigt i Nginx-konfigurationen (valgfrit).

Så hvad har vi brug for

Eksempler vil blive givet baseret på Debian.

Installation af nginx og nginx-extras

apt-get update
apt-get install nginx-extras

Installerer LuaJIT

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

Installerer imagemagick

apt-get -y install imagemagick

og biblioteker tryllestav 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

Opbygning af lua-image

Vi kloner depotet (eller tager zip'en og pakker den ud)

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

Hvis alt gik godt, kan du konfigurere Nginx.

Jeg vil give et eksempel på konfigurationen af ​​backend-værten, som faktisk er ansvarlig for størrelsesændring. Den proxes af frontserveren, også med Nginx, hvor der sker caching i en vis periode (dage) og andre ting.

nginx backend-konfiguration

# 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 påkrævet (udvidelse af billedet rundt om kanterne) sker vha img:extent() og defineres ved hjælp af parameteren resize med et skilt + i slutningen.

Følgende muligheder er tilgængelige:

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

Oversigtstabel med resize-resultater

Anmod om uri-parameter
Output billedstørrelse

?ændre størrelse=400×200
200 × 200

?ændre størrelse=400×200^
400 × 400

?ændre størrelse=400×200!
400×200 (Ikke proportional)

?ændre størrelse=400×200+
400×200 (Proportional)

Ændr størrelse på billeder i farten ved hjælp af Nginx og LuaJIT (OpenResty)

Total

I betragtning af kraften og enkelheden i denne tilgang, kan du implementere ting med ret kompleks logik, for eksempel tilføjelse af vandmærker eller implementering af autorisation med begrænset adgang. For at finde ud af API'ets muligheder for at arbejde med billeder, kan du henvise til bibliotekets dokumentation isage/lua-imagegick

Kilde: www.habr.com

Tilføj en kommentar