I am making a guess the number game over socket.io in node.js Lets say I ask the person to guess the a number 124 which is obviously shown to the user as 12_ ,I want to tell the person complete 12_, if they guessed 4 as the last digit, that would be right answer, how do I send an image containing the text 12_ for each person over socket.io. I need a way to generate images. I believe storing images for a large number of people would be a bad idea. or could I simply have 7 or 8 plain backgrounds and dynamically overlay text that I want on these backgrounds and send it to the user.
What have I tried
I cannot use node-canvas as it needs a native dependency on Heroku
I cannot use GraphicsMagick as Heroku s free plan doesnt support it
Any suggestions
you have to read the image and convert into base64 on the server side
socket.emit('image', { image: true, buffer: buf.toString('base64') });
where as on the client side you can use websocket to receive image
var ctx = document.getElementById('canvas').getContext('2d');
socket.on("image", function(info) {
if (info.image) {
var img = new Image();
img.src = 'data:image/jpeg;base64,' + info.buffer;
ctx.drawImage(img, 0, 0);
}
});
I know it's a really old question, but maybe it helps someone (as there's very little info about this).
I just wanted to say that you can use GraphicsMagick and ImageMagick in Heroku. You just need to add a buildpack for it to work (it works even on free instances).
Here's a blogpost I made saying how I used GraphicsMagick in Node.js. You can check the code on Github (fair warning, the code sucks, but hey, it works).
Related
I have a simple utility that i use to size image on the fly via url params.
Having some troubles with the ruby image libraries (cmyk to rvb is, how to say… "unavailable"), i gave it a shot via nodejs, which solved the issue.
Basically, if the image does not exists, node or ruby transforms it. Otherwise when the image has already been requested/transformed, the ruby or node processes aren't touched, the image is returned statically
The ruby works perfectly, a bit slow if lot of transforms are requested at once, but very stable, it always go through whatever the amount (i see the images arriving one the page one after another)
With node, it works also perfectly, but when a large amount of images are requested, for a single page load, the first images is transformed, then all the others requests returns the very same image (the last transformed one). If I refresh the page, the first images (already transformed) is returned right away, the second one is returned correctly transformed, but then all the other images returned are the same as the one just newly transformed. and it goes on the same for every refresh. not optimal , basically the resquests are "merged" at some point and all return the same image. for reason i don't understand
(When using 'large amount', i mean more than 1)
The ruby version :
get "/:commands/*" do |commands,remote_path|
path = "./public/#{commands}/#{remote_path}"
root_domain = request.host.split(/\./).last(2).join(".")
url = "https://storage.googleapis.com/thebucket/store/#{remote_path}"
img = Dragonfly.app.fetch_url(url)
resized_img = img.thumb(commands).to_response(env)
return resized_img
end
The node js version :
app.get('/:transform/:id', function(req,res,next){
parser.parse(req.params,function(resized_img){
// the transform are done via lovell/sharp
// parser.parse parse the params, write the file,
// return the file path
// then :
fs.readFileSync(resized_img, function(error,data){
res.write(data)
res.end()
})
})
})
Feels like I'm missing here a crucial point in node. I expected the same behaviour with node and ruby, but obviously the same pattern transposed in the node area just does not work as expected. Node is not waiting for a request to process, rather processes those somehow in an order that is not clear to me
I also understand that i'm not putting the right words to describe the issue, hoping that it might speak to some experienced users, let them provide clarifiactions to get a better understanding of what happens behind the node scenes
How can i generate an image of a string that has:
a size in px
embossed effect of the letters in the image
a font
a color
and other less important stuff that i think i can figure out once i achieve whats above like:
rotation of text
drop shadow
basically the user will send a request on how he wants his image to be.
but when i receive the request how should i make use of nodejs to render a png or a base64 url to send it back to the user. is there any libraries or way to achieve this.
i did some previous research and it doesn't seem like there is a frameworks that helps render text with a font and text style like emboss
You can try node canvas implementation: https://github.com/Automattic/node-canvas
Basically you can "draw" anything you want like if you'd be using browser js canvas, but some things may be different
Update - This will cover updating attributes of an image, not pulling text from image and updating that - you may need an image analysis library for that
Use the sharp library to manipulate the image as desired. https://github.com/lovell/sharp
http://sharp.dimens.io/en/stable/
A simple example that resizes (docs will show how to make the changes you want outside of this):
const request = require('request').defaults({ encoding: null });
request.get(imgUrl, params, function (err, res, body) {
sharp(body)
.resize(params.width, params.height)
.toFormat('jpeg')
.toBuffer()
.then((outputBuffer) => {
// outputBuffer contains JPEG image data no wider than params.width and no higher
// than params.height while maintaining quality of image.
let output = "data:" + res.headers["content-type"] + ";base64," + new Buffer(outputBuffer).toString('base64');
return output;
});
The output here will be the base64 image
I am trying to send a GIF image using the bot framework across all platforms. I dont want to use sourceEvent to send custom GIFS across each platform separately. My current code looks as shown below
Hi, first of all , thanks for the fabulous effort in maintaining this library. I want to send a GIF across all channels and read about AnimationCard in the documentation repo
My code looks like this
function onMessage(session) {
var msg = new builder.Message(session).addAttachment(createAnimationCard(session, 'title', 'subtitle', 'text'));
session.send(msg);
}
function createAnimationCard(session, title, subtitle, text) {
return new builder.AnimationCard(session)
.title(title)
.subtitle(subtitle)
.text(text)
.media([
new builder.MediaUrl()
.profile('GIF test')
.url('http://media2.giphy.com/media/FiGiRei2ICzzG/giphy.gif')
])
}
How I get this error saying
TypeError: builder.AnimationCard is not a constructor
at createAnimationCard (D:\bots\fastrivia\index.js:65:12)
at Array.onMessage (D:\bots\fastrivia\index.js:60:58)
at SimpleDialog.waterfallAction [as fn] (D:\bots\fastrivia\node_modules\botbuilder\lib\dialogs\DialogAction.js:131:25)
at SimpleDialog.begin (D:\bots\fastrivia\node_modules\botbuilder\lib\dialogs\SimpleDialog.js:15:14)
at Session.beginDialog (D:\bots\fastrivia\node_modules\botbuilder\lib\Session.js:180:16)
at routeToDialog (D:\bots\fastrivia\node_modules\botbuilder\lib\Session.js:421:23)
at D:\bots\fastrivia\node_modules\botbuilder\lib\Session.js:449:29
at D:\bots\fastrivia\node_modules\botbuilder\lib\Session.js:505:25
at ActionSet.recognizeAction (D:\bots\fastrivia\node_modules\botbuilder\lib\dialogs\ActionSet.js:44:9)
at D:\bots\fastrivia\node_modules\botbuilder\lib\Session.js:501:43
It seems there is no AnimationCard under cards package in the botframework lib when I checked under node_modules. What is the best way to send a GIF across all platforms on the bot framework?
I believe the problem here is that the bits for using AnimationCard in Node.js are not yet public so I believe you will need to install the pre-release version of BotBuilder:
npm install --save botbuilder#next
your code is perfectly fine, just replace the new builder.MediaUrl() with an object. It's often the case, that structures that as simple as MediaUrl have to be directly initialized and do not have a constructor in the framework.
function createAnimationCard(session, title, subtitle, text) {
return new builder.AnimationCard(session)
.title(title)
.subtitle(subtitle)
.text(text)
.media([{ profile: 'GIF test',
url: 'http://media2.giphy.com/media/FiGiRei2ICzzG/giphy.gif'
}])
}
So I have two PNG images, both non-transparent 24bpp.
One image contains a rainbow, other one contains a single line of text:
I do the same thing with both of them:
var gm = require('gm').subClass({imageMagick: true})
gm("./sources/source.png").bitdepth(24).write("test.png", function(){
console.log("test.png")
});
gm("./sources/source2.png").bitdepth(24).write("test2.png", function(){
console.log("test2.png")
});
where gm is this
And I set both to 24bpp explicitly
In result I have two images with different bit depth:
In some cases I also had 32bpp image.
How can I make it create only 24bpp image (discard alpha channel if needed).
Also, I don't want to create jpgs.
Thanks to #mark-setchell, I could force bit depth. I did it this way in Node:
gm("./sources/source.png")
.out("-define")
.out("png:color-type=2")
.write("test.png", function(){
console.log("test.png")
});
out() is an undocumented method but it basically helps you add custom parameters to commandline. Notice that
.out("-define png:color-type=2")
won't work, it only works if you pass each parameter in individual .out() call
.bitdepth(24) doesn't seem to affect output at all, probably because I did .subClass({imageMagick: true}) above.
My suggestion is to try using -define to set the variable png:color-type=2. As you worked out, and kindly shared with the community, it is done as follows:
gm("./sources/source.png")
.out("-define")
.out("png:color-type=2")
.write("test.png", function(){
console.log("test.png")
});
I'm writing simple app that downloads JPEGs images from Flickr API, and then process them.
All I want to do, is to pick 4 random pixels from each image and save the HEX values.
Is it possible at all? I read a lot of graphicmagick documentation, but can't find a way to do this.
Whats the best way to decode JPEG and get this values? I tried a few plugins but neither can do this by default...
Take care!
https://npmjs.org/package/get-pixels seems nice for that:
var getPixels = require("get-pixels")
getPixels("lena.png", function(err, pixels) {
if(err) {
console.log("Bad image path")
return
}
console.log("got pixels", pixels.shape)
})