Nginx的http_image_filter插件可以方便地对图片进行缩放、裁剪、转换格式等等。官方文档:http://nginx.org/en/docs/http/ngx_http_image_filter_module.html
官方的filer包含以下几种:
image_filter off;
image_filter test;
image_filter size;
image_filter rotate 90 | 180 | 270;
image_filter resize width height;
image_filter crop width height;
其中crop为裁剪,只保留图片居中的部分。例如原图:http://127.0.0.1/uploads/36.jpg
裁剪后:http://127.0.0.1/crop/a/200_80/uploads/36.jpg
而我现在想要的效果是保留图片的上面部分,从上往下裁剪。而nginx不支持这种,所以修改了一下插件的源码,添加一种裁剪方法:croptop。
我用的是v1.5.3版本的nginx源码。修改代码 src/http/modules/ngx_http_image_filter_module.c:
$ diff ngx_http_image_filter_module.c ngx_http_image_filter_module.c.bak
21d20
< #define NGX_HTTP_IMAGE_CROP_TOP 6
825,835d823
< } else if (conf->filter == NGX_HTTP_IMAGE_CROP_TOP) {
<
< resize = 0;
<
< if ((ngx_uint_t) dx > ctx->max_width) {
< dy = dy * ctx->max_width / dx;
< dy = dy ? dy : 1;
< dx = ctx->max_width;
< resize = 1;
< }
<
927c915
<
---
>
977,1012d964
< if (conf->filter == NGX_HTTP_IMAGE_CROP_TOP) {
<
< src = dst;
<
< if ((ngx_uint_t) dy > ctx->max_height) {
< oy = dy - ctx->max_height;
< ox = 0;
< dst = ngx_http_image_new(r, dx - ox, dy - oy, colors);
<
< if (dst == NULL) {
< gdImageDestroy(src);
< return NULL;
< }
<
< ox /= 2;
< oy = 0;
<
< ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
< "image crop: %d x %d @ %d x %d",
< dx, dy, ox, oy);
<
< if (colors == 0) {
< gdImageSaveAlpha(dst, 1);
< gdImageAlphaBlending(dst, 0);
< }
<
< gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, ctx->max_height);
<
< if (colors) {
< gdImageTrueColorToPalette(dst, 1, 256);
< }
<
< gdImageDestroy(src);
< }
< }
<
1383,1385d1334
<
< } else if (ngx_strcmp(value[i].data, "croptop") == 0) {
< imcf->filter = NGX_HTTP_IMAGE_CROP_TOP;
可根据此更改制作path包:
$ diff ngx_http_image_filter_module.c ngx_http_image_filter_module.c.bak > image_filter.patch $ patch ngx_http_image_filter_module.c image_filter.patch
nginx 配置:
location ~ /croptop/([^/]+)/(\d+)_(\d+)/(.*)$ {
set $md5 $1;
set $width $2;
set $height $3;
set $img_path $4;
set $imguri http://127.0.0.1/$img_path;
proxy_pass $imguri;
image_filter croptop $width $height;
image_filter_jpeg_quality 85;
}
编译nginx:
sudo apt-get install openssl-dev sudo apt-get install openssl sudo apt-get install libssl0.9.8 sudo apt-get install libssl-dev sudo apt-get install libpcre3 libpcre3-dev sudo apt-get install libgd2-xpm-dev sudo apt-get install libgeoip-dev ./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log \ --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi \ --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy \ --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi \ --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --with-pcre-jit --with-debug \ --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module \ --with-http_image_filter_module --with-http_stub_status_module --with-http_ssl_module --with-http_sub_module \ --with-http_xslt_module --with-ipv6 --with-sha1=/usr/include/openssl --with-md5=/usr/include/openssl \ --with-mail --with-mail_ssl_module
访问新方法来裁剪图片 http://127.0.0.1/croptop/a/200_80/uploads/36.jpg,效果如下图:
原crop裁剪方法有个问题,就是当图片原宽度比裁剪宽度小的时候,比如原 232 x 350,要裁剪成 250 x 250,那么裁剪后变成 165 x 250,也就是它会把高350压缩成 250,宽度等比缩放到 165,而165比我们要的250要小,所以就不再裁剪了。
我想要的效果是,宽度小于250,就不缩放,直接按 232 x 232来裁剪出一个正方形。于是添加了一个自定义裁剪类型square,代码如下:
$ diff ngx_http_image_filter_module.c ngx_http_image_filter_module.c.bak
21,22d20
< #define NGX_HTTP_IMAGE_CROP_TOP 6
< #define NGX_HTTP_IMAGE_SQUARE 7
826,850d823
< } else if (conf->filter == NGX_HTTP_IMAGE_CROP_TOP) {
<
< resize = 0;
<
< if ((ngx_uint_t) dx > ctx->max_width) {
< dy = dy * ctx->max_width / dx;
< dy = dy ? dy : 1;
< dx = ctx->max_width;
< resize = 1;
< }
<
< } else if (conf->filter == NGX_HTTP_IMAGE_SQUARE) {
<
< resize = 0;
<
< if ((ngx_uint_t) dx > ctx->max_width) {
< dy = dy * ctx->max_width / dx;
< dy = dy ? dy : 1;
< dx = ctx->max_width;
< resize = 1;
< } else {
< ctx->max_width = dx;
< ctx->max_height = dx;
< }
<
942,950d914
<
< if (conf->filter == NGX_HTTP_IMAGE_CROP || conf->filter == NGX_HTTP_IMAGE_SQUARE) {
<
< if (conf->filter == NGX_HTTP_IMAGE_SQUARE) {
< if ((ngx_uint_t)dy < ctx->max_width){
< ctx->max_width = dy;
< ctx->max_height = dy;
< }
< }
951a916
> if (conf->filter == NGX_HTTP_IMAGE_CROP) {
1000,1035d964
< if (conf->filter == NGX_HTTP_IMAGE_CROP_TOP) {
<
< src = dst;
<
< if ((ngx_uint_t) dy > ctx->max_height) {
< oy = dy - ctx->max_height;
< ox = 0;
< dst = ngx_http_image_new(r, dx - ox, dy - oy, colors);
<
< if (dst == NULL) {
< gdImageDestroy(src);
< return NULL;
< }
<
< ox /= 2;
< oy = 0;
<
< ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
< "image crop: %d x %d @ %d x %d",
< dx, dy, ox, oy);
<
< if (colors == 0) {
< gdImageSaveAlpha(dst, 1);
< gdImageAlphaBlending(dst, 0);
< }
<
< gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, ctx->max_height);
<
< if (colors) {
< gdImageTrueColorToPalette(dst, 1, 256);
< }
<
< gdImageDestroy(src);
< }
< }
<
1407,1409d1335
< } else if (ngx_strcmp(value[i].data, "croptop") == 0) {
< imcf->filter = NGX_HTTP_IMAGE_CROP_TOP;
<
1412,1414d1337
<
< } else if (ngx_strcmp(value[i].data, "square") == 0) {
< imcf->filter = NGX_HTTP_IMAGE_SQUARE;


