问题
How to use graphicsmagick crop circle picture?
(use png transparent background outer circle)
I use graphicsmagick in node.js
, or have any other way make this in node.js
?
Before: http://i.stack.imgur.com/B34C5.png
After: http://i.stack.imgur.com/PWjQW.png
回答1:
After many hours of fiddling, I found a clean solution using node-gm and Imagemagick.
var gm = require('gm').subClass({ imageMagick: true });
var original = 'app-server/photo.jpg';
var output = 'app-server/photo.png';
var size = 80;
gm(original)
.crop(233, 233,29,26)
.resize(size, size)
.write(output, function() {
gm(size, size, 'none')
.fill(output)
.drawCircle(size/2,size/2, size/2, 0)
.write(output, function(err) {
console.log(err || 'done');
});
});
回答2:
I use another module to solve this problem:
this code is for square image (this.height = this.width)
node-pngjs
var fs = require('fs'),
PNG = require('pngjs').PNG;
fs.createReadStream(__dirname + "/input.png")
.pipe(new PNG({
filterType: 4
}))
.on('parsed', function() {
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
var idx = (this.width * y + x) << 2;
var radius = this.height / 2;
if(y >= Math.sqrt(Math.pow(radius, 2) - Math.pow(x - radius, 2)) + radius || y <= -(Math.sqrt(Math.pow(radius, 2) - Math.pow(x - radius, 2))) + radius) {
this.data[idx + 3] = 0;
}
}
}
this.pack().pipe(fs.createWriteStream(__dirname + "/output.png"));
});
回答3:
I was able to do it with the following plugin: https://www.npmjs.com/package/circle-image
After you install it:
var images = require('circle-image');
var imageSizes = [125, 100, 30];
//uniqueId param is used to identify a user
//so user the primary key or something guaranteed to be unique
images.execute('imagepath', uniqueId, imageSizes).then(function (paths) {
//array of circularized image paths
console.log(paths[0]); //circle_user_{uniqueId}_150.png
})
回答4:
Took me hours to figure it out
- I wanted to avoid third party software, like ImageMagick (many npm packages are built on top of that)
- node-pngjs only appears to support PNG files + requires too much custom code
Here is my solution using sharp:
const sharp = require('sharp');
const width = 400,
r = width / 2,
circleShape = Buffer.from(`<svg><circle cx="${r}" cy="${r}" r="${r}" /></svg>`);
sharp('input.jpg')
.resize(width, width)
.composite([{
input: circleShape,
blend: 'dest-in'
}])
.webp()
.toFile('output.webp', (err, info) => err ?
console.error(err.message) :
console.log(info)
);
If you are interested, basing on the code above I created a utility that gets base64 encoded image (from frontend), and outputs file stream with the circle image. Used temp-write package to save processed images in temp directory.:
const fs = require('fs'),
sharp = require('sharp'),
tempWrite = require('temp-write');
module.exports = {
toCircle: (base64String, width) => new Promise((resolve, reject) => {
const imageBuffer = Buffer.from(base64String, "base64"),
tmpImage = tempWrite.sync('', 'tmp.webp'),
r = width / 2,
circleShape = Buffer.from(`<svg><circle cx="${r}" cy="${r}" r="${r}" /></svg>`);
sharp(imageBuffer)
.resize(width, width)
.composite([{
input: circleShape,
blend: 'dest-in'
}])
.webp()
.toFile(tmpImage, (err) => err ?
reject(err.message) :
resolve(fs.createReadStream(tmpImage))
);
})
};
回答5:
Here is version using gm
and buffers:
var gm = require('gm').subClass({ imageMagick: true });
var max = 200;
// buffer - is Buffer with picture
gm(buffer)
.autoOrient()
.gravity('Center')
.resize(max, max, '^')
.extent(max, max)
.noProfile()
.setFormat('png')
.out('(')
.rawSize(max, max)
.out('xc:Black')
.fill('White')
.drawCircle(max/2,max/2, max/2, 1)
.out('-alpha', 'Copy')
.out(')')
.compose('CopyOpacity')
.out('-composite')
.trim()
.toBuffer((err, buffer) => {
//...
});
The above node.js code is equivalent to this ImageMagick command, but using buffers:
convert input.png \
-gravity Center \
-resize 200x200^ \
-extent 200x200 \
\( -size 200x200 \
xc:Black \
-fill White \
-draw 'circle 100 100 100 1' \
-alpha Copy \
\) -compose CopyOpacity -composite \
-trim output.png
来源:https://stackoverflow.com/questions/29256640/how-to-use-graphicsmagick-in-node-js-to-crop-circle-picture-other-use-any-other