gm图片处理

项目中需要对上传的图片做下处理,比如把原图做一个缩略图,加水印等功能,我使用了gm模块

模块地址: http://aheckmann.github.io/gm/docs.html

这个模块支持:

GraphicsMagick and ImageMagick

因为我机器上装的是ImageMagick,所以我用的是ImageMagick

使用方式:

var gm = require('gm'); 
var imageMagick = gm.subClass({ imageMagick: true });

gm的文档写的比较清楚,需要什么命令查下项目地址,基本上都可以找到,不过上面的项目地址不是最新的,有些命令在文档上并没有找到,只能看下源码了

图片添加水印的命令就没有,所以做下记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

/**
* 图片水印
*/
function addImagWatermark() {
var icon = './logo-2.jpg'; //水印地址
var DIRECTION = {
NorthWest: 'NorthWest',
North: 'North',
NorthEast: 'NorthEast',
West: 'West',
Center: 'Center',
East: 'East',
SouthWest: 'SouthWest',
South: 'South',
SouthEast: 'SouthEast'
};
var writecreateStream = fs.createWriteStream(orignimg);
imageMagick(orignimg)
.composite(icon) //水印
.gravity(DIRECTION['SouthEast']) //水印位置
.geometry('+120+90') //水印坐标,这里的意思是右下角为原点 距离右边120px 下边90px
.dissolve(90) //透明度
.stream().pipe(writecreateStream);
writecreateStream.on('finish', function () {
console.log('All writes are now finish.');
});
writecreateStream.on('close', function () {
console.log('All writes are now close.');
});
writecreateStream.on('error', function (error) {
console.error('write error', error);
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 文字水印
*/
function addWordsWatermark() {
imageMagick(destimg)
.gravity(DIRECTION['SouthEast']) //水印的位置
.geometry('+10+10') //距离右下角右边10px下边10px
.stroke("gray")//文字颜色
.font("font.ttf", 20) //文字字体大小 这里的文字文件需要存在
.drawText(15, 10, "hello world") //15和10是位置信息 最后一个参数是文字信息
.write(destimg, function (err) {
if (err) {
return console.error('err--------', err);
}
console.log("Written composite image.");
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 裁剪缩放图片
*/
function resizeAndCropImag(){
imageMagick(orignImgPath) //图片源地址可以是stream或者path
.gravity(DIRECTION['Center'])//设置处理的原点,这里是以中心为原点
.crop(150, 150) //裁剪大小
.resize(50, 50, '!')//缩放大小 50*50 !强制缩放到50*50 不要按照比例
.stream().pipe(writecreateStream);
writecreateStream.on('close', () => {
thumbnailsize.width = IMAGEMINSIZE;
thumbnailsize.height = IMAGEMINSIZE;
return callback(null,thumbnailsize);
});
writecreateStream.on('error', (error) => {
console.error('write error',error);
return callback(error);
});
}

上面是一些图片处理的实例

在开发的过程中也遇到了一个问题,这个问题以前也遇到过,就是一个图片在电脑上预览的时候是正常的,但是在app里面查看,发现旋转了90度,造成这个问题的原因是因为图片的exif里面的
orientation造成的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{ Format: 'JPEG (Joint Photographic Experts Group JFIF format)',
format: 'JPEG',
'Mime type': 'image/jpeg',
Class: 'DirectClass',
Geometry: '1920x1080+0+0',
size: { width: 1920, height: 1080 },
Resolution: '72x72',
'Print size': '26.6667x15',
Units: 'Undefined',
Type: 'TrueColor',
Endianess: 'Undefined',
Colorspace: 'sRGB',
Depth: '8-bit',
depth: 8,
'Channel depth': { red: '8-bit', green: '8-bit', blue: '8-bit' },
'Channel statistics':
{ Pixels: '2073600',
Red:
{ min: '0 (0)',
max: '255 (1)',
mean: '59.4655 (0.233198)',
'standard deviation': '61.9419 (0.242909)',
kurtosis: '2.66796',
skewness: '1.83875',
entropy: '0.85667' },
Green:
{ min: '1 (0.00392157)',
max: '255 (1)',
mean: '58.7454 (0.230374)',
'standard deviation': '58.8431 (0.230757)',
kurtosis: '3.55934',
skewness: '2.01144',
entropy: '0.859977' },
Blue:
{ min: '0 (0)',
max: '255 (1)',
mean: '56.8535 (0.222955)',
'standard deviation': '57.2232 (0.224405)',
kurtosis: '3.98003',
skewness: '2.08816',
entropy: '0.85872' } },
'Image statistics':
{ Overall:
{ min: '0 (0)',
max: '255 (1)',
mean: '58.3548 (0.228842)',
'standard deviation': '59.3683 (0.232817)',
kurtosis: '3.36539',
skewness: '1.9756',
entropy: '0.858456' } },
'Rendering intent': 'Perceptual',
Gamma: '0.454545',
Chromaticity:
{ 'red primary': '(0.64,0.33)',
'green primary': '(0.3,0.6)',
'blue primary': '(0.15,0.06)',
'white point': '(0.3127,0.329)' },
'Background color': 'white',
'Border color': 'srgb(223,223,223)',
'Matte color': 'grey74',
'Transparent color': 'black',
Interlace: 'None',
Intensity: 'Undefined',
Compose: 'Over',
'Page geometry': '1920x1080+0+0',
Dispose: 'Undefined',
Iterations: '0',
Compression: 'JPEG',
Quality: '78',
Orientation: 'RightTop',
Properties:
{ 'date:create': '2016-10-17T10:09:47+08:00',
'date:modify': '2016-10-17T09:46:34+08:00',
'exif:ColorSpace': '1',
'exif:ExifImageLength': '1080',
'exif:ExifImageWidth': '1920',
'exif:ExifOffset': '38',
'exif:Orientation': '6',
'jpeg:colorspace': '2',
'jpeg:sampling-factor': '2x2,1x1,1x1',
signature: '5336e20b319346abfebb86749f6c6c27213324b226d11e63027d2db45a34c649' },
Profiles:
{ 'Profile-8bim': '40 bytes',
'Profile-exif': '86 bytes',
'Profile-iptc': '0 bytes' },
Artifacts:
{ filename: '/data/dist/lib/57ea5e684c9fecec0001b381.png',
verbose: 'true' },
Tainted: 'False',
Filesize: '161KB',
'Number pixels': '2.074M',
'Pixels per second': '691.2GB',
'User time': '0.000u',
'Elapsed time': '0:01.000',
Version: 'ImageMagick 6.9.1-1 Q16 x86_64 2015-04-15 http://www.imagemagick.org',
path: '/data/dist/lib/57ea5e684c9fecec0001b381.png' }

这里可以使用gm提供的autoOrient的方法来做下处理:

1
2
3
4
   imageMagick(originPath).autoOrient().write(targetPath, function (err) {
if(err) return callback(err);
callback(null);
});

这样子处理下,图片就可以正确显示了

看下autoOrient的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
module.exports = function (proto) {

var exifTransforms = {
topleft: ''
, topright: ['-flop']
, bottomright: ['-rotate', 180]
, bottomleft: ['-flip']
, lefttop: ['-flip', '-rotate', 90]
, righttop: ['-rotate', 90]
, rightbottom: ['-flop', '-rotate', 90]
, leftbottom: ['-rotate', 270]
}

proto.autoOrient = function autoOrient () {
// Always strip EXIF data since we can't
// change/edit it.

// imagemagick has a native -auto-orient option
// so does graphicsmagick, but in 1.3.18.
// nativeAutoOrient option enables this if you know you have >= 1.3.18
if (this._options.nativeAutoOrient || this._options.imageMagick) {
this.out('-auto-orient');
this.strip();
return this;
}

this.preprocessor(function (callback) {
this.orientation({bufferStream: true}, function (err, orientation) {
if (err) return callback(err);

var transforms = exifTransforms[orientation.toLowerCase()];
if (transforms) {

// remove any existing transforms that might conflict
var index = this._out.indexOf(transforms[0]);
if (~index) {
this._out.splice(index, transforms.length);
}

// repage to fix coordinates
this._out.unshift.apply(this._out, transforms.concat('-page', '+0+0'));
}

this.strip();

callback();
});
});

return this;
}
}

大概可以看出来当等于RightTop的时候,会旋转90度,除了这种情况,剩下的几种会有其它的处理方式。

其它的参考:
http://sylvana.net/jpegcrop/exif_orientation.html
http://www.cnblogs.com/itlover2013/p/4553862.html