前言
文章有点长,感觉有用的朋友可以先加收藏。
前两天刚搭建了自己的博客,并写了一篇介绍性的文章:《极简博客搭建,搭建超级简单又好看》,这几天准备写点文章体验一下这款博客。发现不论是撰写文章还是展示效果,都非常符合我的品味,真是太棒了。
直到今天我上传了一张图片,于是便有了这篇文章。
因果
一般情况,我写一篇博客会直接上传图片到文章,有时上传的尺寸并不太适合在文章内显示。就有了打开 PS 或者截取一部分再上传,这就放慢了写博文的速度。我就想有没有在线处理的方式,这样就免去了简单修图的烦恼。
网上也找到很多现成的接口,不过像我们这种都想把核心技术掌握在自己手上的人来说,这不能满足我们的欲望。而且可定制性太小,这样这个解决方案就出炉了!
效果预览
可以实现对jpeg,png,webp(仅解码),tiff和gif图像格式(包括GIF动画)的裁剪、旋转、等操作。更多效果,可快速向下滑动,查看其它操作的效果图。
效果预览
准备
和以往的文章一样,本文章也一样尽力做到通俗易懂,使用的命令尽量简单,让更多的人可以用上好用的服务。
主要用到的工具
- Docker
- 开源库 imageproxy (不需要具体了解,没有安装配置等其它操作,写在这里只是为了让想 DIY 的朋友知道下核心功能)
启动服务
- 启动图片处理服务
mkdir -p /data/image
docker run --restart always --name image-service -p 8080:8080 -v /data/image:/image -d willnorris/imageproxy -cache /image -addr 0.0.0.0:8080
当然你不想保存图片到本地的话,可以运行如下命令
docker run --restart always --name image-service -p 8080:8080 -d willnorris/imageproxy -addr 0.0.0.0:8080
参数解释(不关心的不用看,可直接看第 3 步)
docker run
: 表示运行一个容器,可以想像成运行一个程序
--restart always
:表示程序如果死掉就自动重新启动,保证一直提供服务
--name image-service
: 给你的程序起个名字,image-service 可以换成任何名字
-v /data/image:/image
: 表示把你本地的一个目录放到程序里面用,注:这个目录是容器里面图片保存的文件夹,这里这么操作是当你删除这个容器的时候,你所获取过的图片可直接提供服务,不需重新拉取图片。注意:如果是 Mac 或者 windows 启动不了,需要检查 /data/目录 docker 是否有操作的权限
-p 8080:8080
: 把容器里的一个端口映射到你的宿主机上(也就是你操作的这台服务器上,注意:请检查你的服务器安全组或者防火墙是否对这个端口开放,否则可能外部无法访问你的服务)
willnorris/imageproxy
: 镜像名
-cache /image
: (镜像内参数,也就是你个程序提供的可配置参数), 设置图片缓存在容器内的/image
文件夹内,对应你机子的/data/image
-addr 0.0.0.0:8080:(镜像内参数,也就是你个程序提供的可配置参数), 绑定容器内的0.0.0.0
ip(也就是所有的 ip)8080
端口上。对应你机子上的8080
端口,这个视你-p
参数而定。
本文章使用的测试图片地址:
http://www.picloud.me/images/2015/03/29/fcfc854b160ef5adb93006a02352b647.jpg
- 到这里你已经启动了你的服务,已经可以很好的达到效果了。下面演示一下如何使用:
主要使用方式http://localhost:8080/{options}/{remote_url}
解释:
我的效果{options} - 你需要对目录图片作的调整
{remote_url} - 原图地址
你可以随意修改当前的{options}
在当前URL中就是800x
,可以换成100x
,200x
,200x300
看看具体效果,下面我们来讲一下{options}
部分可以怎么配置,来达到智能裁剪、旋转、占位等效果。
- 现在你的图片处理服务已经启动了。当然图片每一次加载的时候会有点慢,因为第一次访问时需要去目标地址把图片下载到本地,而后通过你的链接提供服务。当然你加了文件缓存后,只要地址不变,你的图片将会通过本地提供服务,而不会再去远端下载。聪明的你可能已经尝试了一些参数来达到你想要的效果了,也可能知道占位功能如何实现了,那么下面我们就详细看下有哪些参数可以配置,能达到怎样华丽的效果。
参数详解
- 定宽,高度自适应
{多少像素}x
例:200x
、800x
(上面例子就是使用了这个参数)
- 高度的百分之多少,宽度自适应
x{百分比}
例:x0.15
(高度的 15%) 、x0.8(高度的 80%)
- 按固定宽高裁剪图片(这个用来做点位图再好不过了,随便选张图,占位无难度)
{宽度}x{高度}
例:400x300
生成 400px * 300px的图片,自动裁剪
- 正方形图片(生成头像的时候很有用)
{数字}
例:96
(生成 96*96 的头像)
- 第二个参数
之前说的都是只有一个参数,有时你可能需要旋转一下,或者翻转一下,传第二个参数可以达到你想要的效果。翻转图片
图片翻转
600,fh
这里的参数表示生成一个600*600
且左右翻转,如果想要水平翻转,可以使用 fv,或者两个一起使用,变成600,fv,hv
,当然你也可以和前面的1,2,3,4
讲到的参数配合使用。
旋转图片
智能裁剪?
r90
逆时针旋转90
度, 这里的度数只能是90
,180
,270
其它的不生效。注意:图片有一个 EXIF 属性,此属性是图片内置的方向属性,当前服务使用的工具已经自动旋转成原始的方向了,相关资料可以自己查一下,关键字:图片 EXIF 属性
图片质量
图片质量测试
q80
设置图片为 80%的质量(默认质量为 95%)图片质量越小,图片的大小会更小,可以节省带宽、提高加载加载图片的速度。
截取图片中的一部分
截取并生成一张 100 像素的头像
cx600,cy500,cw300,ch300,100
这部分参数就很有意思了,c
你可以认为是裁剪,这样x
,y
和w
,h
就组成两个坐标(600,500)
,(300,300)
,表示从这张图片的(600,500)
开始,截取一张300px*300px
的图片, 后面的100
是之前第4 点
说到的,缩放到正方形,这样就有了如下的效果。当然这些参数也可以和之前的共用,也没有顺序的关系。
智能裁剪
image.png
sc
加入此参数,可以实现智能裁剪。可以做到图片感知扩展,压缩扩展人脸不变形(人脸感知),不过这个我感觉可以优化一下,试了下效果没那么好。
服务命令启动参数
当前我们使用了
-cache /image -addr 0.0.0.0:8080
这两个启动参数,在参数介绍里已经介绍过了,这里我们来说明一下-cache
这个 flag, 现在这个是直接传了文件给它,实现了把图片缓存到了本地文件。这里还可以缓存到以下地方:缓存
- 缓存到内存
-cache memory:200:4h
缓存到内存,最大内存使用为 200MB, 且最多缓存 4 小时。容量和过期时间可选,也可以不指定-cache memory
,默认使用100MB内存。- 缓存到亚马逊存储
s3 URL (例:s3://region/bucket-name/optional-path-prefix)
3.缓存到 Google 云
gcs URL (例:gcs://bucket-name/optional-path-prefix)- 缓存到微软的世纪互联
azure URL (例: azure://container-name/)
如果是存到世纪互联,你需要提供两个环境变量:
AZURESTORAGE_ACCOUNT_NAME(account name)
AZURESTORAGE_ACCESS_KEY(access key)- 缓存到 Redis
redis URL (例:redis://hostname/)
如果 redis 有密码,需要环境变量
REDIS_PASSWORD服务拉取远端使用的 referrers
可以通过
-referrers example.com
来设置限制图片拉取的站
-remoteHosts example.com,example1.com
设置只从example.com
,example1.com
获取图片,其它的源图地址将不被服务。这样可以防止别人恶意使用你的服务。
小结
到这里,你已经可以为你的博客或其它提供高定制化的图片服务了,包括裁剪、旋转等功能。这样,很多修图的工作就可以放到这个服务里去做。当然,这个服务还有很多小的问题,比如感觉裁剪扩充效果不好,估计作者也在优化。如果长期没有动作的话,我倒可以写一个类似功能的,如果有机会,可以在后期的博客中与大家见面。
还有就是缓存的地点基本是国外的服务,像国内的七牛、阿里 OSS、腾讯等云存储没有接入,这方面都有现在的库,如果自己使用可以自行接入。
有任何问题欢迎评论讨论,也可私信我。
当前服务比较耗资源,如果要布当前服务的话,不要选择有 cpu 限制的服务器。
还没有服务器?快领取一张高额优惠券
网友评论
location ~ ^/api/imageproxy/ {
# pattern match to capture the original URL to prevent URL
# canonicalization, which would strip double slashes
if ($request_uri ~ "/api/imageproxy/(.+)") {
set $path $1;
rewrite .* /$path break;
}
proxy_pass http://localhost:8080;
}
感谢提供 nginx 配置
有具体的例子吗?我这边用了都挺好用的。