Nip2: A spreadsheet-like GUI for the libvips image processing library
github.com
github.com
John Cupitt (jcupitt here), the main developer of nip2 and libvips, is super helpful, responsive, generous, and patient.
They can pry nip2 from my cold, dead hands.
(the money is in the envelope on your desk)
My favorite one was when JPEG2000s that had an even width was being shown in greyscale on any mac app: Preview, Safari, Pixelmator, etc: https://github.com/libvips/ruby-vips/issues/345
All images with an odd width was working fine.
However the real bug was to do with chroma subsampling (and a lot of other technical stuff that I don't really understand): https://github.com/libvips/libvips/issues/2965
> Witcher Script (.ws) is the primary scripting language for The Witcher 3: Wild Hunt. A very large chunk of the game's logic is written in Witcher Script. Mods can override scripts and thus can drastically change game behavior. Witcher Script is either based on or identical to ActionScript 3 (and very similar to UnrealScript).
https://witcher-games.fandom.com/wiki/Witcher_Script
Interesting. CDPR had a NIH problem. At any rate I'm guessing GitHub is misidentifying something.
The nip2 scripting language is also very odd: it's something like dynamically typed Haskell, but with classes. You can see roughly what it looks like here:
https://github.com/libvips/nip2/blob/master/share/nip2/start...
All of the menus are implemented in this thing.
*.ws linguist-documentationBit of a tangent, but I don't think that's true. It's just ActionScript with a cute file extension - just like .docx is .xml with a cute file extension.
nip2 tries to do something similar, but using expressions, like a spreadsheet. Unlike graphical plugs and wires, expressions allow things like copy-paste, smart refactoring, referential transparency, and progressive rewriting.
nip2 is ancient now (I finished it way back in 2002, I think). I've started a rewrite for gtk4 -- the image display window is here:
https://github.com/jcupitt/vipsdisp
It's quite fancy -- it has a sparse pyramid of image tiles which get composited to your display by the GPU, and computed asynchronously by a libvips pipeline as you zoom and pan around. You should get a smooth 60 fps even with enormous (eg. 300,000 x 300,000 pixel) images.
I will have to check this out.
You can make a workspace interactively that does some task, then run it with something like:
nip2 -bp --set 'Workspaces.process.A1=Image_file "fred.jpg"' --set main=Workspaces.process.A10 -o fred2.jpg process.ws
-b meaning batch mode, -p meaning send the value of main to the output. That'll load the process.ws workspace, set cell A1 to be the image "fred.jpg", set main (the point of execution) to be cell A10, and save it to fred2.jpg.
I made a workspace for medical image analysis (my old job). It finds lungs in a 4D PET-CT scan, then fits a two compartment model per voxel and generates a volume image from k2. It has just over 10,000 cells (!!), 70GB of images, and executes in about 2 minutes using around 1GB of ram.
I then used a small bash script to loop over my dataset of 2,000 scans computing an inflammation index. It worked surprisingly well, IMO.
You can't have circular references to the top level, but you can do recursive definitions within a cell, which is maybe spreadsheety too.
You can use scraps of code to set the GUI behaviour, which is a bit crazy. Try making a region on an image (open an image view window, hold down CTRL, drag down and right).
Back in the main window, press the down button to the left of to the label of the cell containing the region and you'll find you can open it up. Keep clicking and a lot of rows will appear -- including left, top, width, height, etc. If you drag the region around and resize it, you'll see all these numbers update.
Click on the number for height and you can edit it. Enter "width * 2" and try resizing the region.
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.