DAddYE / vips

Go Bindings for Vips (a super fast image processor)
451 stars 52 forks source link

Trimming #6

Open DAddYE opened 9 years ago

DAddYE commented 9 years ago

Support trimming

Rif.: https://github.com/jcupitt/libvips/issues/233#issuecomment-73486391

DAddYE commented 9 years ago

@h2non what do you think?

h2non commented 9 years ago

Actually I don't need this feature in a short-term period (I'm just processing real photos), however I've to say that it could be useful introducing support for that feature, specially for some use cases. I'll think about it...

Definitively the Python implementation (and Ruby as well) looks pretty easy. This probably requires a better support for C low-level bindings providing a better interface versatility when calling different libvips functions.

BTW, I'm thinking in loud about the idea of creating a new Go package to provide a low-level interface and abstraction layer in pure Go to the most common libvips functions, underlying the complexibility and C types coupling in order to simplify when interacting with libvips, just using a clean Go pure API. Also abstracting and to avoid some boilerplate code when interacting with libvips, such as clean references, catch errors, proper thread-based processing etc... As I said, just thinking in loud.

DAddYE commented 9 years ago

BTW, I'm thinking in loud about the idea of creating a new Go package to provide a low-level interface and abstraction layer in pure Go to the most common libvips functions, underlying the complexibility and C types coupling in order to simplify when interacting with libvips, just using a clean Go pure API. Also abstracting and to avoid some boilerplate code when interacting with libvips, such as clean references, catch errors, proper thread-based processing etc... As I said, just thinking in loud.

I'd like that idea! Will be kind of hard especially because of performance problems.

While I checked few days ago I saw several defer, unfortunately that isn't yet fully optimized in go, so it adds (last time I checked) 20ns or so.

Calling C is expensive as well. So one good trick is to stay in c as much possible/needed.

h2non commented 9 years ago

Regarding to defer, that's true, at least with Go 1.2 and lower versions. Since Go +1.3, defer statement was optimized considerably, and in fact, Go team was focused mainly in performance optimization issues in 1.4 and future 1.5 version.

Performance gains are always valuable if the long-term benefit compensates the implementation, specially for some kind of low-level libraries, but I think premature optimizations could be painful. In the case of this statement, the trouble was just a Go core issue, not a Go developer issue. Go was relatively mature, but in terms of GC and memory handling it should be optimized in more ways in the future, and hopefully this is already happening and Go team know it.

Regarding to the C bindings, historically speaking, FFI was intrinsically expensive, however I think Go has a great C-level FFI layer with smart type casting and efficient intermediate code generation. I don't disagree about the idea of putting more (or even almost all) libvips responsibilities in the C-side, I'm just concerned about how to simplify all the things in the Go-side without losing the desired interface versatility in terms of image operations composition. Probably an initial approach is to think about this as C pure-functions which will get all the stuff done and come back to you with the result you expect (reusing processes internally but encapsulating them as well) and abstracting about dealing with memory freed and other funny stuff in the Go side

As conclusion, we could tend to port the each common image operation to a pure C implementation, and designing a high-level API in Go which is based on the composition of C-level functions. I think your feature/thumbnail branch is a good point to start with, and additionally, as simple example, the implementation of watermark feature

DAddYE commented 9 years ago

As conclusion, we could tend to port the each common image operation to a pure C implementation, and designing a high-level API in Go which is based on the composition of C-level functions. I think your feature/thumbnail branch is a good point to start with, and additionally, as simple example, the implementation of watermark feature

Yes!

and to be honest I was thinking on (for just resize) to use the c++ version of @lovell with c exports to work with go, in this way we can share the logic

h2non commented 9 years ago

I thought about that as well, but C++ and Go aren't best friends, specially for data structure like classes. I think too much overhead is required to work conformable with C++ code from Go.

I think sharp's code can be easily ported into a pure ANSI C version, and in any case, as alternative idea, we could converge in the same C code base. C++ is only required for V8 bindings, which is completely reasonable taking into account it's a node/io.js package, but I'd prefer do not generalize the language decision imposed by a third-party library. libvips is written in C, and in this case, taking into account benefits and cons, it sounds more reasonable using a same language in order to be as much close as possible close to the native implementation and removing layers between.

Never mind, just some thoughts :D

lovell commented 9 years ago

I'm hoping to move sharp to the new vips8 C++ bindings to simplify the code, as demonstrated by this edge detection example.

If you're happy moving to a minimum of libvips v7.42.3 (to include https://github.com/jcupitt/libvips/commit/8fbe8c36fa57941c125d0396e6ee9c4fe6a95f2f) you could offload much of the logic, including shrink-vs-affine, to a single vips_resize call.

jcupitt commented 7 years ago

Hi, I just came across this issue. I've been tinkering with an FFI-based libvips binding for Lua:

https://github.com/jcupitt/lua-vips

It's turned out to be pretty simple. There's a "class" for GValue (300 lines of code), a class for VipsObject (200 lines), a class for VipsOperation (220 lines), and an Image class (about 600 lines). The Image class defines all the operator overloads and has a set of convenience functions (so you can write image:sin() rather than the longer image:math("sin")), it could be much smaller.

Anyway, that's all you need to get a nice binding for the whole of libvips. And the binding is generated at runtime, so it'll automatically expand as operators and options get added. Performance seems good, though Lua has a very nice ffi module that lets you cache and reuse scraps of code, I don't know the Go one.

It's not quite done yet, there are some problems integrating reference counts and the Lua garbage collector, sigh.