Open ghost opened 7 years ago
We definitely need to be non blocking on file reads. My suggestion would be to do the following and just giving jimp a buffer:
const buffer = fs.readFileSync('./path/to/your/file.png');
const image = new Jimp(buffer)
image.resize(...)
Is this something we can do currently? I REALLY need synchronous operations and I'm struggling to find a way.
EDIT: After testing and getting really confused for ages I finally realised it seems like new Jimp(buffer)
still does thing asynchronously, so no, I can't do what you've shown here. Well that sucks. I guess I'll have to create some super jank counter system to know when all of my images have loaded :|
My workaround on this for now is just to store an array list of operations that need working through, and as the async promises return I'm just fetching another item from the list to perform operations on. Really need sequential operation for my needs since I'm working on thousands of image files, don't really want to load them and be editing them all at once.
@mindinsomnia Nice workaround. My "solution" was to have two separate loops. The first one determines which (and how many) images need to be loaded, the second starts them all loading. Then, in the callback for the image loading completion I make it decrement the counter. If the counter has reached 0, that means all images have loaded for this job and processing can begin. It's messy and awkward and would be 6000 times easier with synchronous processing. I just wanted to whip up a quick image processing script, but no, it couldn't possibly be that simple...
I'm really not sure why people are so keen to get rid of synchronous processing completely when it's only beneficial with certain types of user-facing programs, and greatly increases code complexity for a lot of other types of programs.
@hipstersmoothie Can we re-open this issue? The solution provided doesn't actually work.
If you only want to decode an image (to get an ImageData
object containing a width
, height
and Uint8ClampedArray
) and not use any other methods, this is the workaround I found when trying to do this in my ImageData package.
You will need know the mime type of your image (I used mime-kind since I needed to be able to check both file paths and Buffers, but there are a lot of packages that do this), and provided you have that, you can directly access the image decoders:
const type = 'image/jpeg'
const buffer = fs.readFileSync('./path/to/your/file.png')
const imageData = jimp.decoders[type](buffer)
Extending the @andreekeberg solution. If you need to process images synchronously and use the Jimp
object and its methods, this worked for me (Jimp version 0.16.1):
// Reading the file
const type = 'image/png'
const buffer = fs.readFileSync('./input.png');
const imageData = jimp.decoders[type](buffer);
const baseImage = new Jimp(imageData);
// ... process the image
// Writing to file
fs.writeFileSync(`./result.png`, Jimp.encoders[type](baseImage));
Seems like a candidate for cleanup up weird stuff we do in our constructor @nopeless
We should never support sync
This will run in browsers/servers where response time is crucial
Imo, jimp's constructor should only accept a uint array of either rgba or rgb. any other means (filename, url, number array, uriencoded, jpeg) should be a method
imo we shouldn't even expose the constructor
import * as jimp from 'jimp';
const image = await jimp.read('/my-image.png')
const image = jimp.create(buffer)
const image = jimp.create({ height, width })
We should never support sync This will run in browsers/servers where response time is crucial
I disagree. This might run on a server where response time is critical, but it's certainly not the only use-case. I have extensively used Jimp for offline processing tools. For offline tools where you only care about quickly writing the tool and not about whether it blocks UI, synchronous programming is just easier. There's less to think about and it's harder to screw yourself over.
Then again, async-await makes it much easier than it used to be, so maybe it's not such a big deal. I just know there have been situations where it sucked that I was forced to use async-await. Certainly it's a significant hurdle to beginners.
Having a way to create a jimp instance from a buffer easily seems like a good win. For loading files I suspect we will go full async.
We should never support sync
This will run in browsers/servers where response time is crucial
Just to add my 5c, my use case is using this in a test framework where I'm dealing with raw images, and when those images don't match I write them out as pngs, to make image comparison easier.
I'm currently running 1404 tests in ~25 seconds, so performance is more than sufficient, and I'd personally favour ease of writing tests over more speed.
We should never support sync
This will run in browsers/servers where response time is crucial
Just to add my 5c, my use case is using this in a test framework where I'm dealing with raw images, and when those images don't match I write them out as pngs, to make image comparison easier.
I'm currently running 1404 tests in ~25 seconds, so performance is more than sufficient, and I'd personally favour ease of writing tests over more speed.
I am guessing that is a CI server (or modern hardware).
I think what you brought is a valid point. Speed may not be the biggest concern
We should never support sync This will run in browsers/servers where response time is crucial
I disagree. This might run on a server where response time is critical, but it's certainly not the only use-case. I have extensively used Jimp for offline processing tools. For offline tools where you only care about quickly writing the tool and not about whether it blocks UI, synchronous programming is just easier. There's less to think about and it's harder to screw yourself over.
Then again, async-await makes it much easier than it used to be, so maybe it's not such a big deal. I just know there have been situations where it sucked that I was forced to use async-await. Certainly it's a significant hurdle to beginners.
Modern node allows top level await, making async programming even easier.
One reasoning might be that a previously sync function had needs to be migrated to an async function and providing sync methods will allow developers to upgrade to latest without much hassle
I need this to block the main thread for reasons.
Could I maybe use fs.readFileSync and somehow turn that into a data URL?