CaiJingLong / dart_image_size_getter

Use dart file api to get image size, needn't use decode. just read the metadata.
Apache License 2.0
64 stars 29 forks source link

Allow for images from network requests #6

Closed kobutri closed 2 years ago

kobutri commented 3 years ago

Loading big images over the network is slow, but the dimensions of an image can be determined with just the first few bytes. In a scenario where the aspect ratio of an image retrieved over the network is not known beforehand, this allows to determine the final layout earlier.

Fetching images over the network is by nature asynchronous. To accommodate this, all APIs of this libraries have been made async in this pull request.

Moreover, a convenient NetworkInput class has been added, that abstracts the response stream.

CaiJingLong commented 3 years ago

Hi, thanks for your commit. But I will consider using the Range header and 206 status code first to determine whether partial loading is supported. If it cannot be completed, then downgrade to your implementation. In addition, I think there should be a separate asynchronous class to complete the process of obtaining the size, because synchronous methods are necessary in many cases.

So, I will add AsyncImageSizeGetter to async load image size.

kobutri commented 3 years ago

Tanks for your feedback.

I didn't know about the Range header so thanks for pointing that out. Do you know how common support for range request is? If it isn't super common, it might be worth putting it behind a flag to avoid unnecessary requests. JPEG requires dynamic ranges. Should we request larger chunks or risk making multiple requests.

The use case for my current implementation is written for getting the size early but still having access to the entire image later without duplicating requests. Is this something that would be in scope for this library or is this only meant for determining image size?

Could you explain your reasoning behind making separate classes for synchronous and asynchronous behaviour. Is it just usability or are there other shortcomings of waitFor?

Lastly, should I incorporate these changes or will you do it yourself?

CaiJingLong commented 3 years ago

This is only for the purpose of loading the size of the image itself. If your goal is to definitely load the image and know the size of the image before rendering, you don't need to customize ImageInput, just use MemoryInput. For example:


   // 1.  request image data.
   final url = 'https://cdn.jsdelivr.net/gh/kikt-blog/blog-2@pay/pay.jpg';

    final client = HttpClient();

    final req = await client.getUrl(Uri.parse(url));
    final resp = await req.close();

    final buffer = <int>[];

    await resp.listen((event) {
      buffer.addAll(event);
    }).asFuture();

    client.close();

    final image = Uint8List.fromList(buffer);

   // 2. Use the library to get size.
    final input = MemoryInput(image);

    final size = ImageSizeGetter.getSize(input);
    print(size);

    // 3.  use the List<int>/Uint8List in flutter.
   ImageProvider imageProvider = MemoryImage(bytes);
   Image(image: imageProvider);

What this library does is: do not load any unnecessary data and get the image size.

If you don't need to render and just want to know the size of a remote image, use it. If you are sure to load the image data, you can use it after request.

CaiJingLong commented 2 years ago

I have submitted new code to complete the relevant functions, and the code has been updated to version 2.0, so close it.

Thanks for pull request.