B4A Library Webp - new options

this is an update to @Pendrush's image conversion library.

i had my own personal utility for webp images.
i thought i might post it as a library, but, on checking, i saw
that member @Pendrush already had one. as it turns out,
our code is mostly identical (there really aren't too many
different ways to convert a bitmap from one format to
another). there was, however, one big difference: the
deprecation by google of the (plain, one-size-fits-all) webp
bitmap format. it was replaced by a choice between
webp lossless and webp lossy formats. my utility uses the
newer format options.

the 2-format option works like the 1-option jpg conversion
function we are already familiar with where we supply the level
of compression desired. why google had to use 2 different
formats to achieve the same end as jpg's 1 is not for me to judge.
perhaps its programmers - not unlike dickens - get paid by the method.
in any case, the reduction in size (while retaining image quality)
when using the lossy format is pretty amazing.

i altered my utility a little so as to behave like a drop-in replacement for
@Pendrush's in terms of parameter passing. as with conversions to
png, the compression factor (quality setting) is ignored for lossless
webp.


if he feels like updating his library to reflect the new webp options, i'm
happy to destroy all digital copies of mine in my possession and to burn the
source.šŸ”„
 

Attachments

  • gwebp.zip
    2.5 KB · Views: 149
Last edited:

Pendrush

Well-Known Member
Licensed User
Longtime User
To use WEBP_LOSSLESS and WEBP_LOSSY you need to set minSdkVersion to 30.

1639555966950.png


You can still achive same result with TO_WEBP.
Compress to the WEBP format. quality of 0 means compress for the smallest size. 100 means compress for max visual quality. As of Build.VERSION_CODES.Q, a value of 100 results in a file in the lossless WEBP format. Otherwise the file will be in the lossy WEBP format.
 

drgottjr

Expert
Licensed User
Longtime User
i should mention that google's changes regarding webp images struck me as confusing.
originally, converting a bitmap to webp appeared to be similar to what we did with jpg images:
apply a quality (or compression) setting to the conversion to control the size of the resulting
image (with a loss in quality the more compressed the image). in the case of a jpg, regardless
of the setting, the result was always "lossy", given that jpg's are, by definition, lossy. things are
not so simple with webp images.

beginning with sdk14, android supported webp as a lossless image format. starting with
sdk18, support for lossy webp was added. at sdk29, android's handling of the quality
setting changed: a setting of less than 100 resulted in a lossy webp. a setting of 100
resulted in a lossless webp. beginning with sdk30, that method was deprecated, and a
new system instituted: you specifically choose whether to create a lossless or a lossy
webp, but the quality settings assume opposite meanings, depending on which format
you choose.

let us review: a jpg is always lossy, an sdk29 webp could be lossy or lossless,
an sdk30 lossless webp is always lossless, and an sdk30 lossy webp is always lossy. so far so
good. what that means in practice, however, is an sdk30 lossy webp with a quality setting of 100
no longer becomes lossless as it did with an sdk29 webp. and an sdk30 lossless webp no longer
becomes lossy with a quality setting less than 100 (as it did with an sdk29 webp).

so what do the quality settings mean for sdk30? according to android's documentation, for
lossless webp: "A quality of 0 means to compress quickly, resulting in a relatively large file size."
for lossy webp: "A value of 0 means compress for the smallest size." In other words, the
opposite meaning. for lossless webp, a quality of 100 results in a smaller file. for lossy webp, a quality of
100 results in a larger file. In other words, the opposite meaning.

android clarifies this by explaining that the quality setting for a lossless webp relates to the
"amount of effort":oops: applied to compress the image. (that reminds me of a setting available in zxing's
barcode api: public static final DecodeHintType TRY_HARDER.šŸ‘)

i ran tests for sdk29 and sdk30 (and corresponding android.jar).

i loaded a sample jpg file and converted it to webp at 3 quality settings ranging between 0 and 100. each range was
tested using the 3 webp formats (webp, webp lossless, webp lossy). so 9 tests per environment. the results were
the same for each of the test enviroments.

webp lossless and webp lossy format options were not introduced until sdk30, so i was surprised they worked with
sdk29. that is to say, they worked the same regardless of which api was used.

the simple webp format option was deprecated in sdk30 but still worked no problem, as expected.

the original jpg was 126379 bytes. the results for that particular image were:

saving sdk30-webplossless-0pct.webp
130326 bytes written.
saving sdk30-webplossless-50pct.webp
129008 bytes written.
saving sdk30-webplossless-100pct.webp
128344 bytes written.

saving sdk30-webplossy-0pct.webp
2494 bytes written.
saving sdk30-webplossy-50pct.webp
10470 bytes written.
saving sdk30-webplossy-100pct.webp
47862 bytes written.

saving sdk30-webp-0pct.webp
2494 bytes written.
saving sdk30-webp-50pct.webp
10470 bytes written.
saving sdk30-webp-100pct.webp
129040 bytes written.

run under api 29, the results were the same.

what's interesting, i found, was a lossless webp image compressed to the max isn't much different in size to
a virtually uncompressed version. the way in which the webp format differs from the lossy format corresponds
to the behavior described in the documentation (both versions resulted in the same file size at 0 and 50 quality,
but at 100, the webp version ballooned to 129kb, whereas the loss webp version, kept its lossiness.) also
striking was the amount of compression the lossy webp was capable of. the resulting quality was pathetic, but
if you were trying to compress top secret military images onto your mini-usb drive, size matters, as they say.

so it seems that the deprecated method is the easiest to deal with (at least until it disappears from the api). i
think that means @Pendrush's library is still the way to go. for anyone wishing to look at the new options, i'll
leave my utility up for a while (note: it's been updated to v 1.50)
 
Last edited:
Top