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

Created on 18 Jun 2016  路  19Comments  路  Source: facebook/fresco

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

bug

All 19 comments

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

`

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

https://github.com/facebook/fresco/issues/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);

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

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.

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.

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.

@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".

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.

https://github.com/pagespeed/mod_pagespeed/issues/1329

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

Thanks,

Eric

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

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

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

Hello,

API 17 :

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

Enable downsample for webp to test :
https://github.com/eldk/fresco/commit/9730761f004f819f7d18f2b38e5b778664b16747

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/

Create a branch with update to libwebp 0.5.1 (static-webp) with downsample enabled (commented if statement https://github.com/facebook/fresco/compare/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 ...

@eldk you are great!

Hello,

as libwebp 0.5.1 is now merged in Fresco/Master (https://github.com/facebook/fresco/pull/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 : https://github.com/eldk/fresco/commit/8e91c71c7d0aece81a2cbf7381cabe6754e84cca)

Hello,

Fresco master branch handle now the size of webp pictures (https://github.com/facebook/fresco/commit/474f62af906341026943efeabf64a32516d1b2fe).

Thanks,

Eric

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 :

Was this page helpful?
0 / 5 - 0 ratings

Related issues

satyarths picture satyarths  路  3Comments

stevenmtang picture stevenmtang  路  3Comments

amodkanthe picture amodkanthe  路  3Comments

eldk picture eldk  路  3Comments

eresid picture eresid  路  4Comments