-
-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for true streaming #33
Comments
True streaming is not yet supported within libvips. There has been quite a bit of talk of adding this, and there's a branch that adds this, but it's never been merged for various reasons. See: In the meantime, I've added support for loading and saving from and to streams (commit e23b10b):
If you want to test this, you can use the nightly version of NetVips. Add the
And update NetVips to |
Thx. I have similar approach with temp file. |
I had a quick look at their code to see how they handle streams. It looks like they use temporary files:
So no "true streaming" either. |
NetVips v1.1.0 is now available. |
libvips has a PR now to add true streaming: Feedback etc. very welcome. |
The @jcupitt The test results look good! The only problem I found is loading a WebP image with a seekable stream that is not backed by a file descriptor. It look like |
I'll have a look, thanks Kleis. Do you have benchmark results you could share? I've not seen any numbers yet :( |
The logic was a bit wonky. Thanks Kleis. See kleisauke/net-vips#33 (comment)
You're right, the logic for map was a bit messed up. It should be better now. |
Update: I've checked php-vips quickly and it seems OK. The add-streams branch of ruby-vips adds support for streams. ruby-vips master now works with the new metadata change restrictions. I've opened an issue on image_processing (the gem behind libvips on rails etc.) telling them about streams. Phew. |
Thanks John! I needed to apply this patch to make it work for seekable streams: DetailsFrom 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Kleis Auke Wolthuizen <[email protected]>
Date: Sun, 1 Dec 2019 13:00:00 +0100
Subject: [PATCH] Ensure vips_streami_map works for seekable streams
diff --git a/libvips/iofuncs/streami.c b/libvips/iofuncs/streami.c
index 1111111..2222222 100644
--- a/libvips/iofuncs/streami.c
+++ b/libvips/iofuncs/streami.c
@@ -825,7 +825,7 @@ vips_streami_is_mappable( VipsStreami *streami )
return( streami->data ||
VIPS_STREAM( streami )->filename ||
(!streami->is_pipe &&
- VIPS_STREAM( streami )->descriptor) );
+ VIPS_STREAM( streami )->descriptor != -1) );
}
/**
@@ -860,6 +860,16 @@ vips_streami_map( VipsStreami *streami, size_t *length_out )
return( NULL );
}
else {
+ /* Seekable streams must be converted.
+ */
+ if( !streami->is_pipe ) {
+ if( vips_streami_rewind( streami ) )
+ return( NULL );
+
+ streami->header_bytes = g_byte_array_new();
+ streami->is_pipe = TRUE;
+ }
+
if( vips_streami_pipe_to_memory( streami ) )
return( NULL );
} I also discovered a small bug on Windows (couldn't reproduce this on Linux, weird). See:
I guess this call should be clamped with By the way, Could we maybe do the opposite in For the loader:
For the saver:
This ensures that the streaming API can also utilize |
Regarding benchmarks; I'll do some benchmarking over the next week (it might be interesting to benchmark with S3 / network streams as well). |
A pre-release version of NetVips v1.2.0-rc1 and NetVips.Native v8.9.0-rc4 (which contains the pre-compiled libvips 8.9.0-rc4 binaries for Linux, macOS and Windows) is now available on NuGet. This release adds support for true streaming. See the blogpost and the tutorial for more information. Any feedback is more than welcome! |
That looks great! The syntax for the custom handler looks really nice. Progress handling looks good too. Do you expose |
I have some problems with reading(detecting) gif. using var input = File.OpenRead("test.gif");
using var output = File.OpenWrite("test.jpg");
using var image = Image.NewFromStream(input, access: Enums.Access.Sequential);
image.WriteToStream(output, ".jpg"); with random gifs and get following exception
Windows 10, NetVips 1.2.0-rc-1, NetVips.Native v8.9.0-rc4. |
The C version of https://github.com/libvips/libvips/blob/master/libvips/iofuncs/image.c#L2240 But it's inside a C func with varargs, so it's awkward to use from language bindings. All bindings will have to implement their equivalent of that. Perhaps we should have a VipsOperation called |
Oh hang one, sorry, that won't work either, since the arguments to |
It's available in the public API, if that's what you mean. The logic is quite simple and similar to pyvips: It uses a custom marshaller for NetVips doesn't have this requirement, allowing you to do this (for example). public delegate void PostClose(IntPtr objectPtr, IntPtr userDataPtr);
static void OnPostClose(IntPtr objectPtr, IntPtr userDataPtr)
{
Console.WriteLine($"postclose: userData = {userDataPtr}");
}
static void Main(string[] args)
{
var im = Image.NewFromFile("lichtenstein.jpg", access: "sequential");
im.SignalConnect("postclose", (PostClose)OnPostClose, (IntPtr)42);
im.Dispose(); // g_object_unref()
} postclose: userData = 42
I'll see if I can implement the equivalent in the binding. I think this will be easy for the load functions (simply call Do you know what loader is the "biggest sniffer" for determining the fall back loader with |
I thought about an awful case. Consider this stream that doesn't support seeking (e.g. network streams or pipes):
Might use 999 MiB of memory (when using a fallback mechanism) since it maps the whole stream to memory because Perhaps we should make |
Ooops hehe. Going too fast. I think we'll need an 8.9.1 pretty soon, openslideload is broken too :( |
Biggest sniffer: openslideload can be a bit slow since it has to load quite a bit of TIFF header to be sure. tiffload can be a little slow too since it must load the first directory to make certain this isn't a DNG etc. file. Yes, perhaps pipe read limit needs to be a parameter. It should be easy to add to |
I think webp load is the only one in 8.9 that has this problem. I don't know what a sane limit on webp size would be. I'd say 10MB for the pixel data, since they can only be 16k x 16k pixels, for now anyway. Perhaps another 10 for crazy XMP metadata blocks. svgload has an |
webpload must force sources into memory to read them, but huge objects on pipes could fill memory. We had a 1GB limit, but that's probably too large. This patch adds a configurable limit and wepload sets it to 20MB. See kleisauke/net-vips#33 (comment)
I made a branch adding a pipe read limit property, does that look reasonable? We'd probably need |
I made a branch adding a fallback for // file-based loader fallback
using (var input = Source.NewFromFile(Helper.GifFile))
{
var img = Image.NewFromSource(input, access: Enums.Access.Sequential);
GifValid(img);
}
// buffer-based loader fallback
using (var input = File.OpenRead(Helper.GifFile))
{
var img = Image.NewFromStream(input, access: Enums.Access.Sequential);
GifValid(img);
}
Ah I see. My idea was to first pass a chunk of the stream to
How about animated WebP images? I think some of them could exceed 10MiB.
If the limit could be configured, then an unlimited flag seems a bit superfluous. For example, you can also set
Looks good! Doesn't it make more sense to add a global function (like the |
I was trying to reuse the svgload behaviour, but you're right, perhaps a global option is better. |
NetVips v1.2.0 and NetVips.Native v8.9.1 is now available. The @jcupitt Should I create a new issue for configuring the |
Good idea, it'll get forgotten otherwise. |
Is it possible with libvips?
The text was updated successfully, but these errors were encountered: