Cambia o tamaño das imaxes sobre a marcha usando Nginx e LuaJIT (OpenResty)

Dende hai un tempo, inspirado no artigo Cambio de tamaño da imaxe sobre a marcha O cambio de tamaño da imaxe foi configurado usando ngx_http_image_filter_module e todo funcionou como debía. Pero un problema xurdiu cando o xestor necesitaba recibir imaxes con dimensións exactas para cargalas nalgúns servizos, porque... estes eran os seus requisitos técnicos. Por exemplo, se temos unha imaxe orixinal de tamaño 1200 × 1200, e ao cambiar o tamaño escribimos algo así ?resize=600×400, entón obtemos unha imaxe proporcionalmente reducida ao longo do bordo máis pequeno, tamaño 400 × 400. Tamén é imposible obter unha imaxe cunha resolución superior (upscale). Eses. ?resize=1500×1500 devolverá a mesma imaxe 1200 × 1200

Este artigo veu ao rescate OpenResty: converte NGINX nun servidor de aplicacións completo para entender como funciona Nginx con Lua e a propia biblioteca para Lua isage/lua-imagick - Ligazóns Lua pure-c a ImageMagick. Por que se escolleu esta solución e non, digamos, algo en Python, porque é rápido e cómodo. Nin sequera precisa crear ningún ficheiro, todo está ben na configuración de Nginx (opcional).

Entón, que necesitamos

Daranse exemplos baseados en Debian.

Instalación de nginx e nginx-extras

apt-get update
apt-get install nginx-extras

Instalación de LuaJIT

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

Instalación de imagemagick

apt-get -y install imagemagick

e bibliotecas maxia máxica a el, no meu caso para a versión 6

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

Construíndo lua-imagick

Clonamos o repositorio (ou collemos o zip e desempaquetamos)

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

Se todo saíu ben, podes configurar Nginx.

Vou poñer un exemplo da configuración do servidor backend, que, de feito, é o responsable do redimensionamento. É proxy polo servidor frontal, tamén con Nginx, onde o caché ocorre durante un período de tempo (días) e outras cousas.

configuración de 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
    }
}

O que se requiría (ampliar a imaxe arredor dos bordos) ocorre usando img:extent() e defínese mediante o parámetro resize cun sinal + ao final.

As seguintes opcións están dispoñibles:

  • Ancho x alto (manteña a relación de aspecto, usa dimensións máis altas)
  • WxH^ (Mantén a relación de aspecto, usa unha dimensión inferior (recortar))
  • WxH! (Ignorar a relación de aspecto)
  • WxH+ (Manter a relación de aspecto, engadir bordos laterais)

Táboa de resumo cos resultados do cambio de tamaño

Solicitar parámetro uri
Tamaño da imaxe de saída

?resize=400×200
200 × 200

?redimensionar=400×200^
400 × 400

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

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

Cambia o tamaño das imaxes sobre a marcha usando Nginx e LuaJIT (OpenResty)

Total

Tendo en conta o poder e a sinxeleza deste enfoque, pode implementar cousas cunha lóxica bastante complexa, por exemplo, engadindo marcas de auga ou implementando autorización con acceso limitado. Para coñecer as capacidades da API para traballar con imaxes, podes consultar a documentación da biblioteca isage/lua-imagick

Fonte: www.habr.com

Engadir un comentario