Closed ErisDS closed 5 years ago
Doing any form of image processing client-side is a definite no from my point. I've worked on a project before which required resizing an uploaded image in canvas, but the browser (iOS 7 Safari in this case) had a file size limit of approx 2mp. I couldn't even process photos from the devices own camera. :)
Processing images that the browser couple code with was also super slow.
Edit:
The maximum size for a canvas element is 3 megapixels for devices with less than 256 MB RAM and 5 megapixels for devices with greater or equal than 256 MB RAM. ~ Scroll to "Know iOS Resource Limits"
I know this is iOS specific, but it's a large audience.
I use cloudinary for image processing on my blog and my (in development) node art gallery. The Node API is fantastic and works, the only problem is that by being a third party service and so could be better served as a plugin (or app in Ghost terms).
For using a pure nodejs library i guess that JIMP can be an option.
It can actually be useful for creating the Multiple image sizes @ErisDS mentioned.
@mattiascibien JIMP is an awesome find - thank you! It looks like it has most of the features we need - crop, resize and quality that will help us generate images.
This just leaves the exif device orientation issue, as I don't think it will solve that.
Would be great if someone could try JIMP out and see how well it works.
@ErisDS I'll set up a simple repo on my profile and share my test with the Ghost team. Always wanting to learn more node. :+1:
EDIT: for exif https://www.npmjs.org/package/exif-rotaten https://www.npmjs.org/package/fix-orientation and https://www.npmjs.org/package/jpegorientation. (I'll check those tomorrow since it is almost midnight here)
EDIT 2: Maybe with just a node exif parser and JIMP we can manipulate the image as we want.
While I understand the need for a "one true place" for a discussion on images, the features discussed here are momentous and will take ages to implement.
I wonder if an agile approach wouldn't be more appropriate here, so we can have quick time-to-market with image related issues? What's more, some requirements are far less common than others. In other words, I don't think other issues need to be closed due to this 'central discussion place'.
My particular case is that I user OmniGraffle to generate diagrams. I export them as PNGs, with may having 200px width. Ghost stretches these images, so pixilation appears. It makes little sense to add white margins to fit the blog width, as you don't want these margins when sharing these diagrams on social networks (like Pinterest).
All I need is a way to tell Ghost not to stretch diagrams. As far as implementation goes, this is nowhere on par with "providing themes various image sizes to display in different places" or many other ideas proposed here.
@Izhaki what you're describing is how the theme handles the images, not Ghost itself. If you don't want full-width images, you can use a different theme or modify the one you're using (I assume Casper).
This is intended as a place to gather and share knowledge about what solutions are available for processing and manipulating images in node. There may well be many smaller issues to implement solutions in future once we've decided on a direction - but it helps to keep all of the problems we have described in one location so that we can evaluate potential solutions.
Hey guys,
I decided to try and tackle the EXIF problem, so I grabbed jimp and built a small demo. It's running on node and is pure JS, so no 'hard to install' dependencies. Also, I'm thinking of turning it into express middleware. Any thoughts?
Demo: https://imageware.herokuapp.com/ Example images: https://github.com/recurser/exif-orientation-examples Repo: https://github.com/ekulabuhov/imageware
Hey @ekulabuhov this looks awesome! The main thing with making it middleware is would it work with the busboy setup in Ghost or would we need to change that?
I'd love to see a PR adding your new middleware to Ghost! :grinning:
Thanks @ErisDS! The busboy setup shouldn't be a problem because I'm using multer at the moment, which is a simple wrapper around busboy. What bothers me is the performance of this solution. The implementation is way too slow with real photos. Decoding and encoding JPEGs takes a big chunk of time from what I see. Nodejs is not a great candidate for long blocking operations from what I gathered.
I've been thinking about this quite a lot, off and on, over the past couple of months. It's such a killer that we haven't got basic image processing available to us, and I think we're going to need to be super creative with a solution if we move forward.
I tested out @ekulabuhov's demo and whilst it's not fast, it wasn't terribly slow either, and the laws of tech say it should only get faster, right? So it might not be a complete loss.
In addition, from reading through the (very minimal) documentation for blueimp it seems they support some resizing in the client - but whether you still need a backend or whether it can be done using canvas in browsers that support it is not 100% clear.
What blueimp definitely can do, is show a preview of the image being uploaded. I think we could do something clever and combine this with server-side workers. We can show the image before it uploads, and then after it uploads kick off a task to do the necessary processing. The user doesn't need to wait for it to finish, they can carry on working with the preview version.
If none of that works, there are definitely 3rd party services we could offload the work to over an API, and that approach could work very well.
I think there's more investigation and experimentation to be done, but I believe there is a solution out there somewhere!
I'm very interested in this feature. jimp seems like a pretty good solution. A PureJS solution feels like the most appropriate direction for this project.
As long as the chosen library is wrapped in some API that represents the features Ghost needs (crop, resize, etc) then a more appropriate library could always be dropped in later.
Attempting one feature to see if jimp will do the trick could be a worthwhile effort. "Multiple image sizes" is a good candidate as it only requires resize, and could easily fall back to presenting the original image until the processing is complete (if the processing does indeed take a significant amount of time).
I'm eager to help out in any way possible to see this land in Ghost.
Yes I'd love to see a demo which used blueimp's preview to mask the upload process taking a while. I really think the solution is out there it just needs someone with enough time & interest to have a play around with it and see what they can come up with.
Jimp looks good and should do the trick. At the moment I'm having to locally batch resize photos taken from my camera, otherwise I'll be uploading 2mb per photo!
I proposed a way we could optimize images at #5487
I would like to submit this new, free and open source api into consideration: ResponsiveBreakpoints.com via Cloudinary. I use the web gui for other non-ghost work, and it is great.
I think it would be better to handle the image processing internally, on the Ghost server itself just in case the API dies on us one day.
@nii236 I've never actually gotten it running myself (that's a wee bit above my head at the moment) but the tool is open sourced on github
@JamesJosephFinn the ResponsiveBreakpoints tool still goes through Cloudinary's service so it's not suitable for anyone who doesn't want to set up, use & pay for that service.
We're looking at making the image processing in Ghost modular so that users can swap in the processor of their choice similar to the modular fileStorage system we currently have. Once at that stage it should be possible to create a Cloudinary module, possibly even one that uses their ReponsiveBreakpoints tool.
I'm using JIMP on my node project as well and it works like a charm. What's the verdict on that? It might not solve all of the issues, but at least it solves 80% of it.
Sry for bringing this up, but this could be a good alternative. I'm using sharp in most of my node projects. Similar to jimp it's largely written in c/c++. All the needed features should also be possible with sharp. In comparison to jimp it's around 30x faster http://sharp.dimens.io/en/stable/performance/
Hi everyone, I was recently alerted to this discussion and as the maintainer of sharp, mentioned as a possible solution to all of the original requirements, may be able to help.
I love the all work that's been done to make ghost
as easy as possible for newcomers to install so completely understand why adding support for image processing needs to be done carefully.
To avoid the magick-esque problem of having to install global runtime dependencies, sharp
downloads a tarball containing a pre-compiled libvips
and its dependencies into the local node_modules
at npm install
time. These are provided for Linux (x64 and ARM), Windows (x64) and OS X.
The work to avoid a C++ compilation step for as many people as possible via node-pre-gyp
is being tracked at https://github.com/lovell/sharp/issues/186.
Hey guys, tried out sharp and damn, it's fast!
I didn't have much trouble compiling it on both OSX and Heroku. Win32 is not supported and I don't have Win64 to test it (but should be supported according to sharp documentation).
As for API, I think implementing it as an middleware that intercepts all the .jpg, .png requests could be a good solution. We could append parameters to the image URL to specify the kind of transformations we want applied to the image, for example:
http://
Links to the new updated demo are still the same: Demo: https://imageware.herokuapp.com/ Example images: https://github.com/recurser/exif-orientation-examples Repo: https://github.com/ekulabuhov/imageware
Also sharp has a very cool API. It includes the EXIF decoder and a rotate() method that automatically fixes the EXIF issue.
Has anyone had a go at implementing sharp with Ghost yet?
Yes 😁
I worked on a demo, we are formulating plans around functionality for after we ship 1.0 😍
I've kept this issue in mind for a long time and I finally made a HTTP API that does this: https://github.com/lacqueristas/lumin
gm
for the manipulation?lenses=original,thumbnail,monocromatic
)Hi all, please add history images navigation in the editor. The goal in select old image in the new posts without uploading it but just select previus.
Thanks LP
Any updates on this? It's been 3 years since the first request was submitted.
Hi @ErisDS ! Are there any plans in near future on the agenda to add image processing (especially image rotation based on exif after upload)?
yes, should give priority to image processing feature @ErisDS ,any plans about this in further build?
Is there still development going on for Ghost ? Any plans/roadmap for the image optimization? Thinking of switching to other blogging platform, because of that.. really drops performance by a factor.. Cheers.
Ran into this issue aswell. Are there updates?
It's definitely on the roadmap but there are higher priority issues at the moment. Any updates will be added to this issue.
@ekulabuhov Do you have any info on how to setup sharp as a middleware layer to resize based on image url parameters?
I have a demo here: https://github.com/ErisDS/Ghost/commit/fb0a0fbcd756b7326fde0c21513b70ae7a698c7d.
Prebuilt binaries are now available in sharp v0.20.0.
Can't wait to have this feature built in, @ErisDS any change it would get included in the next release?
Hello, I am a happy ghost user and node programmer. The features defined in this issue would be awesome to have in the official ghost release. Is there a current roadmap of when this might be implemented? Is there a way I could look into contributing the functionality myself?
Any thought to accomplishing this with server side image resizing + caching? For instance: https://stumbles.id.au/nginx-dynamic-image-resizing-with-caching.html
If Ghost were able to determine that it is serving a thumbnail, preview, or full-sized image, it could simply pass the size in the URL, and have nginx process the image manipulation via a location proxy on the /content/images/
folder.
Interesting idea but that would require nginx in the first place. I don’t think such a feature should be implemented by requiring a specific webserver. Many people may be using apache or lighttpd or something else. Or they may be using a hoster without router access.
Has there been any updates or work being done towards this end? I do have people that are intrigued by using Ghost, but I know they are not really the type to resize images themselves. If you are looking for help, let me know.
Also, is there thoughts or options of a media browser situation?
I've been tracking this issue for years now and I'm surprised it hasn't been solved yet. In terms of client side resizing, I've used picajs with great success.
It's very much on our radar and has been discussed internally a number of times but no quick-win has emerged so far. Unfortunately we don't have the resources to tackle it just yet, it's a very large project to implement well and in a way that works across the huge variety of Ghost install environments and use-cases.
You can add your vote/input to the related feature requests on our Ideas board that we'll be referencing when we do get to the design & implementation stage:
https://forum.ghost.org/t/automatic-thumbnailing-resizing-of-image-uploads/475 https://forum.ghost.org/t/media-library-manage-all-files-in-one-place/675
no quick-win has emerged so far
Put in my votes.
I have wanted to use Ghost as my main blog platform, but I have a problem with a PaaS that doesn't acknowledge the main focus for our Search Engine brethren - Well structured and a speedy website.
To that end, a minimum of resizing an image - or option at least to size to a size that can be turned on or off seems like a good starting point.
Personally, I can write these things myself, but if I do I am more likely to utilize a cloud function implementation.
From a starting point, perhaps start with a solution that can be used on Google (Pro) that supports your hosting solution adding a hook that extends into other services and grows with time.
It may not give everyone everything and serve everyone at once, but it is a starting point.
Also, thank you for creating this platform. I really do prefer using Markdown for writing posts.
Good points, the success of any platform is listening to its users because without the users there would be no product.
This thread has become a rant and is no longer useful, so I'm restricting it to maintainers.
I'll summarise the answers to the questions which keep coming up:
Why don't you just do it already? If it was that straightforward, we would. It isn't straightforward at all, and to date there's still no good solution.
Then howcome [other platform] manages to do it so easily? Because it is either centralised, or written in PHP. Both of which make solving this very easy.
Omg I can't believe it has been 5 years and nobody has fixed this, what a joke The way open source works is that people who care about an issue write code to solve it. If you care about this issue, please write some code to solve it.
I'm not going to write any code, I don't have time for that! There's your answer to why this issue has been open 5 years.
So what now? We'll work on it as soon as we can. Right now there are other things which are more important to us.
But: Anyone else is more than welcome to contribute to this if they want to see it happen sooner rather than later. Hannah has posted very detailed info above, and even a prototype implementation :)
This is also a great read: https://nolanlawson.com/2017/03/05/what-it-feels-like-to-be-an-open-source-maintainer/
Opened an issue in sharp
repository regarding image being transformed even though no compression parameters were specified - https://github.com/lovell/sharp/issues/1360 . We have a workaround for it but would be nice to figure it out :thinking:
Cropping example here: https://github.com/tryghost/cropper
FYI: We have merged and released (Ghost 2.1.0) the first iteration of image processing using sharp
. sharp
is very good maintained, offers all the functionality we need and is easy to install since 1.20.0.
This issue replaces (at least for now) issues #1688, #1734, and #4333 as the one true place to discuss all of our image processing needs in Ghost, and the possible solutions.
Please note that this issue is not about storing or managing uploaded images, only about processing them on the way to the server ;)
Image Processing Features
When it comes to uploading images in Ghost, there are a few issues we need to be able to resolve:
Multiple image sizes
There are a few ideas for Ghost features that have been floating around forever that would require us to be able to generate multiple sizes of any one image:
The current state of Image Processing
Ghost doesn't currently have any form of image processing built in because we haven't yet found a good solution for doing this. Pretty much all node libraries for image processing have imagemagick as a dependency - and that is not a viable solution for Ghost due it it being a c++ program that's ridiculously hard to install. This leaves us with a few alternative options:
node-pre-gyp
which is the same thing we use to install sqlite3Several of these solutions have been discussed or covered in the comments on #1688 and #1734, so they are worth a read ;)
What we know so far
In summary, there's quite a bit of research and investigation to be done to come up with a couple of potential solutions for image processing in Ghost, and weigh up their pros and cons. I don't think there is going to be an obvious winner, but we need to gather together a clear picture of what's available to us so we can make a decision. The key thing is that we only* need crop, rotate, resize, exif modification & some optimisation tools - we aren't trying to detect faces or anything!
Anyone and everyone is welcome to jump in on this, with any solution they can come up with - I'm not looking for one person to do all the research but rather for people to volunteer their suggestions.
* I know I know only... haha