背景
之前在使用阿里云OSS(对象存储)的服务时候一直比较好奇,只需要简单的在图片的访问链接上加上参数,就可以按照定义的功能,得到裁剪或者处理好的图片。并且访问的时候 还可以对图片自动压缩处理。
刚好最近看到了一些文章介绍 Nginx的 http_image_filter_module模块使用,果断尝试了之后,确实 get 了一项很实用的技能或者说是工具。
运行原理和优缺点分析
http_image_filter_module是Nginx提供的集成图片处理模块,支持nginx-0.7.54以后的版本,在网站访问量不是很高;磁盘有限不想生成多余的图片文件的前提下,就可以用它实时缩放图片,旋转图片,验证图片有效性以及获取图片宽高以及图片类型信息,由于是实时计算的结果,所以网站访问量极大的话,不建议使用。
Nginx图片处理http_image_filter_module 的优缺点:
优点
-
(1)操作简单。通过简单配置,省去了后端裁剪程序的复杂性;
-
(2)实时裁剪。可以实时访问在线裁剪图片;
-
(3)灵活性强。后端程序裁剪图片时需要知道裁剪图片的尺寸和质量,使用nginx裁剪可以实时裁剪任意尺寸的图片;
-
(4)不占用硬盘空间;
缺点
-
(1)消耗CPU和内存,访问量大的时候就会给服务器带来很大的负担。(可以通过使用Nginx缓存和缓存服务器来解决);
-
(2)功能不是很强大,支持的处理图片类型只包括JPG、JPEG、GIF、PNG or WebP;
开始实践起来吧!
使用docker启动一个自由裁切的nginx图片服务器
1. 首先创建相应的目录和配置文件
#启动之前需要把对应的目录创建好
mkdir -p /data/nginx/conf.d /data/nginx/logs /data/nginx/html
#创建的nginx的配置文件
touch /data/nginx/nginx.conf
2. 定义nginx的配置文件(本地图片资源)
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535; #进程限制
error_log /var/log/error.log warn;
pid /run/nginx.pid;
load_module /etc/nginx/modules/ngx_http_image_filter_module.so; #加载相应的模块配置
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 8192;
use epoll;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/conf.d/*/*.conf;
#配置对图片的压缩传输
gzip on;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types application/javascript text/plain application/x-javascript text/javascript text/css application/xml image/svg+xml image/jpeg image/png;
#定义配置文件
server {
listen 80;
listen [::]:80;
server_name _;
location ~* /images/.*\.(jpg|gif|png)$ {
root /usr/share/nginx/html;
# 图片默认宽度
set $width -;
# 图片默认高度
set $height -;
if ($arg_width != "") {
set $width $arg_width;
}
if ($arg_height != "") {
set $height $arg_height;
}
#image_filter off;
#image_filter test;
#image_filter size;
#image_filter rotate 90;
image_filter resize $width $height;
#image_filter crop 300 200;
image_filter_buffer 100M;
image_filter_interlace on;
image_filter_jpeg_quality 95;
image_filter_sharpen 100;
image_filter_transparency on;
}
}
}
3. 启动一个 my-nginx 容器,并且将图片资源挂载上去。
#这里我使用的是 nginx:1.25版本
docker run -it -p 80:80 --name my-nginx \
-v /data/nginx/nginx.conf:/etc/nginx/nginx.conf \
-v /data/nginx/conf.d:/etc/nginx/conf.d \
-v /data/nginx/logs:/var/log/nginx \
-v /data/nginx/html:/usr/share/nginx/html \
-d \
--restart=always \
nginx:1.25
4.传入图片 进行测试
#把准备好的图片拷贝到指定的目录中
cp mac-photo.jpg /data/nginx/html/images
5. 对比使用效果
通过访问地址
http://test.domain/images/mac-photo.jpg?height=200
http://test.domain/images/mac-photo.jpg?width=300
http://test.domain/images/mac-photo.jpg?width=600&height=500
就可以访问到按照比例出现的图。注意这里面有个问题是:图像显示是按照比例呈现的。并非任意的比都可以实现。 并且也不会超过其最大的比例
这是原图
这是裁切到500像素的效果 访问 test.domain/images/mac-…
这是裁切到100像素的效果 访问 test.domain/images/mac-…
6.如果想对其他网站上的图片进行裁切可以看这里(外部图片资源)
如下是nginx.conf的配置文件 使用proxy_pass 做图片代理
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535; #进程限制
error_log /var/log/error.log warn;
pid /run/nginx.pid;
load_module /etc/nginx/modules/ngx_http_image_filter_module.so;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 8192;
use epoll;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/conf.d/*/*.conf;
gzip on;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types application/javascript text/plain application/x-javascript text/javascript text/css application/xml image/svg+xml image/jpeg image/png;
server {
listen 80;
listen [::]:80;
server_name _;
location ~* /.*\.(jpg|gif|png)$ {
proxy_pass https://www.skyname.cn;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
# 图片默认宽度
set $width -;
# 图片默认高度
set $height -;
if ($arg_width != "") {
set $width $arg_width;
}
if ($arg_height != "") {
set $height $arg_height;
}
#image_filter off;
#image_filter test;
#image_filter size;
#image_filter rotate 90;
image_filter resize $width $height;
#image_filter crop 300 200;
image_filter_buffer 100M;
image_filter_interlace on;
image_filter_jpeg_quality 95;
image_filter_sharpen 100;
image_filter_transparency on;
}
}
}
这里 我们用 这张图片做示例www.skyname.cn/app/upload/…
访问test.domain/app/upload/…
可以看到图片被裁切变小
到这里就介绍完成了, 这里是一些参数详细解释。
image_filter off;
#关闭模块
image_filter test;
#确保图片是jpeg gif png否则返415错误
image_filter size;
#输出有关图像的json格式:如下显示{ "img" : { "width": 100, "height": 100, "type": "gif" } } 出错显示:{}
image_filter rotate 90|180|270;
#旋转指定度数的图像,参数可以包括变量,单独或一起与resize crop一起使用。
image_filter resize width height;
#按比例减少图像到指定大小,公减少一个可以另一个用"-"来表示,出错415,参数值可包含变量,可以与rotate一起使用,则两个一起生效。
image_filter crop width height;
#按比例减少图像比较大的侧面积和另一侧多余的载翦边缘,其它和rotate一样。没太理解
image_filter_buffer 10M;
#设置读取图像缓冲的最大大小,超过则415错误。
image_filter_interlace on;
#如果启用,最终的图像将被交错。对于JPEG,最终的图像将在“渐进式JPEG”格式。
image_filter_jpeg_quality 95;
#设置变换的JPEG图像的期望质量。可接受的值是从1到100的范围内。较小的值通常意味着既降低图像质量,减少传输数据,推荐的最大值为95。参数值可以包含变量。
image_filter_sharpen 100;
#增加了最终图像的清晰度。锐度百分比可以超过100。零值将禁用锐化。参数值可以包含变量。
image_filter_transparency on;
#定义是否应该透明转换的GIF图像或PNG图像与调色板中指定的颜色时,可以保留。透明度的损失将导致更好的图像质量。在PNG的Alpha通道总是保留透明度。