FLIF-hub / FLIF

Free Lossless Image Format
Other
3.72k stars 229 forks source link

Added an LGPLed gdk-pixbuf loader #417

Closed Traneptora closed 7 years ago

Traneptora commented 7 years ago

Added an LGPL-licensed gdk-pixbuf loader. This allows FLIF files to be viewed in image viewers like Eye of Gnome/MATE. It only implements reading so far and it's somewhat limited but it does do the primary purpose.

Notable TODOs

Gdk-pixbuf's progressive loader works by collecting chunks of bytes at a time to feed directly to the decoder, which is basically how downloading from a webpage works. When libflif reads an initial segment, it tries to decode it and gets an "unexpected end of file," because the whole file hasn't been loaded yet. Unfortunately, if you've buffered only some but not all of the image file, and attempt to decode with flif_decoder_decode_memory, the flif decoder will report "end of file" and start interpolating. At this point, there's no way to actually get it to resume decoding where it had left off. If you want to restart, you have to start decoding from the beginning. This seems to contradict "responsive-by-design" and it's clearly not a file format issue, so hopefully I can fix the lack of progressive decoding in this pixbuf loader when the API becomes easier to use.

jonsneyers commented 7 years ago

Very nice! Thanks!

hrj commented 7 years ago

About progressive decoding, if your platform supports threads, then the existing API is sufficient. You decode in one thread and block on it when you run out of input. In another thread, you do the rendering.

Having said that, an async API would be nice. It would tremendously help with the JS port, because JS doesn't support blocking calls. However, writing an async decoder is non-trivial and would probably also reduce performance.

Traneptora commented 7 years ago

@hrj "block on it when you run out of input" the problem is entirely that the library doesn't allow this to happen. You'd have to do some sort of hack like create a blocking pipe and decode in a separate process. If the library runs out of input, either via EOF from a FILE, or via reaching the end of a memory buffer, it'll treat it as an "unexpected end of file" and it won't allow you to append new data to the buffer or grow its size. You have somehow create a special FILE pointer that does that for you, such as one that reads from a socket or a pipe.

hrj commented 7 years ago

"block on it when you run out of input" the problem is entirely that the library doesn't allow this to happen. You'd have to do some sort of hack like create a blocking pipe and decode in a separate process.

IMO, it's not a hack to create a blocking pipe and use a separate thread/process. But yes, it would be nice to expose the IO subsystem into the API. However, that hits another problem: the IO subsystem is written in C++ like the rest of the code, while the API is pure C.

IIRC, you are using the decoder functions directly (not through the C API). In which case, you can extend the IO class directly and add a blocking implementation.

hrj commented 7 years ago

IIRC, you are using the decoder functions directly (not through the C API). In which case, you can extend the IO class directly and add a blocking implementation.

Scratch that. That was in the context of the flif binary, not this PR.

Traneptora commented 7 years ago

Yes, if you're executing the CLI then inter-process communication isn't a hack, but if you're trying to use functionality that should be in the library when you link to it, it seems unnecessary. Consider how libwebp exploses this does it just as an example.