add something like `mutable`
Opened this issue · 1 comments
The ruby-vips binding has a nice feature for encapsulating destructive operations, like metadata change or the draw operations:
https://www.libvips.org/2021/03/08/ruby-vips-mutate.html
tldr: you can write eg.:
z = x.mutate do |y|
1000.times do
y.draw_circle! Array.new(3) {rand(255)},
rand(y.width), rand(y.height), rand(100), fill: true
end
end
mutate
takes an image (x
in this case) and makes an instance of a class calledMutableImage
- This constructor runs
copy()
to make a private copy of the underlying vips image, and subclassesImage
, adding a few new methods such asdraw_circle!
(ruby uses the!
suffix on method names to indicate destructive operations) mutate
executes the block after, passing in the mutable image (y
in this case)draw_circle!
modifies the image you give it by erm drawing a circle ... the first time this happens, libvips will force the iamge into memory, ie. allocate a huge ram buffer and render the image into that- Now the 1000 circles are drawn directly into memory with no copying and no chance of side effects
- Finally, the mutable block ends, and
mutate
uses the modified vips image to build a new instance of theImage
class - And this new Image instance is returned (and assigned to
z
in this code)
So this scheme automates the copying that lua-vips requires right now before you can use destructive operations like metadata changes, or line or circle draw. It has locks to prevent things like set
or remove
being used on a non-mutable image, so it's always safe.
You see a nice speedup too: that code is more than 10x faster and needs less than 1/10th the memory compared to ruby-vips without mutate
.
This would be a nice thing to add to lua-vips. You could perhaps use anonymous functions, so the code above might be:
z = x:mutate(function (y)
for i = 1, 1000 do
y:draw_circle(... stuff)
end
end)
You'd need to add a new mutable image class and some locks to gate access to set
, remove
, draw_circle
, etc.
For reference, the ruby-vips mutable image class is here:
https://github.com/libvips/ruby-vips/blob/master/lib/vips/mutableimage.rb
And here's the mutate
method:
https://github.com/libvips/ruby-vips/blob/master/lib/vips/image.rb#L800-L819
The thing to call libvips operations has a few if
s for enforcing mutability.
https://github.com/libvips/ruby-vips/blob/master/lib/vips/operation.rb