Load images from local directory in Fabric - node.js

I am trying to load images from a local folder using fabric.js in node.
There seems to be very little up to date documentation on how to do this.
Most example use fabric.Image.fromURL(imageurl)
As far as I'm aware, this only works for web urls, not local paths.
Correct me if I'm wrong, but I have tried
fabric.Image.fromURL(imgpath, (img) => {
...
}
which throws the error Coul not load img: /image/path/img.jpg
Where
fs.readFile(imagepath, (err, i) => {
...
})
will successfully read the file, i will be a buffer.
What is the correct way to load a local image.
I know there is a fabric.Image.fromObject but I have no idea what type of object it wants.
I am currently loading the image into a 2d canvas object, converting it with canvas.toDataURL() and putting that url into fabric.Image.fromURL() which works but converting the image to a url is very slow due to large images. There must be a way to load the image directly and avoid this problem.

If you are using fabricjs 3+, that uses the new jsdom, you can use the file urls!
fabric.Image.fromURL(file://${__dirname}${filepath});
Check here on the fabricJS codebase how they handle reading files in browser and node for the visual test images
https://github.com/fabricjs/fabric.js/blob/master/test/lib/visualTestLoop.js#L139

try this one:
fabric.Image.fromURL(require("../../assets/mockup/100.png"), (img) => {...}

Related

Get exact dimensions of resized image using Sharp

I have a Cloud Function that resizes an image uploaded to Cloud Storage using Sharp. Everything works, but I'm trying to find a way for Sharp to include metadata of the exact height and width of the new image. I could make a new function that uses other npm packages to download the image from the url and get what I want, but I'm curious to know if there is a way for Sharp to do that as well?
just include "withMetadata()"
sharp('input.jpg')
.withMetadata()
.toFile('output-with-metadata.jpg')
.then(info => { ... });
you can find the documentation here
https://sharp.pixelplumbing.com/api-output#withmetadata

Efficient media transfers in Node and Electron

As a toy project for Electron, I'm trying to rewrite a WPF media management application and would like to get up to speed on what would be the best means of loading media (namely images, but later video) through node's fs and get it into a webpage for Electron to render.
Currently I've got a basic working setup using Base64 encoding:
function getImage(imageID, success) {
fs.readFile('f:/pictures/2.jpg', function(err, data) {
if (err) throw err;
success(Buffer.from(data).toString('base64'));
});
}
and rendering it like so in my html:
api.getImage(0, (result) => {
$('#mainContent').append('<img src="data:image/jpeg;base64,' + result + '" />');
});
This doesn't strike me as the most efficient method to do so. Base64 conversions are helpful for cross technology boundaries, but not the most efficient way to do things.
Some other considerations I had:
Host the file directory via node so I can link to the file directly from my webpage (this is not ideal as files can come from anywhere on the local filesystem)
Use node to copy the file from the filesystem to the served directory so I can link to it via html (this would be slow: disk IO and whatnot)
Pass the raw file buffer back to the webpage somehow (this seems like it should be the way to go, but not sure how to render it in "traditional" html)
Considering that I may want to process 50 or 100 images or so at a time (including possible resizing for thumbnail views: something I was able to do in WPF effectively by optimizing the decoding for the BitmapImage), what would be the general approach to follow?
To clarify, I'm not asking so much about async/process blocking as I am the data transfer itself.

Save an image file into a database with node/request/sequelize/mysql

I'm trying to save a remote image file into a database, but I'm having some issues with it since I've never done it before.
I need to download the image and pass it along (with node-request) with a few other properties to another node api that saves it into a mysql database (using sequelize). I've managed to get some data to save, but when I download it manually and try to open it, it's not really usable and no image shows up.
I've tried a few things: getting the image with node-request, converting it to a base64 string (read about that somewhere) and passing it along in a json payload, but that didn't work. Tried sending it as a multipart, but that didn't work either. Haven't worked with streams/buffers/multipart all that much before and never in node. I've tried looking into node-request pipes, but I couldn't really figure out how possibly apply them to this context.
Here's what I currently have (it's a part es6 class so there's no 'function' keywords; also, request is promisified):
function getImageData(imageUrl) {
return request({
url: imageUrl,
encoding: null,
json: false
});
}
function createEntry(entry) {
return getImageData(entry.image)
.then((imageData) => {
entry.image_src = imageData.toString('base64');
var requestObject = {
url: 'http://localhost:3000/api/entry',
method: 'post',
json: false,
formData: entry
};
return request(requestObject);
});
}
I'm almost 100% certain the problem is in this part because the api just takes what it gets and gives it to sequelize to put into the table, but I could be wrong. Image field is set as longblob.
I'm sure it's something simple once I figure it out, but so far I'm stumped.
This is not a direct answer to your question but it is rarely needed to actually store an image in the database. What is usually done is storing an image on storage like S3, a CDN like CloudFront or even just in a file system of a static file server, and then storing only the file name or some ID of the image in the actual database.
If there is any chance that you are going to serve those images to some clients then serving them from the database instead of a CDN or file system will be very inefficient. If you're not going to serve those images then there is still very little reason to actually put them in the database. It's not like you're going to query the database for specific contents of the image or sort the results on the particular serialization of an image format that you use.
The simplest thing you can do is save the images with a unique filename (either a random string, UUID or a key from your database) and keep the ID or filename in the database with other data that you need. If you need to serve it efficiently then consider using S3 or some CDN for that.

Composite images in Graphicsmagick

I'm trying to request an image from an API and "paste" it on top of another image. In Photoshop, I would paste the image into a new layer and then merge the layers. I can accomplish this with Graphicsmagick using gm's composite().
gm().command("composite")
.in("path/to/topImg.png")
.in("path/to/bottomImg.png")
.toBuffer('PNG', function(err, buffer) {
if (!err) {return buffer;}
});
However, composite only takes file paths. So let's say I want to get the logo from http://www.google.com. I could save the image, use it in the code above, and then delete it. What I'm looking for is a way to accomplish this without having to save the image to disk first.
You can use URL directly as image path, without downloading and saving it
gm()
.command("composite")
.in("http://someurl...")
.in("http://someurl...")
.toBuffer('PNG', function(err, buffer) {
if (!err) {return buffer;}
});
But GraphicsMagick uses the HTTP support from libxml2, which does not currently support HTTPS. So if you want to download images over HTTPS you will need external program.

Optimal way to define the correct size of a SVG image

When creating a SVG image you have to set width,height and position otherwise it will not be rendered.
How do I read them from the original image?
Using Dart I first load the html image and after it's loaded I get the size and then define the SVG image and use the info I got before. This is a bit cumbersome and I wondered if there is another way.
The dart code looks like this:
ImageElement img = new ImageElement(src:'2.jpg'); //401x600
img.onLoad.listen((e) {
svg.ImageElement image = new svg.ImageElement();
image.setAttribute('x', '0');
image.setAttribute('y', '0');
image.setAttribute('width', img.width.toString());
image.setAttribute('height', img.height.toString());
image.getNamespacedAttributes('http://www.w3.org/1999/xlink')['href'] = '2.jpg';
});
There seems not to be a more convenient method (also not in JavaScript except when you use jQuery or another framework that includes methods for this).
Just create a method yourself and reuse that method for each image you load.

Resources