Skip to content
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

.setDownsampleEnabled(true) then resize don't work for webp with at least Android API =17 #1310

Open
eldk opened this issue Jun 18, 2016 · 19 comments
Labels

Comments

@eldk
Copy link
Contributor

eldk commented Jun 18, 2016

Hello,

Testing Fresco with .setDownsampleEnabled(true) on one API 17 device, I don't have the downsample fresco logs (RequestLoggingListener).

With another device, that is API 10, files are well downsampled. I could see the RequestLoggingListener lines.

The API 10 device, with same Fresco settings (downsample and resize to same size) is fastest (about x2 to x4 ) to decode picture that the API 17 one.

API 10 :
RequestLoggingListener: time 210302582: onProducerFinishWithSuccess: {requestId: 11, producer: DecodeProducer, elapsedTime: 273 ms, extraMap: {bitmapSize=1600x1067, queueTime=0, imageType=DEFAULT, isFinal=true, hasGoodQuality=true}}

API 17 :
RequestLoggingListener: time 89545018: onProducerFinishWithSuccess: {requestId: 52, producer: DecodeProducer, elapsedTime: 928 ms, extraMap: {bitmapSize=1600x1067, queueTime=2, imageType=DEFAULT, isFinal=true, hasGoodQuality=true}}

On API 10, I can find the Downsample log line :
DownsampleUtil: Downsample - Specified size: 2048x2048, image size: 1600x1067 ratio: 1.3 x 1.9, ratio: 1.919 for http://domain.tl/picture.jpg

Thus I can't in API 17.

I have read this (http://frescolib.org/docs/configure-image-pipeline.html#_) and see downsample is experimental, but which Android version are supported, and which are not ?

This have been tested with fresco 0.10.0, 0.11.0.
All tested pictures are prefetch to disk and stored there before to be displayed.

Greatings,

Eric

@eldk
Copy link
Contributor Author

eldk commented Jun 18, 2016

Hello,

I think it's a bug related to webp usage :

If I prefetch a jpg picture, then display it, downsample is well done for API 17 :

DownsampleUtil: Downsample - Specified size: 2048x2048, image size: 4133x2554 ratio: 0.5 x 0.8, ratio: 0.802 for http://domain.tld/img.jpg

If I prefetch a webp picture (named img.jpg and not img.webp), then display it, downsample is not done :

I use mod_pagespeed (https://developers.google.com/speed/pagespeed/module/):

  • the requested picture filename is always something.jpg
  • the UA and accept header are always "faked" with the use of okHttp.

A curl example of a request :
curl -H "Accept: image/webp,image/*,*/*;q=0.8" -A "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36" http://domain.tld/picturefolder/image.jpg

The server response :
HTTP/1.1 200 OK Server: nginx Content-Type: image/webp Content-Length: 86864 Connection: keep-alive ETag: W/"PSA-aj-9k8tbmsEil" Date: Sat, 18 Jun 2016 22:51:28 GMT Expires: Mon, 27 Apr 2026 08:13:48 GMT Cache-Control: max-age=310987340 Vary: Accept

exiftool img.jpg :
ExifTool Version Number : 9.16 File Name :img.jpg File Size : 85 kB File Modification Date/Time : 2016:06:19 01:37:17+02:00 File Access Date/Time : 2016:06:19 01:40:00+02:00 File Type : WEBP MIME Type : image/webp VP8 Version : 0 (bicubic reconstruction, normal loop) Image Width : 1600 Horizontal Scale : 0 Image Height : 1067 Vertical Scale : 0 Image Size : 1600x1067

So, the response is always a webp, from API 10 to ...

I stiil have to try with one pictures simply named img.webp ...

Thanks,

Eric

`

@eldk
Copy link
Contributor Author

eldk commented Jun 19, 2016

Hello,

I stiil have to try with one picture simply named img.webp ...

Test KO : no log for downsampling, and DecodeProducer is longest for about x4 compare to API 10

RequestLoggingListener: time 348148: onProducerFinishWithSuccess: {requestId: 0, producer: DecodeProducer, elapsedTime: 811 ms, extraMap: {bitmapSize=1600x1067, queueTime=1, imageType=DEFAULT, isFinal=true, hasGoodQuality=true}}

Looking at this :

I have tryed to force lossy webp request (as it's API 17) and see if downsample is done : No change : KO.

Full fresco logs from combined tests with API 10 vs API 17 (picture is the same for all runs):

logs_fresco_downsample_webp.txt

two android API 17 debug info :
06-19 16:47:20.084 29781-30199/tld.domain.app I/dalvikvm: Could not find method android.graphics.Bitmap.getAllocationByteCount, referenced from method com.facebook.imagepipeline.nativecode.Bitmaps.reconfigureBitmap
06-19 16:47:20.094 29781-30199/tld.domain.app I/dalvikvm: Could not find method android.graphics.Bitmap.getAllocationByteCount, referenced from method com.facebook.imageutils.BitmapUtil.getSizeInBytes

#220

But image is wrap with aspect ratio :
http://frescolib.org/docs/using-drawees-xml.html#wrap-content

final RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

build draweeView with params :
imageView.setLayoutParams(params); imageView.setPadding(0, 10, 0, 10); ficheEspece.addView(imageView, params);

request picture

Then set aspect ratio :

imageView.setAspectRatio(1.62f);

@eldk eldk closed this as completed Jun 19, 2016
@eldk eldk reopened this Jun 19, 2016
@eldk eldk closed this as completed Jun 19, 2016
@eldk eldk reopened this Jun 21, 2016
@eldk
Copy link
Contributor Author

eldk commented Jun 21, 2016

Hello,

Setting fixed values to width and height for layout does not solved - "webp pictures are not downsampled for API 17":

06-21 18:16:09.826 21639-22178/tld.domain.app I/dalvikvm: Could not find method android.graphics.Bitmap.getAllocationByteCount, referenced from method com.facebook.imagepipeline.nativecode.Bitmaps.reconfigureBitmap

06-21 18:16:09.826 21639-22178//tld.domain.app W/dalvikvm: VFY: unable to resolve virtual method 626: Landroid/graphics/Bitmap;.getAllocationByteCount ()I

06-21 18:16:09.826 21639-22178//tld.domain.app I/dalvikvm: Could not find method android.graphics.Bitmap.getAllocationByteCount, referenced from method com.facebook.imageutils.BitmapUtil.getSizeInBytes

`06-21 18:16:09.826 21639-22178//tld.domain.app W/dalvikvm: VFY: unable to resolve virtual method 626: Landroid/graphics/Bitmap;.getAllocationByteCount ()I``

The diff from API10/API17 is that all off previous logs are not present.

For API 10 the logs are only:

06-21 18:32:34.779 22163-22198/tld.domain.app W/dalvikvm: VFY: unable to resolve virtual method 626: Landroid/graphics/Bitmap;.getAllocationByteCount ()I
06-21 18:32:34.779 22163-22198/tld.domain.app W/dalvikvm: VFY: unable to resolve virtual method 627: Landroid/graphics/Bitmap;.getByteCount ()I

and the picture is downsampled :

06-21 18:32:34.809 22163-22199/tld.domain.app V/unknown:DownsampleUtil: Downsample - Specified size: 320x480, image size: 1600x1067 ratio: 0.2 x 0.4, ratio: 0.450 for http://domain.tld/picture.jpg

and deco

@eldk eldk changed the title .setDownsampleEnabled(true) - Which Android versions are supported ? .setDownsampleEnabled(true) doesn't work for webp with at least API >=17 Jun 21, 2016
@eldk eldk changed the title .setDownsampleEnabled(true) doesn't work for webp with at least API >=17 .setDownsampleEnabled(true) doesn't work for webp with at least Android API =17 Jun 21, 2016
@eldk
Copy link
Contributor Author

eldk commented Jun 21, 2016

Here : https://github.com/facebook/fresco/blob/master/imagepipeline/src/main/java/com/facebook/imagepipeline/producers/DownsampleUtil.java#L38

EncodedImage.isMetaDataAvailable(encodedImage) is always false with webp in API 17 thus it's not in API 10.

EncodedImage.isValid(encodedImage) return true on both API 10 and API 17.

@eldk
Copy link
Contributor Author

eldk commented Jun 22, 2016

Hello,

As request is made with same headers with okHttp (3 now), the same picture send to both device with API 10 and API 17 have same size : GET /palourde_bleue-2.jpg HTTP/1.1" 200 86864.

The .ext is .jpg, but it's a webp :

A curl example of a request : curl -H "Accept: image/webp,image/*,*/*;q=0.8" -A "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36" http://domain.tld/picturefolder/image.jpg

The server response :
HTTP/1.1 200 OK Server: nginx Content-Type: image/webp Content-Length: 86864 Connection: keep-alive ETag: W/"PSA-aj-9k8tbmsEil" Date: Sat, 18 Jun 2016 22:51:28 GMT Expires: Mon, 27 Apr 2026 08:13:48 GMT Cache-Control: max-age=310987340 Vary: Accept

exiftool img.jpg :
ExifTool Version Number : 9.16 File Name :img.jpg File Size : 85 kB File Modification Date/Time : 2016:06:19 01:37:17+02:00 File Access Date/Time : 2016:06:19 01:40:00+02:00 File Type : WEBP MIME Type : image/webp VP8 Version : 0 (bicubic reconstruction, normal loop) Image Width : 1600 Horizontal Scale : 0 Image Height : 1067 Vertical Scale : 0 Image Size : 1600x1067

But files stores in Android app cache are different in size, encoding ...

API 10 stored file (.cnt) :

ExifTool Version Number : 9.16
File Name : scivwy71EWXLfd2WGo5U3Iu85FY_api10.cnt
File Size : 165 kB
File Type : JPEG
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : None
X Resolution : 1
Y Resolution : 1
Image Width : 1600
Image Height : 1067
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:2:0 (2 2)
Image Size : 1600x1067

API 17 stored file (.cnt) :

ExifTool Version Number : 9.16
File Name : scivwy71EWXLfd2WGo5U3Iu85FY_api17.cnt
File Size : 85 kB
File Type : WEBP
MIME Type : image/webp
VP8 Version : 0 (bicubic reconstruction, normal loop)
Image Width : 1600
Horizontal Scale : 0
Image Height : 1067
Vertical Scale : 0
Image Size : 1600x1067

Should it be the Vary: Accept from server response ?

I will check.

If So EncodedImage.isMetaDataAvailable(encodedImage) will always be false for API 17.
And it should explain why decoding is more time consuming.
A least, there's no a big diff to time to onProducerFinishWithSuccess but the rendering appear "flappy" and much long.

@eldk
Copy link
Contributor Author

eldk commented Jun 22, 2016

#743

@oprisnik
Copy link
Contributor

Thank you very much for the very detailed description @eldk , that is amazing!

As you've mentioned previously this is still experimental and has a couple of issues.
We'll take a look at this and do some digging.

@eldk
Copy link
Contributor Author

eldk commented Jun 22, 2016

@oprisnik , thanks.

Should you have a look here :

https://groups.google.com/forum/#!topic/mod-pagespeed-discuss/GbntPnwiGTU

that's not a direct matter but should enhance the use of Fresco and the app user respect on "get what you need, for what you should expect from what your device can do".

@eldk
Copy link
Contributor Author

eldk commented Jun 22, 2016

#1098

@eldk
Copy link
Contributor Author

eldk commented Jun 27, 2016

Hello,

I don't know if that should be opened in another topic, "mod_pagespeed/ngx_pagespeed : Provide support for image-resizing in-place " :
That's should be resume in "request, download and store pictures to the size you need for the user device spec from Apache or Nginx webserver".

From Fresco side, that would be done with oKHttp backend that can modify request headers.

apache/incubator-pagespeed-mod#1329

preambule : https://groups.google.com/forum/#!topic/mod-pagespeed-discuss/GbntPnwiGTU

Thanks,

Eric

PS : @tyronen ... , should you have a look

@eldk
Copy link
Contributor Author

eldk commented Jun 28, 2016

Hello,

API 17 :

When webp pictures are used, downsample, nor resize are done.

final DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); int height = displaymetrics.heightPixels; int width = displaymetrics.widthPixels;

ImageRequest request = ImageRequestBuilder .newBuilderWithSource(urlImage) .setResizeOptions(new ResizeOptions(width, height))

with setDownSampleEnabled(true) :

RequestLoggingListener: time 20375552: onRequestSuccess: {requestId: 54, elapsedTime: 4165 ms}
Final image received! Size %d x %d: Quality level 3945, good enough: 2438, full quality: 2147483647

without //setDownSampleEnabled(true) :

RequestLoggingListener: time 20638151: onRequestSuccess: {requestId: 0, elapsedTime: 4195 ms}
Final image received! Size %d x %d: Quality level 3945, good enough: 2438, full quality: 2147483647

With jpg :
DownsampleUtil: Downsample - Specified size: 600x976, image size: 3945x2438 ratio: 0.2 x 0.4, ratio: 0.400 for
RequestLoggingListener: time 551538: onRequestSuccess: {requestId: 0, elapsedTime: 1275 ms}
Final image received! Size %d x %d: Quality level 1973, good enough: 1219, full quality: 2147483647

@eldk
Copy link
Contributor Author

eldk commented Jun 30, 2016

Hello,

API 17 :

When webp pictures are used, downsample, nor resize are done.

remove static-webp from build change nothing (picture is displayed), except :
those logs are not there :

06-30 16:11:01.720 2000-2335/tld.domain.app D/dalvikvm: Trying to load lib /data/app-lib/tld.domain.app-1/libstatic-webp.so 0x41a7ace8

06-30 16:11:01.730 2000-2335/tld.domain.app D/dalvikvm: Added shared lib /data/app-lib/tld.domain.app-1/libstatic-webp.so 0x41a7ace8

@eldk
Copy link
Contributor Author

eldk commented Jun 30, 2016

Hello,

API 17 :

When webp pictures are used, downsample, nor resize are done.

Enable downsample for webp to test :
eldk@9730761

Have you some pictures ... info, on what is https://github.com/eldk/fresco/blob/9730761f004f819f7d18f2b38e5b778664b16747/imagepipeline-base/src/main/java/com/facebook/imagepipeline/image/EncodedImage.java#L282 ?

I have tryed with a set of 50 webp pictures (WEBP_SIMPLE) but no error and all webps are "downsampled".

And no more :

06-21 18:16:09.826 21639-22178/tld.domain.app I/dalvikvm: Could not find method android.graphics.Bitmap.getAllocationByteCount, referenced from method com.facebook.imagepipeline.nativecode.Bitmaps.reconfigureBitmap

06-21 18:16:09.826 21639-22178//tld.domain.app W/dalvikvm: VFY: unable to resolve virtual method 626: Landroid/graphics/Bitmap;.getAllocationByteCount ()I

06-21 18:16:09.826 21639-22178//tld.domain.app I/dalvikvm: Could not find method android.graphics.Bitmap.getAllocationByteCount, referenced from method com.facebook.imageutils.BitmapUtil.getSizeInBytes

`06-21 18:16:09.826 21639-22178//tld.domain.app W/dalvikvm: VFY: unable to resolve virtual method 626: Landroid/graphics/Bitmap;.getAllocationByteCount ()I``

Thanks,

Eric

https://chromium.googlesource.com/webm/libwebp/+/master/doc/

@eldk eldk changed the title .setDownsampleEnabled(true) doesn't work for webp with at least Android API =17 .setDownsampleEnabled(true) then resize doesn't work for webp with at least Android API =17 Jul 6, 2016
@eldk eldk changed the title .setDownsampleEnabled(true) then resize doesn't work for webp with at least Android API =17 .setDownsampleEnabled(true) then resize don't work for webp with at least Android API =17 Jul 6, 2016
@eldk
Copy link
Contributor Author

eldk commented Aug 1, 2016

Create a branch with update to libwebp 0.5.1 (static-webp) with downsample enabled (commented if statement master...eldk:mlibwebp0.5.1+downsampleWebp#diff-834406681de434c4151758dd5d280b43R285) for webp :
https://github.com/eldk/fresco/tree/mlibwebp0.5.1+downsampleWebp .

About to publish one app version with listener on producer ... to build stats on times to fetch, transcode, decode ...

@caojianfeng
Copy link
Contributor

@eldk you are great!

@eldk
Copy link
Contributor Author

eldk commented Sep 7, 2016

Hello,

as libwebp 0.5.1 is now merged in Fresco/Master (#1388).

I deleted all branches, from my repository, with previous libwebp versions.

Branche with downsample enable for webp (to test) is here : https://github.com/eldk/fresco/tree/mDownSample (diff is here : eldk@8e91c71)

@eldk
Copy link
Contributor Author

eldk commented Nov 6, 2016

Hello,

Fresco master branch handle now the size of webp pictures (474f62a).

Thanks,

Eric

@eldk
Copy link
Contributor Author

eldk commented Feb 1, 2017

Hello,

Here are/will be some datas about times to display pictures with Fresco : https://neptune.opalesurfcasting.net/

  • Pictures are always dowloaded as WebP, from API 10 to ... to save bandwith use.
  • Pictures have always the same dpi, whatever is the device dpi
  • For devices before Android 4.0+, pictures are downloaded then transcoded from WebP to jpg before to be "diskCached".

So datas are :

  • time to display downloaded pictures (include transcoding for device before Android 4.0)
  • time to display "diskCached" pictures (so jpg for pre-Android 4.0 devices)
  • time to display "fromMemoryCache"

Times are in milliseconds (converted from nanos).

The next step will be to request and build adapted device dpi pictures on the fly.

Thanks,
Eric

PS :

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants