Transparent JPG, an efficient PNG compression method

Photos with transparent background are commonly used on ecommerce. This images are typically served as PNGs, a lossless format which is not very efficient compressing photos. There are some more efficient alternatives to compress transparent images, like the WebP format, but this format is not supported in iPhones and Safari.

JPEG is the universally used photo compression format, but it does not support transparency. However, there are some tricks to show JPEG photos with a transparent background:

  • We can use CSS to make a JPEG transparent using mask-image on moderm web browsers.
  • We can also convert PNGs to transparent JPEGs using the SVG format to make it looks with no background.

Both techniques are based on masking. So the trick is to use a photo and a mask to remove the background. We need then to convert the PNG to an optimized JPEG photo without any transparency first. And second to extract the alpha mask as a 8-bit PNG image (this is just a grayscale image that represents the foreground as white and the backgroud as black).

  1. First to convert optimized JPEG photo without any transparency.
  2. Second to extract the alpha mask as a 8-bit PNG image.

The first is a regular JPEG file without any transparency. The second is an 8-bit PNG (alpha mask). This is just a grayscale image that represents the transparent background. Noticie how the PNG is only 34kB; that's because it contains so few colors and no transparency.

jpeg photo with no transparency
png8 alpha mask

Note how the JPG image is only 85kB and the PNG mask 34kB.

Transparent JPEG with CSS

To directly show the image as transparent using the CSS option, we need to use the style like bellow:

<img src="https://abraia.me/docs/transparent-jpg/t-shirt-2068353_1920_image.jpg"
  style="mask-image:url('https://abraia.me/docs/transparent-jpg/t-shirt-2068353_1920_mask.png');
         mask-size:100% 100%;
         -webkit-mask-image:url('https://abraia.me/docs/transparent-jpg/t-shirt-2068353_1920_mask.png');
         -webkit-mask-size:100% 100%;
         width:100%;height:auto;">

Note how mask-image has some browser support limitations, but the result it is really impressive, because we are showing a transparent image using 119kB instead of the 1.6MB that demands the original PNG image.

Transparent JPEG with SVG

The other option to show JPEG images like they were transparent is to convert it to SVG. For instance, the image bellow is 1.6MB in PNG and it is reduced to 185kB using the SVG format, when images are attached to the SVG file.

original transparent png
efficient transparent jpeg as svg

So, the trick is created with a little snippet of inline SVG, as bellow:

<svg viewBox="0 0 1920 1440">
  <defs>
    <mask id="canTopMask">
      <image
        width="1920"
        height="1440"
        xlink:href="t-shirt-2068353_1920_mask.png"></image>
    </mask>
  </defs>
  <image
    mask="url(#canTopMask)"
    id="canTop"
    width="1920"
    height="1440"
    xlink:href="t-shirt-2068353_1920_image.jpg"></image>
</svg>

Here the alpha channel image is included as a mask which is then applied to the JPEG to create the transparent region. As a result, a transparent JPG image is created.

This trick can have some problems with old browsers, but most of then work fine with the SVG inline.