Inspired by this blog post by Peter Hrynkow, we implemented some new features to rokka to provide a solution to his question “Wouldn't it be great if you could get the compression of a JPEG and keep the transparency of a PNG?”. There's a new operation now in rokka, which allows you to extract just the alpha channel as a mask.
Let's take a picture. A PNG with an alpha channel surrounding the screen. It's 24 kB large (due to the use of pngquant and zopflipng on rokka here, it's smaller than usual, without those it would be 95 kB). The green pattern is the background and not part of the image.
This is just the JPEG of it, but it lost transparency in the process. Just white, no green pattern, not the desired result. But it's only 12 kB in size.
(as a side note, with lossy WebP, which supports transparency, the size would be in the same area as the JPEG one, just with transparency included, but that's not the topic here, since only chrome supports WebP)
Now with the solution of Peter, we need a PNG with just a mask for where it should be transparent. rokka can create that automatically for you with the same source image uploaded before, no additional work needed. The mask PNG has a size of 5 kB
You then stitch them together with an SVG snippet (more details, see in the blog post mentioned above) and embed that in your page.
<svg preserveAspectRatio="xMinYMin" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 232"> <defs> <mask id="canTopMask"> <image width="500" height="232" xlink:href="https://liip.rokka.io/dynamic/resize-width-500-height-232--alpha/7ed6427d9edaaaa60bf21f503022d56a208962aa.png"></image> </mask> </defs> <image mask="url(#canTopMask)" id="canTop" width="500" height="232" xlink:href="https://liip.rokka.io/dynamic/resize-width-500-height-232/7ed6427d9edaaaa60bf21f503022d56a208962aa.jpg"></image> </svg>
And the result looks like this:
The mask PNG and the JPEG together have a size of 17 kB, smaller than the initial 24 kB of the original PNG (or 95 kB unoptimized). For bigger pictures, the gain would be significantly more. And all you had to do is to upload one image with the correct alpha channels, create initially two different rokka stacks and an svg snippet. The conversion then is done automatically by rokka.
A little remark. As you can see, there's a little shadow below the screen in the alpha channel. This one is hardly noticable on the SVG version, due to more or less “double” transparency. We couldn't come up with a quick solution for this problem, but are happy to look into it, if anyone is depending on that. In short, this approach produces best results, if you only have 1-bit transparancy. For other cases, there may be small differences in the output.
Update: See our new post about making this even easier when using rokka.