Redimensione imagens dinamicamente usando Nginx e LuaJIT (OpenResty)

Já há algum tempo, inspirado no artigo Redimensionando Imagens em Tempo Real , o redimensionamento de imagem com ngx_http_image_filter_module foi configurado e tudo funcionou como deveria. Mas havia um problema quando o gerente precisava obter imagens com tamanhos exatos para fazer o upload para alguns serviços, porque esses eram seus requisitos técnicos. Por exemplo, se tivermos uma imagem original do tamanho 1200x1200 e, ao redimensionar, escrevermos algo como ? Resize = 600x400 , obteremos uma imagem proporcionalmente reduzida na borda menor, tamanho 400x400 . Também é impossível obter uma imagem com uma resolução mais alta (upscale). Essa. ? redimensionar = 1500x1500 retornará a mesma imagem1200x1200


Um artigo do OpenResty veio ao resgate: transformamos o NGINX em um servidor de aplicativos completo para entender como o Nginx funciona com Lua e a biblioteca do próprio Lua isage / lua-imagick - ligações Lua pure-c ao ImageMagick. Por que essa solução foi escolhida, e não, digamos, algo em python - porque é rápida e conveniente. Você nem precisa criar arquivos, tudo está certo na configuração do Nginx (opcional).


Então, o que precisamos


Exemplos serão dados com base no Debian.


Instale o nginx e o nginx-extras


apt-get update
apt-get install nginx-extras

Instale LuaJIT


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

Instale o imagemagick


apt-get -y install imagemagick

e as bibliotecas de varinha mágica , no meu caso para a versão 6


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

Construção Lua-imagick


Clonamos o repositório (ou pegamos o zip e descompactamos)


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

Se tudo correu bem, você pode configurar o Nginx.


backend , , , . Nginx, () . .


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

, ( ) img:extent() resize + .


:


  • WxH (Keep aspect-ratio, use higher dimension)
  • WxH^ (Keep aspect-ratio, use lower dimension (crop))
  • WxH! (Ignore aspect-ratio)
  • WxH+ (Keep aspect-ratio, add side borders)


uri
?resize=400x200200x200
?resize=400x200^400x400
?resize=400x200!400x200 ( )
?resize=400x200+400x200 ()



Dado o poder e a simplicidade dessa abordagem, você pode implementar coisas com uma lógica bastante complexa, por exemplo, adicionar marca d'água'i ou implementar autorização com acesso limitado. Para descobrir os recursos da API para trabalhar com imagens, você pode consultar a documentação da biblioteca isage / lua-imagick


All Articles