HN user

jcupitt

49 karma
Posts0
Comments39
View on HN
No posts found.

Hello, libvips author here, you can get it to do the OKLab averaging for you. For example, using pyvips (ahem, untested):

image = pyvips.Image.new_from_file(filename, access="sequential")

scale = min(200 / image.width, 200 / image.height)

thumbnail = image.colourspace("oklab").resize(scale).extract_bands(0, n=3)

rgbf = thumbnail.write_to_memory()

That'll stream the source image and make a RGBRGBRGB memory buffer of single precision floats. You could perhaps use kernel="linear" and avoid any ringing from lanczos3.

I think I would downsample in a linear light space, like scRGB. Averaging there means averaging photons, which will surely be better than OKLab. Maybe switch to OKLab for clustering. Though of course I've not tested it.

Ah no problem! I'm glad it's useful.

`govips` was a pretty early binding and wasn't really done the libvips way. It doesn't expose all the operations or options, it's mostly done by hand, and there are a number of leaks and misfeatures.

It's been replaced by `vipsgen`:

https://github.com/cshum/vipsgen

Which is an automatically generated 100% binding. It should have the complete API, it should be very stable and leak-free, and it should be simple to maintain.

`autorot` is pretty expensive. You'll see much better performance if you flip x and y in your crop instead.

Hello, libvips author here, the JPEG loader has a flag to do this for you. You can write:

VipsImage *image = vips_image_new_from_file("something.jpg", "autorotate", TRUE, NULL);

and it'll flip it upright for you and remove any EXIF orientation tag. It isn't the default since it has (obviously) a large memory and cpu cost.

For simple resize and crop it's much better to use the exif tag to adjust the resize and crop parameters (the vipsthumbnail command does this).

Those three all use libvips as the image processing engine, fwiw, so it's maybe not a very wide survey.

libvips is fairly highly threaded and does a lot of alloc/free, so it's challenging for most heap implementations.

libvips dev here -- the CLI interface is deliberately really basic, you'll see much better performance and flexibility with one of the language bindings. pyvips works well:

https://github.com/libvips/pyvips

The idea is that complex CLIs like imagemagick's are almost complete programming languages, and need a lot of learning. It's much better (imo) (and less work) to have a good binding, and to lean on python for the programming side.

libvips is mostly self-binding. It has good introspection support, so the core of pyvips is just 200 lines of code, and automatically updates itself for new libvips versions.

I made an image viewer for large images:

https://github.com/jcupitt/vipsdisp

It should be fine with your huge PNGs. Internally it's a bit like a tiled map viewer, but it makes the tiles as you view the image with a set of background worker threads. It uses your GPU to scale and composite the set of visible tiles to your screen.

It uses openslide to let you view slide formats like SVS and MRXS, which might be handy. It also supports colour management.

nip2 does this. It's a little like a spreadsheet, but cells can contain images, matrices, text, widgets, stuff like that. You can add scraps of code to link them together (just like a spreadsheet).

https://github.com/libvips/nip2

Your example might look like this:

https://imgur.com/a/RmESTBw

Everything is live, so you can drag sliders and adjust expressions and it all updates.

There's also imagemagick, of course, but it's command-line only.

It's actually the other way around: WebP images are about the same size as JPEG encoded with mozjpeg -- compression is no better. WebP does have advantages for images with transparency. Google effectively abandoned webp more than five years ago now and began work on webp2. But they've now abandoned that as well.

JXL, AVIF and HEIC use next-gen compressors and are about half the size of JPEG and WebP at the same quality. HEIC has a range of terrible patent problems, so the current choice is AVIF vs JXL.

AVIF has wider industry support and is likely to get hardware decode. JXL is technically more interesting and more flexible, and far better CPU encode/decode performance.

I use tiled TIFF with jpeg compression for things like this. You get good compression, support for huge sizes, and wide compatibility. TIFF supports image pyramids too, so you can even get good interactive performance.

No direct web browser support is the only big downside :(

Firefox has had basic support behind a flag for a good while, but it needs some work -- their code is missing things like transparency and colour profiles. Sadly mozilla have laid off a lot of their dev team and they don't have much capacity right now.

Safari have support as a build-time option, apparently.

libvips has had libjxl support for a couple of years now, including in our fuzzing and build systems. Everything is pretty much ready to roll, and would have brought support to downstream projects and users like sharp, ActiveRecord, imaginary, Shopify, etc.

We've just been waiting for Chrome to flip the switch and start deployment, To have support pulled like this at the last second is extremely disappointing.

Yes, nip2 workspaces are DAGs, like node graph interfaces. The spreadsheet comparison was originally there to help introduce the interface to a less technical audience. nip2 was written in the 1990s when this stuff was less widespread.

I don't like plug-and-socket style graphical node graph interfaces personally -- I think they are hard to reason about, and things like composition and rewriting feel unnatural (to me). I came out of the functional programming community and I wanted things like referential transparency.

nip2 is supposed to be a graphical interface that's an expression of a set of relations. It has a three part model:

1. You enter scraps of code (or pick menu items) to build an object in nip2's programming language.

2. nip2 looks at the constructed object and draws the GUI.

3. Changes to the GUI trigger "edit" functions on the constructed object to update it.

4. ... if you go back and edit the code that originally constructed the object, the GUI resets.

So your code and the GUI independently update the constructed object, with code taking priority. You get a stateful GUI with a purely functional programming language and you get to keep equational reasoning.