var buf = require('fs').readFileSync('test.jpg');
gm().in('-page', '+0+0').in(buf,'test.jpg').write('output.jpg', function (err) {
if (err) console.log(err);
})
in this case i want to pass buffer data as input to the gm.in()
method.
Below is the link I'm referencing but in it, an image path is used as an input. I want to use buffer data as an input. How can I do this?
Tile four images together using Node.js and GraphicsMagick
Without modifying the source of GraphicsMagick itself, you can't. The gm
module interacts with the GraphicsMagick program through the command line. The arguments you're passing through the .in()
method are being converted into command-line arguments. The GraphicsMagick program only accepts filenames for this argument and will not attempt to process any direct form of data.
If you really needed to make this work without the filesystem, you could always download the GraphicsMagick source code and change the CLI to accept some form of data blob instead of a URL for this argument.
Actually I was creating a poster with two different image one is template image "background" and 2nd is top image with some text. I tried with gm
but i loose image quality. Someone guide me to use Buffer data as input to improve the image quality. I tried but don't know how to pass Buffer data as an input.
So finally i decided to use node child process with command string. Here is the sample code i am sharing with you.
var fs = require('fs');
var gm = require("gm");
var exec = require('child_process').exec;
var IMAGEFILEPATH = "/images";
var gmcreateImage = function() {
var imageConfig = {"topimage":{"density":"300x300","startx":925,"starty":650,"width":575,"height":825},
"offers": [
{"startx": 75, "starty": 850, "msg": "SAVE 5$", "textcolor": "#4f61ac", "font": "Arial Bold", "fontsize":34,"stroke":{"color":"#4f61ac","width":4}},
{"startx": 75, "starty": 970, "msg": "per gallon", "textcolor": "#4f61ac", "font": "Arial Bold", "fontsize":34,"stroke":{"color":"#4f61ac","width":4}},
{"startx": 75, "starty": 1150, "msg": "With the purchase of", "textcolor": "black", "font": "Arial", "fontsize":18,"stroke":{"color":"black","width":1}},
{"startx": 75, "starty": 1260, "msg": "any Pepsi Z0 S2", "textcolor": "black", "font": "Arial", "fontsize":16,"stroke":{"color":"black","width":1}},
{"startx": 75, "starty": 1370, "msg": "on all flavours", "textcolor": "black", "font": "Arial", "fontsize":16,"stroke":{"color":"black","width":1}},
{"startx": 75, "starty": 1480, "msg": "Ask for details.", "textcolor": "black", "font": "Arial", "fontsize":18,"stroke":{"color":"black","width":1}}
]};
var addLast=imageConfig.topimage.last;
var commandStr = "gm convert '-page' '+0+0' '-units' 'PixelsPerInch' '-density' '" + imageConfig.topimage.density + "' '" + IMAGEFILEPATH+ "/template.jpg' ";
var imageActualPosition={};
imageActualPosition["x"] = imageConfig.topimage.startx;
imageActualPosition["y"] = imageConfig.topimage.starty;
if (!addLast) {
commandStr += " '-page' '+" + imageActualPosition["x"] + "+" + imageActualPosition["y"] + "' '" + IMAGEFILEPATH + "/top.jpg' ";
}
var offers = imageConfig.offers;
for (var i in offers) {
var color = offers[i].textcolor;
var startX = offers[i].startx;
var startY = offers[i].starty;
var font = offers[i].font;
var fontSize = offers[i].fontsize;
var msg = offers[i].msg;
var offerStr = "";
if (offers[i].stroke) {
offerStr += " '-stroke' '" + offers[i].stroke.color + "' '-strokewidth' '" + offers[i].stroke.width + "'";
}
offerStr += " '-fill' '" + color + "' '-pointsize' '" + fontSize + "' '-draw' 'text " + startX + " " + startY + " \"" + msg + "\"'";
commandStr += offerStr;
}
if (addLast) {
commandStr += " '-page' '+" + imageActualPosition["x"] + "+" + imageActualPosition["y"] + "' '" + IMAGEFILEPATH + "/top.jpg' ";
}
var finalImage="done.jpg";
commandStr += " '-mosaic' '-quality' '100' '" + IMAGEFILEPATH + finalImage + "'";
exec(commandStr, function(err, stdout, stderr) {
if (err) {
console.log("Error while executing gm commands" + err);
return;
} else {
console.log("Done See your image");
}
})
};
gmcreateImage();
As noted in another response, graphicsmagick doesn't allow a buffer as an input. However, interestingly, it does allow an HTTP URL as an input. If you are determined to get this to work without modifying graphicsmagick's source code, try something like this:
Add the uuid module:
npm install uuid
Create a global object to hold the buffers:
const magickbuffers = {}
Create an http server in your script:
const uuid = require('uuid')
const http = require('http')
const magickserver = new http.Server()
const magickport = 9555
magickserver.on('request', (req, res) => {
res.writeHead(200, { 'Content-Type': 'image/png' })
if (magickbuffers[req.url]) {
res.end(magickbuffers[req.url])
}
else {
res.end("\n")
}
})
magickserver.listen(magickport, () => {})
Create a prototype to supply a usable local url so graphicsmagick can find the buffer on the local server and hand it off as an image, and also to handle the storage of the buffer:
Object.prototype.openBuffer = function() {
this.id = uuid()
magickbuffers[`/${this.id}`] = this
return `http://localhost:${magickport}/${this.id}`
}
Create another prototype to handle the cleanup of the buffer once you're completely done with it:
Object.prototype.closeBuffer = function() {
delete magickbuffers[`/${this.id}`]
return true
}
Old example that is desired but doesn't work:
gm()
.in('-page', '+0+0')
.in(bufferone) // gm cant use a buffer here, this won't work
.in('-page', '+50+20')
.in(buffertwo) // or here
.mosaic()
.stream('png', function (err, stdout, stderr) {
stdout.pipe(writestream)
})
New method that works:
let one = bufferone.openBuffer()
let two = buffertwo.openBuffer()
gm()
.in('-page', '+0+0')
.in(one) // gm recognizes this because 'one' is a url pointing to the buffer
.in('-page', '+50+20')
.in(two)
.mosaic()
.stream('png', function (err, stdout, stderr) {
stdout.pipe(writestream)
bufferone.closeBuffer() // do this once gm has completely finished using these buffers
buffertwo.closeBuffer() // don't forget to do this for each buffer manipulated with .openBuffer()
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With