fluttercommunity / flutter_blurhash

Compact representation of a placeholder for an image. Encode a blurry image under 30 caracters for instant display like used by Medium. Maintainer: @Solido
https://pub.dev/packages/flutter_blurhash
MIT License
528 stars 66 forks source link

Add BlurHash encoding #20

Closed cachapa closed 4 years ago

cachapa commented 4 years ago

There are some use-cases where it is useful to perform encoding on the device, e.g. when sending large images using e2e encryption.

Adding encoding to this package would support that use case without including another dependency. I'm not too familiar with the BlurHash algorithm but I suspect this wouldn't add much code to the implementation.

For reference, here's the blurhash_dart implementation, which itself has no dependencies: https://github.com/justacid/blurhash-dart/blob/master/lib/src/blurhash.dart#L70

SaadArdati commented 4 years ago

This is exactly what I was looking for! Haha

I needed a server-side BlurHash encoder with no dependencies.

Solido commented 4 years ago

Use case is way too marginal to add it as a Flutter package.

In e2e you're still using a central server which is by far a better solution as you can rely on the C implementation.

Thanks !

cachapa commented 4 years ago

In e2e encrypted communication the server doesn't have access to the image in order to encode it though. That's the whole point of e2e, or am I misunderstanding your comment?

Solido commented 4 years ago

You're totally right ! but it still can figure out the use case in e2e.

Original file on mobile 1 -> encryption -> decryption on mobile 2 using p2p or central server.

How does blurhash help in this ? the time to generate the blurshash is equivalent to encryption.

While would you send the hash at the same time than the real file ?

cachapa commented 4 years ago

For example, sending an image from device1 to device2:

  1. device1 takes a photo
  2. device1 computes the blurhash
  3. device1 composes a json payload which includes the blurhash and sends it to device 2
  4. device1 starts sending the photo to device2
  5. device2 gets the payload and displays a blurhash placeholder
  6. device2 replaces the placeholder with the photo once it's downloaded

To be clear, I understand your reasoning that this may not be common enough to make sense implementing in your package. My only argument against that is that it wouldn't be a huge amount of code, but I also understand not wanting to maintain it.

Solido commented 4 years ago

Encoding to blurhash is an expensive method that's why low level C is still preferred with batch encoding of already available content.

Encoding an image in a mobile device to send the hash before the real image will not make a huge gain.

If more use cases scenarii emerge then I'll consider the option.

Thanks @cachapa

cachapa commented 4 years ago

Encoding to blurhash is an expensive method that's why low level C is still preferred with batch encoding of already available content.

Actually it's pretty fast (< 100 ms) provided you resize the image before encoding (which is also recommended by the official implementation).

Encoding an image in a mobile device to send the hash before the real image will not make a huge gain.

I don't understand this argument. Isn't the entire reason for BlurHash to show placeholders while images download? Mobile devices sometimes have pretty bad network so even a relatively small photo can take a while to download.

Solido commented 4 years ago

Yes but how much for resizing in mobile ? you need to load the image in memory, resize it then encode for the hash then you send the hash. At the same time you also need to encrypt the image.

On the second case you just encrypt the image and send it.

The whole use case of blurhash is having instant display that's why you batch the encoding with efficient process. Mainly C in mass parallel batch. Then you send the link to the image which name is the hash. Here you have instant display. The image is not encoded when you request it, it has been prepared upfront.

In your case the image is not ready when you ask for it so you add the hash encoding and on top of that the encryption.

Do you want this for a chat app where someone is not asking for an image but waiting that an undefined resource is hashed and encrypted. Then the whole process would be much more effective with native bridge than using encoding in Flutter.

cachapa commented 4 years ago

Resizing images is actually quite efficient on mobile since it uses the GPU which is optimized for exactly that - every time you display an image on the device it's being implicitly resized to the size of its view.

In fact, the slowest part is reading the bytes but that's a price you have to pay anyway in order to encrypt and send the data.

I agree that the point of blurhash is to have an instant display, which is why I'm confused about you saying it doesn't make sense for a chat app. I'm also confused by what you mean with "mass parallel batch". We're talking about sending a single picture to another user.

What I'm talking about isn't hypothetical: WhatsApp uses e2e encryption and shows a blurred placeholder when receiving images.

Solido commented 4 years ago

Ok I put imaginary numbers so we can clarify

Loading image i1 in memory : 200ms

What's the gain here ? 200ms between the two messages and you send the same information twice. Also it's still with a central server so at scale it cost you network fees. It's obviously a badly designed architecture for latency and running cost.

What I suspect they do in real world chat is they ONLY send the encrypted content then you decrypt in and calculate a blur effect from decoded data. It's much more efficient.

I get your point you don't get mine. BlurHash is useless in a chat it's used only as aesthetics when it's vital in a landing page when resources are pre-encoded for perception of loading speed.

This use case is not the blurhash use case when let's say Medium receive images for an articles they encode the image by batch because you simply won't start a process for each img, you do that at scale for cost and then replace the link in the article with the hash as link.

Feel free to test other libs to encode image as blurhash and send two messages to the channel for each posted image to see how effective it's.

cachapa commented 4 years ago

No need for imaginary numbers, I already have it implemented and on my phone it takes between 50 and 150 ms to generate a blurhash of high resolution images.

It's obviously a badly designed architecture for latency and running cost.

Sorry but I find this incredibly condescending and arrogant. You know nothing about my product or architecture yet feel entitled to comment on the quality of its design?

What I suspect they do in real world chat is they ONLY send the encrypted content then you decrypt in and calculate a blur effect from decoded data. It's much more efficient.

You suspect wrong. You can verify this by disabling automatic image download. Signal actually uses BlurHash for the same purpose btw, so there are at least two successful products that agree with the use-case. I mean, why would you calculate the blur effect if you already have the image? That doesn't make any sense.

I'm honestly surprised at your resistance to this, especially considering you're the maintainer of a BlurHash package. You say it's only used as aesthetics as if making beautiful products that people like to use was a bad thing. I'm also surprised you speak to the BlurHash use case as if it was only useful for Medium-style large-scale deployments, when the original developers specifically say they were motivated to work on it because loading images on mobile devices is sometimes too slow.

To be clear I managed to make my implementation work using only blurhash-dart so I was just continuing this discussion out of academic curiosity.

Solido commented 4 years ago

Sorry that you think I'm arrogant and that you feel judged on your choice.

I think you still miss my point about when using BlurHash or not.

If you architecture works for you it's the more important yet I'm convinced I would never do that in an architecture for chat.

You makes me tell stuff I don't said. BlurHash should be used when expectation of speed is required like landing page or cold start. When in a chat, there's no such expectation and thus implementing it is not necessary. The receiving user never had the perception of a delay. That's my point.

Thanks for sharing your points