Es ist schon eine Weile her, inspiriert von einem Artikel wurde das Resizing von Bildern mit Hilfe von und alles funktionierte wie geplant. Doch es trat ein Problem auf, als der Manager Bilder mit genauen Abmessungen für das Hochladen auf bestimmte Dienste benötigte, da dies deren technische Anforderungen waren. Zum Beispiel, wenn wir das Originalbild mit der Größe 1200×1200, und beim Resizing geben wir etwas wie ?resize=600×400ein, erhalten wir ein proportional verkleinertes Bild an der kleinsten Kante mit der Größe 400×400. Es ist auch nicht möglich, ein Bild mit höherer Auflösung (Upscale) zu erhalten. Das heißt, ?resize=1500×1500 gibt nur das gleiche Bild zurück 1200×1200
Ein Artikel kam zur Hilfe um zu verstehen, wie Nginx mit Lua funktioniert und die Bibliothek für Lua — Lua pure-c Bindings für ImageMagick. Warum wurde diese Lösung gewählt und nicht, sagen wir, etwas in Python — weil es schnell und praktisch ist. Sie müssen nicht einmal irgendwelche Dateien erstellen, alles direkt in der Nginx-Konfiguration (optional).
Also, was brauchen wir
Beispiele werden auf Basis von Debian gegeben.
Installation von nginx und nginx-extras
apt-get update
apt-get install nginx-extrasInstallation von LuaJIT
apt-get -y install lua5.1 luajit-5.1 libluajit-5.1-devInstallation von imagemagick
apt-get -y install imagemagickund die Bibliothek magickwand darum, in meinem Fall für Version 6
apt-cache search libmagickwand
apt-get -y install libmagickwand-6.q16-3 libmagickwand-6.q16-devBuild lua-imagick
Wir klonen das Repository (oder wir laden das Zip herunter und entpacken es)
cd ~
git clone https://github.com/isage/lua-imagick.git
cd lua-imagick
mkdir build
cd build
cmake ..
make
make installWenn alles erfolgreich war, kann Nginx konfiguriert werden.
Ich gebe ein Beispiel für die Konfiguration des Backend-Hosts, der sich um das Resizing kümmert. Er wird vom Frontserver ebenfalls mit Nginx proxied, wobei für eine bestimmte Zeit (einen Tag) und andere Dinge Caching erfolgt.
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
}
}
Das, was benötigt wurde (Erweiterung des Bildes an den Rändern), geschieht durch img:extent() und wird durch den Parameter resize mit dem Vorzeichen + am Ende definiert.
Die folgenden Parameter sind verfügbar:
- WxH (Seitenverhältnis beibehalten, höhere Dimension verwenden)
- WxH^ (Seitenverhältnis beibehalten, niedrigere Dimension verwenden (zuschneiden))
- WxH! (Seitenverhältnis ignorieren)
- WxH+ (Seitenverhältnis beibehalten, Seiteneinfassungen hinzufügen)
Zusammenfassungstabelle mit den Ergebnissen des Resizings
Parameter uri der Anfrage
Größe des Ausgangsbildes
?resize=400×200
200×200
?resize=400×200^
400×400
?resize=400×200!
400×200 (Nicht proportional)
?resize=400×200+
400×200 (Proportional)

Zusammenfassung
Angesichts der gesamten Leistungsfähigkeit und Einfachheit eines solchen Ansatzes können recht komplexe Logiken realisiert werden, zum Beispiel das Hinzufügen von Wasserzeichen oder die Implementierung von Berechtigungen für den Zugriff. Um die API-Möglichkeiten zur Arbeit mit Bildern zu erfahren, kann auf die Dokumentation der Bibliothek verwiesen werden.
Quelle: habr.com
