That's some pretty aggressive editorializing in the title. The linked page doesn't once use "faster", "VIPS" or "PIL".
The page does link to benchmarks [0] but Photon isn't the clear victor. It's slower on the PNG benchmark but faster on the JPG benchmark. There are no benchmarks for PIL.
It's an interesting project but the differentiating factor is more portability and security than speed. WASM means that this can be run in a nice sandbox where its ability to harm the system is drastically reduced.
Most Python libraries like PIL rely on some flavor of the venerable libjpeg (e.g. libjpegturbo, mozjpeg) which makes it the de-facto standard for loading jpegs.
A notable downside is that it's written in C and there have been more than a few exploits found inside it over the years. While it's pretty damn mature by now and there has been a huge amount of fuzzing done to tease out remaining issues, fact remains that it's yet another attack vector that makes your resident security guy or gal raise a few eyebrows.
With zune-jpeg you get a fully memory-safe implementation that can act as a drop-in replacement, and when you turn on the (admittedly experimental) SIMD support for things like the IDCT and color-space conversion it's as fast, or in places even faster, than libjpegturbo/mozjpeg, even on very large (e.g. 4k by 4k) images.
I really wish it were considered bad practice to waste README space on what amounts to advertising. A README should plainly provide a high-level overview and documentation. It shouldn't stand in for a website, a blog post, or marketing.
> security and safety is guaranteed
Only memory safety is guaranteed, and only if the library avoids `unsafe`, right?
Only if the entire address space for that process is built using memory safe code (different from necessarily marked "safe" in the rust sense) and only if there are no soundness bugs in the rust compiler.
Otherwise C code can muck with things the rust code considers invariant and "verified". Or if something with a soundness issue is used, maybe safe doesn't quite mean safe.
As a counterpoint unsafe can be safe if the behaviour is well modelled and understood. It just means no checks are applied to the superset features of rust if they are used (outside of unsafe they can't be). The standard library of rust uses unsafe quite a bit.
Probably the best way I can try to put it is that "safe" is a subset of correct where you mean no memory safety issues (spatial or temporal) and rust tries to prove this for you. Except it you type unsafe then it is on you to promise to the compiler that the extra footguns it enables are used correctly. If you include this code in a larger program some of these guarantees are statically assured at compile time for performance including the correctness of the runtime checks rust does. There is no compartmentalisation unless you use OS features (separate processes) for that (or whatever webasm allows for).
Last time I checked this didn't do operations involving multiplications in linear space, i.e. any convolution or downscale operation would create wrong results.
Everything was done in 8-bit/channel non-linear. It uses the 'image' crate's `ImageRgb8` type under the hood. As such I would also be surprised if did anything faster than the 'image' crate/its companion crate 'imageproc' (for the same operations, resp.).
I think the 'image' crate may have fixed some of the non-linear issues in the meantime (but not sure). But 'photon-rs' on crates.io wasn't updated in two years and depends on 'image' v0.23.12 which does e.g. resizing in the input space, AFAIR.
Also this crate confuses what is a color model with a what is a color space. Some of the supported "color spaces" are color models, some are indeed spaces. E.g. RGB is a model, as is HSV or HSL.
While there are the 'colstodian' (1), 'kolor' (2) and recently the new (and very good looking) 'color' (3) crates to abstract the color space aspect nicely, the list of reverse dependencies on crates.io lays the issue bare (1: zero, 2: one when not counting colstodian and 3: a few but none of them dealing with image processing AFAIK).
The ecosystem of Rust crates that get these things right is small because few people understand the signal processing math and color science.
At the same time there are disproportional many crates that do some sort of image processing (as many people want to write/enjoy writing such a crate, it seems -- possibly theirs being "faster" or their API being "better" than everyone else's).
To wrap up the bitching about the 'photon-rs' crate: it's name has an -rs suffix about which the official Rust API guidelines [3] have this to say:
"Crate names should not use -rs or -rust as a suffix or prefix. Every crate is Rust! It serves no purpose to remind users of this constantly."
And its getters start with `get_`, also a no-no in Rust, if you care about [3] (which you should, official naming guidelines are one of the reasons that make the Rust ecosystem a lot more "wholesome").
And now for some good stuff:
If you want to see some really fast image processing in Rust that has built-in support to get the above things right, check e.g. the 'libblur' [1] or 'pic-scale' [2] crates, by the same author.
They allow doing operations in non-linear space but they warn users about it and/or explicitly mention & provide avenues of doing the right thing easily, i.e. in doing everything in linear space (even when input & output is e.g. 8bit/channel sRGB).
The page does link to benchmarks [0] but Photon isn't the clear victor. It's slower on the PNG benchmark but faster on the JPG benchmark. There are no benchmarks for PIL.
It's an interesting project but the differentiating factor is more portability and security than speed. WASM means that this can be run in a nice sandbox where its ability to harm the system is drastically reduced.
[0]: https://github.com/silvia-odwyer/photon/wiki/Benchmarks