nodejs choosing between JIMP and MOZJPEG - node.js

I was wondering if there is a blaring reason to use jimp vs. imagemin-mozjpeg for compressing jpegs (I am already using both imagemin and jimp in my project already, imagemin-webp to serve next gen images, and jimp to convert pngs to jpegs in rare cases) So I am more looking for reasoning that is based on the following:
Performance
Reliability (I have noticed that there are some JPEGs mozjpeg has trouble with and fails on. specifically ones that I have used GNU Image Manipulation Program [GIMP] with.)
However, if someone has good reasons that don't align with the two aforementioned I would still like to hear them.
Heres some quick links to the NPM packages mentioned if anyone needs them:
imagemin-mozjpeg
jimp

Performance
imagemin-mozjpeg uses mozjpeg to process images. And mozjpeg itself is made using C language. While jimp uses javascript to process it.
As mention in the main repository jimp:
An image processing library for Node written entirely in JavaScript, with zero native dependencies.
We know the difference in performance between Javascript and C.
Reliability
I do not want much opinion in this section. but we can see directly how the statistics of each repository.
mozjpeg:
Star: 4.1k
Open Issues: 76
Closed Issues: 186
jimp:
Star: 10.3k
Open Issues: 157
Closed Issues: 430
I do not side with either. They all have worked well. I really appreciate the work of the maintainers and contributors of the library library.

Yes, and it goes far beyond the performance of the compression process (ie how long it takes to compress an image, which is also important) or the relative activity of development of the library (which is arguably less important).
I highly recommend reading Is WebP really better than JPEG? (and this discussion), which shows that even among JPEG compression libraries, the implementation can have a significant impact on compression ratio.
In short, MozJPEG produces jpeg files that are 10% smaller than jpeg files produced by the reference JPEG implementation (libjpeg). Even more interesting, for images larger than 500px, MozJPEG actually produces jpeg files that are smaller than WebP.
This leads to an interesting question. It will depend on exactly your use case and priorities, but it might actually make sense to simplify and use MozJPEG for everything, and ditch WebP entirely.
Looking forward, AVIF might make sense as a true next-gen format (delivering 30% smaller images), but browser support is "coming soon". Alternatively, JPEG XL also looks promising, but the standard hasn't been finalized yet. HEIC is problematic and I wouldn't count on wide support.
Warning regarding jimp:
As jimp is implemented in pure JavaScript, all image operations end up blocking the JS thread. This is catastrophic in node.js.
You must use the new Worker Threads API manually to run jimp on a thread.
Finally, a warning regarding selecting image manipulation libraries generally in the node.js world:
From what I've seen, a majority of them end up writing temp files to disk and then invoking a child process to do the actual work, and then read the result back in. (eg something like child_process.exec('imageresizer -in temp/file.jpg -out temp/resized.jpg')).
This is not an ideal way to do this, and it may be especially surprising when the API looks something like var img = await resizeImg(buffer), which does not look like it writes to disk.
imagemin is one such library; I would avoid it where performance matters.
Instead, search for modules that implement bindings to native code on the libuv thread pool. This will usually be the most performant way to work with images, since the operations happen on a thread in your node process and with minimal memory copying — and no disk I/O at all.
I've never used it, but node-mozjpeg looks like a good candidate.

Related

jpegoptim vs jpegtran vs mozjpeg

I found two slightly conflicting blog posts on this matter, here I summarize:
jpegoptim and jpegtran perform identically and produce identical results, while mozjpeg takes twice as long for very marginal filesize savings
mozjpeg takes approx 1.7* the compute time and results in a roughly proportional benefit in filesize savings compared to jpegtran
Adding to confusion, this
Reddit thread suggests that mozjpeg uses the same algorithm used in jpegcrush, and that jpegcrush is a wrapper for jpegtran... so we've come full circle? I can only assume that those Reddit comments are wrong, can anyone confirm that?
MozJPEG library uses one algorithm inspired by jpegcrush (optimized progressive scans), but technically it's a completely new implementation.
MozJPEG library is a drop-in replacement for the popular libjpeg, so almost every JPEG-related tool can be compiled in "regular" and "MozJPEG" flavors.
There exists a "regular" jpegtran and a MozJPEG version of jpegtran. That's the same program, but the MozJPEG version has different default settings and performs extra work to compress better.
Similarly, jpegoptim is usually built with stock libjpeg, but it's also possible to build it with MozJPEG's version of libjpeg (e.g. ImageOptim does it).
There are two ways to use MozJPEG:
lossless (take an existing JPEG file and make it a bit smaller). That's what MozJPEG's jpegtran does.
lossy (create a new JPEG file from uncompressed pixels, with higher quality/filesize ratio). That's what MozJPEG's cjpeg does, and other tools like jpegoptim can be made to do with MozJPEG.
Both modes of operation are slower than vanilla non-optimizing libjpeg. Lossless optimization does less work, but also achieves smaller gain.
More precise speed analysis is here: https://libjpeg-turbo.org/About/Mozjpeg
Note that "slow" here is relative. In absolute terms it compresses several megapixels per second, so it may be fast enough for most applications.

Is there a binary kind of SVG?

It just seems to me that when writing code for dynamic data visualization, I end up doing the same things over and over in different languages/platforms. Now if I had a cross platform language(which I do) and something like a binary version of SVG, I could make my code target that and use/create interpreters for whatever platform I currently need to use it on.
The reason I don't want SVG is because the plaintext part makes it too slow for my purposes. I could of course just create my own intermediary format but if there is something already out there that's implemented by various things then the less work for me!
Depending on what you mean by “too slow”, the answer varies:
Filesize too large
Officially, the closest thing SVG has to a binary format is SVGZ, which is a gzipped SVG file with the .svgz extension. All conforming SVG viewers should be able to open it. Making one is simple on *nix systems:
gzip yourfile.svg && mv yourfile.svg.gz yourfile.svgz
You could also try Brotli compression, which tends to have smaller filesize at the cost of more compression time.
Including other assets is inefficient
SVG can only bundle bitmaps and other binary data through base64 encoding, which has a fair amount of overhead.
PDF can include “streams” of raw binary data, and is surprisingly efficient when programmatically generated.
Parsing the text data takes too long
This is tricky. PDF and its brother, Encapsulated PostScript, are also old, well-supported vector graphic formats. Unfortunately, they too are also text at their core, with optional compression.
You could try Computer Graphics Metafiles, which can be compiled ahead of time. But I’m unsure how well-supported they are across consumer devices.
From a comment:
Almost nothing about the performance of SVG other than the transmission cost of sending it over a network is down to it being plaintext
No, that's completely wrong. I worked at CSIRO using XML for massive 3D models. GeoScience Australia did a formal study into the parsing speed - parsing floating point numbers from text is relatively expensive for big data sets, compared to reading a 4 or 8 byte binary representation.
I've spent a lot of time optimising my internal binary formats for Touchgram and am now looking at vector art.
One of the techniques you can use is a combination of
variable-length integer coding and
normalising your points to a scale represented by integers, then storing paths as sequences of deltas
That can yield paths where often only 1 or 2 bytes are used per step, as opposed to the typical 12.
Consider a basic line
<polyline class="Connect" points="100,200 100,100" />
I could represent that with 4 bytes instead of 53.
So far, all I've been able to find in binary SVG is this post about a Go project linking to the project description and repo
Adobe Flash SWF files may work. Due to its previous ubiquity, 'players' and libraries were written for many platforms. The specifications were open and license permitting. For simple 2D graphics, earlier, more compatible versions would do fine.
The files are binary and extraordinarily small.

Image size optimisation in Linux

There is a Yahoo "Smush.it" service that allow to optimise image size.
I am looking for alternative way to reach the same goal using Linux application.
A lot of images need to processed and uploading them manually one by one seems not a good idea.
How such can be done in Linux ?
For jpegs I use JPEGmini and from what I tested it's the one with the best results keeping the same visible image quality while reducing a lot of the size, they have a server version for Linux which is not cheap and I never used.
There's also Mozilla's mozjpeg which you can use directly from the terminal, but it also reduces image quality.
In some tests I did, mozjpeg gives smaller files (not much) than JPEGmini's, but with lower image quality.
If you need to reduce pngs, you could try Trimage or some of the alternatives listed on the same link.
Smush.it's FAQ lists all the tools they are using in their service.

Producing Vector Graphics Movies with something like Nodebox or Processing

I like the idea of Nodebox and Processing, and would like to generate movies to visualize some data/algorithms. However, Nodebox exports extremely bloated Quicktime files with frame by frame images, and Processing only exports Java applications. I want to be able to export movies that don't take a Gigabyte a minute of disk space. Perhaps something like SVG animations or Actionscript which stores the vector graphics definition of the animation rather than frame images would be better. Is there a framework that is as easy to program as Nodebox and Processing and can export "lean" movies?
Have you tried the MovieMaker library that ships with Processing ?
Also, it should be fairly simple to save multiple frames using saveFrame().
This is option have a couple of advantages:
If your sketch crashes at some point, you still have all the frames up to that point (unlike writing a .mov file)
It's fairly simple to put the frames back into a video file, but you also have control over playback speed and can easily do a bit of editing if needed.
You can try to a sequence of PDF file using createGraphics() to get vector output, but I'm not sure how stable/feasible this option is.
They are changing the way this works moving towards 2.0 too, as they are moving to GSVideo over Quicktime...
Daniel Shiffman posted about it recently on his blog, but it's the only place I've heard about any changes to post-2.0 tactics (though he IS part of the inner circle, I know)
You can find that post at
http://www.shiffman.net/2011/12/28/night-8-rendering-out-as-image-sequence/
Also, if you are on OSX, you can try Syphon ? See info here
https://forum.processing.org/topic/syphon-integration-with-processing

SVG to PDF on a shared linux server

I have a website which uses SVG for an interactive client side thingamabob. I would like to provide the option to download a PDF of the finished output. I can pass the final SVG output back to the server, where I want to convert to PDF, then return it to the client for download.
This would need to work on a headless shared linux server, where installation or compilation is either an enormous pain, or impossible. The website is PHP, so the ideal solution would be PHP, or use software that's easily installed on a shared webserver. Python, perl and ruby are available, along with the usual things you might expect on a linux box. Solutions that involve cairo, scripting inkscape, or installation more complex than 'FTP it up' are probably out. Spending large amounts of money are also out, naturally. As this is a shared server, memory and/or CPU hungry solutions are also out, as they will tend to get killed; this more or less rules out Batik.
The nearest that I've got so far is this XSL transform which I can drive from PHP and then squirt the resulting postscript through ps2pdf (which is already installed). The only problem with this is that it doesn't support SVG paths - if it did, it would be perfect.
There are a bunch or related questions on StackOverflow, all of which I've read through, but they all assume that you can either install stuff, spend money, or both.
Does anyone have an off-the-shelf solution to this, or should I just spend some downtime trying to add paths support to that XSL transform?
Thanks,
Dunc
I stumbled across TCPDF today which would have been perfect for this, had I known about it at the time. It's just a collection of pure PHP classes, no external dependencies for most things.
It can build PDF's from scratch and you can include pretty much anything you want in there, including SVG (amongst many, many other things), as shown in these examples:
http://www.tcpdf.org/examples.php
Main project page is here:
http://www.tcpdf.org/
Sourceforge page is here:
http://sourceforge.net/projects/tcpdf/
You can use Apache FOP's free Batik SVG toolkit which has a transcoder api to transform SVG to PDF.
download link
You will need to write a tiny bit of java. There are code examples here – note you will need to set the transcoder to org.apache.fop.svg.PDFTranscoder instead of Java.
You should be able to do this without installing anything on your machine – just drag the jars on there and run a script. I quote:
All other libraries needed by Batik are included in the distribution. As a consequence the Batik archive is quite big, but after you have downloaded it, you will not need anything else.
have you looked at imagemagick? I suspect you also need ghostscript to complete the loop, which might make installation difficulty and performance a problem.
I'd suggest giving princexml a try, they provide various addons (including one for PHP) and can output PDF from SVG/HTML/XML.
i have used TCPDF (http://www.tcpdf.org/) in many projects and it work in almost every use case.
Here is the example of SVG: https://tcpdf.org/examples/example_058/
and following is the code which can help you:
$pdf->ImageSVG($file='images/testsvg.svg', $x=15, $y=30, $w='', $h='', $link='http://www.tcpdf.org', $align='', $palign='', $border=1, $fitonpage=false);
$pdf->ImageSVG($file='images/tux.svg', $x=30, $y=100, $w='', $h=100, $link='', $align='', $palign='', $border=0, $fitonpage=false);

Resources