2018-01-05 thumbor使用简介
资源
https://github.com/thumbor/thumbor
http://thumbor.readthedocs.io/en/latest/index.html
配置
conf 文件在/etc/thumbor.conf
配置见文档
http://thumbor.readthedocs.io/en/latest/configuration.html
配置:
/usr/local/bin/thumbor-config
运行脚本文件
/usr/local/bin/thumbor
安装地址
/usr/local/lib/python2.7/dist-packages/thumbor
执行配置文件
/usr/local/lib/python2.7/dist-packages/thumbor/config.py
获取当前配置文件,执行,将配置文件导入到./thumbor.conf
thumbor-config > ./thumbor.conf
supervisor的配置,路径:/etc/supervisor/conf.d
,参考:http://tech.yipit.com/2013/01/03/how-yipit-scales-thumbnailing-with-thumbor-and-cloudfront/
[program:thumbor]
command=thumbor --port=800%(process_num)s --ip 0.0.0.0 --conf=/etc/thumbor.conf
process_name=thumbor800%(process_num)s
numprocs=1
user=username
autostart=true
autorestart=true
startretries=3
stopsignal=TERM
stdout_logfile=/var/log/thumbor/thumbor800%(process_num)s.stdout.log
stdout_logfile_maxbytes=1MB
stdout_logfile_backups=10
stderr_logfile=/var/log/thumbor/thumbor800%(process_num)s.stderr.log
stderr_logfile_maxbytes=1MB
stderr_logfile_backups=10
nginx 配置,路径/etc/nginx/nginx.conf
sites配置,实现将http://dev.img.ziines.com/180x180/ziines-user-upload/dev/upload/2017/10/23/98740_20171023171233_59edb28135217.jpg
映射到aws s3上。
upstream thumbor {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
}
server {
listen 80;
server_name dev.img.ziines.com;
client_max_body_size 10M;
rewrite_log on;
location ~ / {
proxy_cache cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
if ($request_uri ~ ziines-user-upload) {
rewrite ^/(.*)(ziines-user-upload.*) /unsafe/$1http://s3-ap-southeast-1.amazonaws.com/$2 break;
}
rewrite ^/(.*)(upload.*) /unsafe/$1http://dev.ziines.com/$2 break;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header X-Proxy-Cache $upstream_cache_status;
proxy_pass http://thumbor;
proxy_redirect off;
}
}
图片按比例放大缩小
http://yourthumbordomain/unsafe/0x100/http://yourwebsitedomain/files/images/2016/12/01/2016120115435927886796378745.png
resize 图片,如果指定width和height就会严格按照给定的widht,height生成图片,不会变形,但是比例跟原图不一致。如果只给定width,则会根据图片比例和width,生成匹配比例的缩略图。
水印
http://yourthumbordomain/unsafe/filters:watermark(https://i.pinimg.com/236x/07/0e/6e/070e6e3f1c3cf010076de715d7473e33--identity-design-logo-design.jpg,-10,-10,50)/http://zhaoshang.abilixschool.com/application/views/images/1.png
文件名不能带空格,否则会出不了图片。
参考:
https://github.com/thumbor/thumbor/issues/784
I have the same issue here, and I tried [@mvdklip](https://github.com/mvdklip) 's technique, and it's not working.
testing:
[http://localhost:8000/unsafe/640x360/mytest.jpg](http://localhost:8000/unsafe/640x360/mytest.jpg) (without any space in name) => OK
[http://localhost:8000/unsafe/640x360/my](http://localhost:8000/unsafe/640x360/my) test.jpg => not ok
[http://localhost:8000/unsafe/640x360/my%20test.jpg](http://localhost:8000/unsafe/640x360/my%20test.jpg) => not ok
[http://localhost:8000/unsafe/640x360/my%2520test.jpg](http://localhost:8000/unsafe/640x360/my%2520test.jpg) => not ok
I don't know what to test next neither what to do...
Most of my images have space in names or in directory names, I'm pretty stuck with that...
% 代表%25 ,空格用%20表示,要转换(2次rawurlencode)成%2520 才能被thumbor 正确解析到路径。
$path = '1 2.jpg';
echo rawurlencode(rawurlencode($path)) . '<br>'; // 输出1%25202.jpg
通过thumbor生成水印图片:
http://img.test.pool.nmg.com.hk/unsafe/filters:watermark(http://img.test.pool.nmg.com.hk/1200x0/files/ED.png,0,0,0)/http://img.test.pool.nmg.com.hk/1200x0/files/q.jpg
以下是nginx 代理配置
upstream thumbor3 {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
}
server {
listen 80;
server_name img.test.pool.nmg.com.hk;
client_max_body_size 10M;
rewrite_log on;
location ~ / {
proxy_cache cache;
proxy_cache_valid 200 302 48h;
proxy_cache_valid 404 1m;
if ($request_uri ~ unsafe/filters:watermark) {
# rewrite ^/unsafe/filters:watermark.* /unsafe/$
break;
}
rewrite ^/(.*)(files.*) /unsafe/$1http://test.pool.nmg.com.hk/$2 break;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
add_header X-Proxy-Cache $upstream_cache_status;
proxy_pass http://thumbor3;
proxy_redirect off;
}
}
下面是GD和thumbor生成水印和图片缩放的代码
/*
* @param width 大的图片宽度
@param oriWidth 小的图片宽度
@param oriHeight 图片高度
@return 新的图片高度
*/
function getNewImageHeight($width, $oriWidth, $oriHeight)
{
return round($oriHeight * ($oriWidth / $width));
}
function waterMarkByThumbor($filePath, $logoPath, $fileRelativePath, $logoRelativePath)
{
list($fileWidth, $fileHeight, $fileType) = getimagesize($filePath);
if ($fileWidth >= IMAGE_WIDTH_MAX) {
$settingWidth = IMAGE_WIDTH_MAX;
} else {
$logoThumborPath = thumborPath();
$settingWidth = $fileWidth;
}
$fileThumborPath = thumborPath($fileRelativePath, $settingWidth . 'x0');
$logoThumborPath = thumborPath($logoRelativePath, $settingWidth . 'x0');
$waterMarkThumborPath = IMAGE_POOL_URL . 'unsafe/filters:watermark(' .
$logoThumborPath . ',0,0,0)/' . $fileThumborPath;
$copyResult = file_put_contents($filePath, file_get_contents($waterMarkThumborPath));
if (!$copyResult) {
Log::out('publish', '', 'copy water mark by thumbor failed,source:' .
$waterMarkThumborPath . ',target:' . $filePath);
}
return $copyResult;
}
/*
添加水印图片
*/
function waterMarkImage($filePath, $waterPath, $parentPath)
{
list($fileWidth, $fileHeight, $fileType) = getimagesize($filePath);
if (!file_exists($filePath) || !file_exists($waterPath)) {
return $filePath;
}
list($markWidth, $markHeight, $markType) = getimagesize($waterPath);
list($fileWidth, $fileHeight, $fileType) = getimagesize($filePath);
if ($fileWidth < 1200) {
// 复制缩略图,压缩尺寸
$markName = 'tmp_water.png';
$newWaterPath = $parentPath . $markName; // 临时发布目录
if (file_exists($newWaterPath)) {
unlink($newWaterPath);
}
copy($waterPath, $newWaterPath);
$markHeight = getNewImageHeight($markWidth, $fileWidth, $markHeight);
resize_watermark($newWaterPath, $fileWidth, $markHeight);
$waterPath = $newWaterPath;
} elseif ($fileWidth > 1200) {
// 压缩原图为1200x0
// $newImageHeight = getNewImageHeight($fileWidth, IMAGE_WIDTH_MAX, $fileHeight);
resize_image($filePath, IMAGE_WIDTH_MAX);
}
$dst_image = getImageData($filePath, $fileType);
$logo_image = getImageData($waterPath, $markType);
imagealphablending($logo_image, false);
imagesavealpha($logo_image, true);
imagecopy($dst_image, $logo_image, 0, 0, 0, 0, $markWidth, $markHeight);
createImage($dst_image, $filePath, $fileType);
imagedestroy($dst_image);
imagedestroy($logo_image);
$endpoint = $filePath;
return $endpoint;
}
/*
生成新的水印图片
*/
function resize_watermark($file, $w, $h)
{
list($width, $height, $type) = getimagesize($file);
if (!$width || !$height) {
return false;
}
$r = $width / $height;
if ($w / $h > $r) {
$newwidth = $h * $r;
$newheight = $h;
} else {
$newheight = $w / $r;
$newwidth = $w;
}
$src = getImageData($file, $type);
$dst = imagecreatetruecolor($w, $h);
imagealphablending($dst, false);
imagesavealpha($dst, true);
$transparent = imagecolorallocatealpha($dst, 255, 255, 255, 127);
imagefilledrectangle($dst, 0, 0, $w, $h, $transparent);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
$base_image = imagecreatetruecolor($w, $h);
imagealphablending($base_image, false);
$col = imagecolorallocatealpha($base_image, 255, 255, 255, 127);
imagefilledrectangle($base_image, 0, 0, $w, $h, $col);
imagealphablending($base_image, true);
imagesavealpha($base_image, true);
imagecopy($base_image, $dst, 0, 0, 0, 0, $newwidth, $newheight);
createImage($base_image, $file, $type);
imagedestroy($dst);
imagedestroy($src);
imagedestroy($base_image);
return true;
}
function resize_image($file, $w, $crop = false, $transparent = false)
{
list($width, $height, $type) = getimagesize($file);
if (!$width || !$height) {
return false;
}
$r = $width / $height;
$h = getNewImageHeight($width, IMAGE_WIDTH_MAX, $height); // 計算壓縮後的圖片高度
if ($crop) {
if ($width > $height) {
$width = ceil($width - ($width * abs($r - $w / $h)));
} else {
$height = ceil($height - ($height * abs($r - $w / $h)));
}
$newwidth = $w;
$newheight = $h;
} else {
if ($w / $h > $r) {
$newwidth = $h * $r;
$newheight = $h;
} else {
$newheight = $w / $r;
$newwidth = $w;
}
}
if ($w == IMAGE_WIDTH_MAX) {
$newwidth = IMAGE_WIDTH_MAX;
$newheight = $h;
}
$src = getImageData($file, $type);
$dst = imagecreatetruecolor($newwidth, $newheight);
if ($transparent) {
imagealphablending($dst, false);
imagesavealpha($dst, true);
$transparent = imagecolorallocatealpha($dst, 255, 255, 255, 127);
imagefilledrectangle($dst, 0, 0, $newwidth, $newheight, $transparent);
}
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
createImage($dst, $file, $type);
imagedestroy($dst);
imagedestroy($src);
return true;
}