De ceva timp, inspirat de un articol a fost configurată redimensionarea imaginilor folosind și totul a funcționat așa cum trebuie. Dar a apărut o problemă, când managerul a avut nevoie să obțină imagini cu dimensiuni precise pentru încărcare pe unele servicii, deoarece acestea erau cerințele lor tehnice. De exemplu, dacă avem un original al imaginii cu dimensiunea 1200×1200, iar la redimensionare specificăm ceva de genul ?resize=600×400, atunci vom obține o imagine redusă proporțional la cea mai mică dimensiune, având dimensiunea 400×400. De asemenea, nu este posibil să obținem o imagine cu o rezoluție mai mare (upscale). Adică, ?resize=1500×1500 va returna exact aceeași imagine 1200×1200
În ajutor a venit articolul pentru a înțelege cum funcționează Nginx cu Lua și biblioteca în sine pentru Lua — binding-uri pure-c Lua pentru ImageMagick. De ce a fost aleasă această soluție, și nu, să spunem, ceva pe Python — pentru că este rapid și convenabil. Nici nu va trebui să creați fișier, totul se face direct în configurația Nginx (nu este obligatoriu).
Așadar, ce ne va trebui
Exemplele vor fi prezentate pornind de la Debian.
Instalarea nginx și nginx-extras
apt-get update
apt-get install nginx-extrasInstalarea LuaJIT
apt-get -y install lua5.1 luajit-5.1 libluajit-5.1-devInstalarea imagemagick
apt-get -y install imagemagickși bibliotecile magickwand pentru acesta, în cazul meu pentru versiunea 6
apt-cache search libmagickwand
apt-get -y install libmagickwand-6.q16-3 libmagickwand-6.q16-devCompilarea lua-imagick
Clonăm repository-ul (sau luăm zip-ul și-l dezarhivăm)
cd ~
git clone https://github.com/isage/lua-imagick.git
cd lua-imagick
mkdir build
cd build
cmake ..
make
make installDacă totul a decurs bine, putem configura Nginx.
Voi prezenta un exemplu de configurație a backend-ului hostului, care se ocupă propriu-zis de redimensionare. Este proxy-izat de serverul frontal folosind de asemenea Nginx, pe care se face caching pentru o anumită perioadă (24 de ore) și alte lucruri.
configurația 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
}
}
Ceea ce era necesar (extinderea imaginii pe marginile) se realizează cu ajutorul img:extent() și este definit cu ajutorul parametrului resize cu semnul + la final.
Următoarele parametrii sunt disponibili:
- WxH (Menține raportul de aspect, utilizând dimensiunea mai mare)
- WxH^ (Menține raportul de aspect, utilizând dimensiunea mai mică (cropează))
- WxH! (Ignoră raportul de aspect)
- WxH+ (Menține raportul de aspect, adaugă margini laterale)
Tabel rezumat cu rezultatele redimensionării
Parametrul uri al solicitării
Dimensiunea imaginii de ieșire
?resize=400×200
200×200
?resize=400×200^
400×400
?resize=400×200!
400×200 (Nu proporțional)
?resize=400×200+
400×200 (Proporțional)

Rezultatul
Având în vedere toată puterea și simplitatea acestui mod de abordare, se pot implementa lucruri cu o logică destul de complexă, cum ar fi adăugarea de watermark-uri sau implementarea unei autorizări cu acces restricționat. Pentru a afla posibilitățile API-ului pentru lucrul cu imagini, se poate consulta documentația bibliotecii.
Sursa: habr.com
