Nginx と LuaJIT (OpenResty) を使用してその場で画像のサイズを変更します

かなり前から、この記事に触発されて オンザフライで画像のサイズを変更する 画像のサイズ変更は次を使用して構成されました ngx_http_image_filter_module そしてすべてが正常に機能しました。 しかし、マネージャーがいくつかのサービスにアップロードするために正確なサイズの画像を受信する必要があるときに、XNUMX つの問題が発生しました。 これらは彼らの技術的要件でした。 たとえば、次のサイズの元の画像があるとします。 1200x1200そして、サイズを変更するときは次のように書きます ?リサイズ=600×400、次に、最小エッジに沿って比例的に縮小された画像が得られます。 400x400。 また、それ以上の解像度(アップスケール)の画像を取得することもできません。 それらの。 ?リサイズ=1500×1500 同じ画像を返します 1200x1200

この記事が役に立ちました OpenResty: NGINX を本格的なアプリケーション サーバーに変える Nginx が Lua とどのように連携するか、および Lua のライブラリ自体を理解する isage/lua-imagick - ImageMagick への Lua pure-C バインディング。 たとえば Python でのソリューションではなく、このソリューションが選ばれた理由は、高速で便利だからです。 ファイルを作成する必要さえありません。すべてが Nginx 構成に含まれています (オプション)。

それで、何が必要ですか

Debian に基づいて例を示します。

nginx と nginx-extras のインストール

apt-get update
apt-get install nginx-extras

LuaJIT のインストール

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

imagemagickのインストール

apt-get -y install imagemagick

と図書館 魔法の杖 私の場合はバージョン6の場合

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

lua-imagick の構築

リポジトリのクローンを作成します (または zip を取得して解凍します)

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

すべてがうまくいけば、Nginx を構成できます。

実際にサイズ変更を担当するバックエンド ホストの構成の例を示します。 これはフロント サーバーによってプロキシされ、同じく Nginx を使用して、一定期間 (日) などのキャッシュが発生します。

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

必要なこと(画像の端の周りを拡大すること)は、次のようにして行われます。 img:extent() パラメータを使用して定義されます resize 署名済み + 最後に。

次のオプションが利用可能です。

  • 幅×高さ (アスペクト比を維持し、より高い寸法を使用)
  • WxH^ (アスペクト比を維持し、より低い寸法を使用 (トリミング))
  • W×H! (アスペクト比を無視します)
  • WxH+ (アスペクト比を維持し、サイドボーダーを追加)

サイズ変更結果をまとめた表

リクエストの URI パラメータ
出力画像サイズ

?リサイズ=400×200
200x200

?resize=400×200^
400x400

?サイズ変更=400×200!
400×200(非比例)

?resize=400×200+
400×200(比例)

Nginx と LuaJIT (OpenResty) を使用してその場で画像のサイズを変更します

合計

このアプローチの強力さとシンプルさを考慮すると、透かしの追加やアクセスを制限した承認の実装など、非常に複雑なロジックを実装することができます。 画像を操作するための API の機能を確認するには、ライブラリのドキュメントを参照してください。 isage/lua-imagick

出所: habr.com

コメントを追加します