{"id":6843,"date":"2015-01-14T01:55:59","date_gmt":"2015-01-14T05:55:59","guid":{"rendered":"http:\/\/www.useragentman.com\/blog\/?p=6843"},"modified":"2019-08-22T13:04:50","modified_gmt":"2019-08-22T17:04:50","slug":"using-webp-jpeg2000-jpegxr-apng-now-with-picturefill-and-modernizr","status":"publish","type":"post","link":"http:\/\/www.useragentman.com\/blog\/2015\/01\/14\/using-webp-jpeg2000-jpegxr-apng-now-with-picturefill-and-modernizr\/","title":{"rendered":"Using WEBP\/JPEG 2000\/JPEG-XR\/APNG Now With Picturefill and Modernizr"},"content":{"rendered":"<div class=\"importantNotes\">\n<h3>Blog Post Updates (Jan 30, 2019):<\/h3>\n<ul>\n<li>On January 30, 2019, we updated this article to reflect WEBP support for both Firefox and Microsoft Edge.<\/li>\n<li>On August 22, 2019, we updated this article to reflect Microsoft Edge > 18 will not support JPEG-XR anymore, due to it switching to the Blink rendering engine.<\/li>\n<li>At the original time of this writing, Modernizr was important to implement <code>&lt;picture&gt;<\/code> element for many browsers due to spotty support.  Today, IE11 is the only browser in use that doesn&#8217;t support it natively.  For this reason, and depending on your use-case, you may want to forgo using picturefill and have IE11 use the <code>&lt;img&gt;<\/code> tag fallback instead.<\/li>\n<\/ul>\n<\/div>\n<div id=\"dice-example\" class=\"resizable alignleft\">\n<iframe src=\"\/tests\/html5ImageConverter\/examples\/dice-compare\/dice.html\"><br \/>\n<\/iframe><\/p>\n<p><span class=\"resize-text\">Drag the ball around or <\/span><a href=\"\/tests\/html5ImageConverter\/examples\/dice-compare\/dice.html\">open demo in a new window<\/a><\/p>\n<\/div>\n<p>The demo on the left (which uses <a href=\"http:\/\/codyhouse.co\/gem\/css-jquery-image-comparison-slider\/\">Claudia Romano&#8217;s amazing Image Comparison Slider<\/a>) contains <strong>two alpha channeled images<\/strong> of dice placed on top of a multicolor background image.  If you are looking at it in a browser that supports alternate image formats (i.e. <strong>IE9+, Chrome 9+<\/strong> and modern versions of <strong>Safari<\/strong>, <strong>Firefox<\/strong> and <strong>Opera 11+<\/strong>) you&#8217;ll see that the image on the <strong>left hand side is smaller byte-wise<\/strong> than the image on the right.  This is because the left-hand image is using an image format that supports <strong>alpha channeling and lossy compression at the same time<\/strong>.  Use the slider to compare the two images and you&#8217;ll see the visual differences between them are negligible.  This demo is just one example of how you can use the <strong>HTML5 <code>&lt;picture&gt;<\/code> element to detect what kind of alternate image format<\/strong> (if any) your browser supports and serve the one that uses up the least amount of bandwidth.  You&#8217;ll also notice that if you resize the iframe that, as the demo&#8217;s viewport grows, the browser will load larger versions of the image, which is another great feature of the <code>&lt;picture&gt;<\/code> element.<\/p>\n<p>Although modern browsers support <code>&lt;picture&gt;<\/code> natively, IE11- doesn&#8217;t, so I added <strong>JPEG-2000, JPEG-XR and APNG<\/strong> to the mix so that developers could take advantage of these alternate image formats in IE (thanks to the picturefill team for accepting my pull request!)  This blog post will explain how to use picturefill or modernizr to use these formats, why you would want to use these image formats in your web projects, and what tools you can use to generate them.<\/p>\n<h2>More Image Formats? Why Should I Bother?<\/h2>\n<p>If you have been doing web development for a while, you have come across a few problems with the traditional image formats.  Let&#8217;s go over them here and see how the new image formats address them:<\/p>\n<h3>Reducing Blocky Artifacts in Highly Compressed Images<\/h3>\n<p>JPEGs images have a lot of unacceptable blocky artifacting the more you compress the file, due to the limitations of the way the JPEG format compresses the images.  <strong>WEBP, JPEG-2000 and JPEG-XR<\/strong> use different compression algorithms that (in general) <strong>look better the more the images are compressed.<\/strong>  To illustrate this, move the slider on CN Tower demo below:<\/p>\n<div id=\"cn-tower-example\" class=\"resizable aligncenter\">\n<iframe src=\"\/tests\/html5ImageConverter\/examples\/cn-tower-retina\/cn-tower.html\"><br \/>\n<\/iframe><\/p>\n<p><span class=\"resize-text\">Drag the ball around or <\/span><a href=\"\/tests\/html5ImageConverter\/examples\/cn-tower-retina\/cn-tower.html\">open demo in a new window<\/a><\/p>\n<\/div>\n<p>Here are some browser screenshots that to show the difference between the JPEG, JPEG 2000, JPEG-XR and WEBP:<\/p>\n<table class=\"dataTable screenshots\">\n<thead>\n<tr>\n<th>ImageMagick<br \/>encoded<br \/>JPEG (Firefox)<\/th>\n<th>JPEG 2000<br \/>(Safari)<\/th>\n<th>JPEG-XR<br \/>(IE9 &#8211; IE11, Edge < 18)<\/th>\n<th>WEBP<br \/>(Chrome,<br \/>Firefox 65+,<br \/>Edge 18+)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-jpg.png\" alt=\"cn-tower-jpg\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6929\" \/>\n<\/td>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-jp2.png\" alt=\"cn-tower-jp2\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6928\" \/>\n<\/td>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-jxr.png\" alt=\"cn-tower-jxr\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6930\" \/>\n<\/td>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-webp.png\" alt=\"cn-tower-webp\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6931\" \/>\n<\/td>\n<\/tbody>\n<\/table>\n<p><em>(Note that since the HTML <code>&lt;picture&gt;<\/code> element supports different renditions of the image at different breakpoints, I created three different renditions for each of the file formats.  You can <a href=\"\/tests\/html5ImageConverter\/examples\/cn-tower-retina\/cn-tower.html\">open the demo in a new window<\/a> in a desktop browser and resize the browser window to see them clearly, or just simply resize the above iframe)<\/em><\/p>\n<p>If you are using Chrome, Safari, Opera or Internet Explorer 9+, Edge or Firefox 65+ you will see <strong>JPEG artifacts on the right-hand side<\/strong> of the demo (especially in the clouds), while the <strong>left hand side doesn&#8217;t have them.<\/strong>  For this demo, I compressed the CN Tower JPEG using <a href=\"http:\/\/www.imagemagick.org\/\">ImageMagick<\/a> with a quality value of 20% and then compressed WEBP, JPEG-2000 and JPEG-XR images to the same file size as the JPEG image (or lower).  If you resize the iframe (or open the demo in a new window and resize the browser window) you will note that there are different image renditions at different breakpoints, and that this artifacting appears in all of the JPEG renditions.<\/p>\n<p>In 2015, Firefox didn&#8217;t support any of the alternate image formats and opted, in the short term, to create a more optimized JPEG compression library, <a href=\"https:\/\/github.com\/mozilla\/mozjpeg\">mozjpeg<\/a> (in the long term, they were apparently looking into supporting <a href=\"http:\/\/people.xiph.org\/~xiphmont\/demo\/daala\/update1.shtml\">Daala<\/a>, but given their adoption of WEBP in Firefox 65, I assume they abandoned that format).  To see how well mozjpeg works, I downloaded a <a href=\"https:\/\/github.com\/pornel\/mozjpeg\/releases\/tag\/v2.0.1\">precompiled binary<\/a> of mozjpeg for my Mac (since I had a huge amount of trouble compiling it from the source) and although the results are better, there is still a little bit of artifacting that remains in the JPEG renditions:<\/p>\n<div id=\"cn-tower-example-mozjpeg\" class=\"resizable aligncenter\">\n<iframe src=\"\/tests\/html5ImageConverter\/examples\/cn-tower-retina-mozjpeg\/cn-tower.html\"><br \/>\n<\/iframe><\/p>\n<p><a href=\"\/tests\/html5ImageConverter\/examples\/cn-tower-retina-mozjpeg\/cn-tower.html\">open demo in a new window<\/a><\/p>\n<\/div>\n<table class=\"dataTable screenshots\">\n<thead>\n<tr>\n<th>mozjpeg<br \/>encoded<br \/>JPEG (Firefox)<\/th>\n<th>JPEG 2000<br \/>(Safari)<\/th>\n<th>JPEG-XR<br \/>(IE9)<\/th>\n<th>WEBP<br \/>(Chrome)<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-moz-jpg.png\" alt=\"cn-tower-jpg\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6929\" \/>\n<\/td>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-jp2.png\" alt=\"cn-tower-jp2\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6928\" \/>\n<\/td>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-jxr.png\" alt=\"cn-tower-jxr\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6930\" \/>\n<\/td>\n<td>\n<img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/cn-tower-webp.png\" alt=\"cn-tower-webp\" width=\"140\" height=\"140\" class=\"alignnone size-full wp-image-6931\" \/>\n<\/td>\n<\/tbody>\n<\/table>\n<p>Even though some artifacting remains, mozjpeg is pretty good, so it is worth investigating when creating fallbacks for alternative image formats.<\/p>\n<h2>One Image Format To Rule Them All?<\/h2>\n<p>So, is WEBP, JPEG 2000 or JPEG-XR the better lossy image compression format?  The short answer is &#8220;it depends&#8221;.  I find that each one compresses certain images better than others.  Also, while these image formats tend to reduce the artifacting at lower compression ratios, JPEGs tend to keep more of the detail (although I believe that this would not be noticed by the casual user). In any event, the image compression wars have just started, and it will be interesting to see which on of these formats (if any) will come out on top.<\/p>\n<p>To get an idea how some of these formats compress compared to each other, here are a few more examples to take a look at:<\/p>\n<ul>\n<li>Lana Del Ray: compared with <a href=\"https:\/\/www.useragentman.com\/tests\/html5ImageConverter\/examples\/lana-del-rey-mozjpeg\/lana-del-rey.html\">ImageMagick (quality=20)<\/a> and <a href=\"https:\/\/www.useragentman.com\/tests\/html5ImageConverter\/examples\/lana-del-rey-mozjpeg\/lana-del-rey.html\">mozjpeg (quality=24)<\/a> JPEG files.<\/li>\n<li>Saturn: compared with <a href=\"https:\/\/www.useragentman.com\/tests\/html5ImageConverter\/examples\/saturn\/saturn.html\">ImageMagick (quality=30)<\/a> and <a href=\"https:\/\/www.useragentman.com\/tests\/html5ImageConverter\/examples\/saturn-mozjpeg\/saturn.html\">mozjpeg (quality=38)<\/a> JPEG files.<\/li>\n<\/ul>\n<p>When this article was originally written, WEBP was not supported by Microsoft or Mozilla.  We now have support on modern builds of Edge and Firefox.  The only holdout on WEBP is Apple, who as of 2019 still does not support this format.<\/p>\n<h3>Reducing the File Size of Alpha Channeled Images<\/h3>\n<p>If your web page needs a lot large alpha-channeled images  (i.e. image with a semi-transparent section), using PNGs will bloat the page due to the PNGs use of lossless compression.  However, using a modern web broser, you will see that alternate formats can reduce this bloat:<\/p>\n<div id=\"dice-drag-example\" class=\"resizable aligncenter\">\n<iframe src=\"\/tests\/html5ImageConverter\/examples\/dice-compare\/drag-test.html\"><br \/>\n<\/iframe><\/p>\n<p><a href=\"\/tests\/html5ImageConverter\/examples\/dice-compare\/drag-test.html\">open demo in a new window<\/a><\/p>\n<\/div>\n<p>Let&#8217;s compare the file sizes of the alternate image compared to the PNG original:<\/p>\n<table class=\"dataTable\">\n<thead>\n<tr>\n<th><\/th>\n<th>JPEG 2000<\/th>\n<th>JPEG-XR<\/th>\n<th>PNG<\/th>\n<th>WEBP<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th>320&#215;240<\/th>\n<td>2060<\/td>\n<td>22618<\/td>\n<td>55162<\/td>\n<td>11210<\/td>\n<\/tr>\n<tr>\n<th>600&#215;450<\/th>\n<td>13464<\/td>\n<td>48476<\/td>\n<td>143355<\/td>\n<td>26562<\/td>\n<\/tr>\n<tr>\n<th>1024&#215;768<\/th>\n<td>19613<\/td>\n<td>97979<\/td>\n<td>333557<\/td>\n<td>57388<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As you can see, the numbers for JPEG-2000 are especially impressive.  However, the file sizes of the alternate images will vary depending on the characteristics of the original image.  Up until now, quantizing a PNG (using programs like <a href=\"http:\/\/pngquant.org\/\">pngquant<\/a>) was the only way to get a smaller alpha channeled image from an original PNG (<a href=\"https:\/\/pornel.net\/\">Pornel<\/a> mentions it in his comment below).  While alternative image formats may give better results, sometimes they don&#8217;t.  Let&#8217;s take a look at this example of an alpha channeled image on top of an animated background:<\/p>\n<div id=\"saturn-example\" class=\"resizable aligncenter\">\n<iframe src=\"\/tests\/html5ImageConverter\/examples\/saturn-alpha\/saturn.html\"><br \/>\n<\/iframe><\/p>\n<p><a href=\"\/tests\/html5ImageConverter\/examples\/saturn-alpha\/saturn.html\">open demo in a new window<\/a><\/p>\n<\/div>\n<p>If you look at this Saturn demo in Safari, you will see the JPEG 2000 is 20% the size of the quantized PNG, with little noticeable loss of detail.  The WEBP and JPEG-XR versions are okay, but you can see they are &#8220;blurrier&#8221; than the PNG (and the WEBP and JPEG-XR versions are only around 70-80% of the original).  This is not always the case &mdash; sometimes WEBP is better, sometimes JPEG-XR is better, sometimes a quantized PNG is better.  <\/p>\n<h3 id=\"producing-truecolor-animations\">Producing Truecolor Animations<\/h3>\n<p>GIF animations only support 256 colors per frame, and can look blocky if they have a transparent background.  However, WEBP and APNG (supported by Firefox and Safari) support full truecolor animations <em>with<\/em> alpha channels.  For browsers that don&#8217;t support WEBP or APNG, you can use JPEG 2000 and JPEG XR files with <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Guide\/CSS\/Using_CSS_animations\">CSS Animations<\/a> (using the <code>step<\/code> property) to implement it for those browsers (thanks to <a href=\"http:\/\/blog.teamtreehouse.com\/css-sprite-sheet-animations-steps\">Treehouse&#8217;s Guil Hernandez&#8217;s excellent tutorial on how to do this<\/a>). Compare the animated GIF with the truecolor animation below and you&#8217;ll see the difference:<\/p>\n<div class=\"resizable aligncenter\">\n<iframe  src=\"\/tests\/html5ImageConverter\/examples\/ball-pres\/b-gif.html\"><br \/>\n<\/iframe><\/p>\n<p><span class=\"resize-text\">Drag the balls around or <\/span><a href=\"\/tests\/html5ImageConverter\/examples\/ball-pres\/b.html\">open demo in a new window<\/a><\/p>\n<\/div>\n<p>(Note: if you are using IE9, you&#8217;ll only see the animated GIF, since IE9 doesn&#8217;t support CSS3 Animations).<\/p>\n<p>Let&#8217;s do another file size comparison:<\/p>\n<table class=\"dataTable\">\n<thead>\n<tr>\n<th>Original APNG<\/th>\n<th>WEBP<\/th>\n<th>JPEG-2000<\/th>\n<th>JPEG-XR<\/th>\n<th>Quantized APNG<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>65993<\/td>\n<td class=\"hilite\">18396<\/td>\n<td class=\"hilite\">25036<\/td>\n<td class=\"hilite\">29534<\/td>\n<td>39874<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As you can see, WEBP, JPEG 2000 and JPEG-XR compress extremely well compared to the original animated PNG (a 27% to 44% savings in bandwidth!).  Note, though, the quantized APNG: it is roughly 60% smaller than the original.  Quantizing APNG&#8217;s can produce animations that are smaller in some cases, and I will discuss how to do this later.<\/p>\n<h2>Cool! How Can I Use Alternate Image Formats Today In All Browsers?<\/h2>\n<h3>The Wrong Way<\/h2>\n<p>You can use a regular image tag to place any of these images into your pages just like any other page:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n&lt;img src=\"myimage.webp\" \/&gt;\r\n<\/pre>\n<\/blockquote>\n<p>The problem is this method is that support for each of these image formats is not universal in all browsers, so although embedding a WEBP using the <code>&lt;img&gt;<\/code> tag will work in Chrome and Opera, it won&#8217;t work in the other browsers.  Here&#8217;s a table that illustrates browser support:<\/p>\n<p><!-- noautoformat on --><\/p>\n<table class=\"dataTable withCheckmarks\">\n<thead>\n<tr>\n<th><\/th>\n<th>WEBP<\/th>\n<th>JPEG-2000<\/th>\n<th>JPEG-XR<\/th>\n<th>APNG<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th>Chrome<\/th>\n<td class=\"check\">\u2714<\/p>\n<td><\/td>\n<td><\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<th>Safari<\/th>\n<td><\/td>\n<td class=\"check\">\u2714<\/td>\n<td><\/td>\n<td class=\"check\">\u2714<\/td>\n<\/tr>\n<tr>\n<th>Internet Explorer 8+<\/th>\n<td><\/td>\n<td><\/td>\n<td class=\"check\">\u2714<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<th>Microsoft Edge<\/th>\n<td class=\"check\">\u2714<\/td>\n<td><\/td>\n<td class=\"check\">\u2714<\/td>\n<td><\/td>\n<\/tr>\n<tr>\n<th>Firefox<\/th>\n<td class=\"check\">\u2714<\/td>\n<td><\/td>\n<td><\/td>\n<td class=\"check\">\u2714<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><!-- noautoformat off --><\/p>\n<p>So &#8230; how do we do this in a progressive-enhancement-like way?<\/p>\n<h3 id=\"using-picturefill\" name=\"using-picturefill\">Use <code>&lt;picture&gt;<\/code> For Still Images<\/h3>\n<p>In order to serve the right still (i.e. non-animated) image to the right browsers, developers should use the <code>&lt;picture&gt;<\/code> element.  If you are familiar with <code>&lt;video&gt;<\/code> tag, the syntax is quite similar: it is contains a list of <code>&lt;source&gt;<\/code> elements that say which urls contain content of a specific MIME type:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n&lt;picture&gt;\r\n  &lt;source srcset='dice.webp' type='image\/webp'&gt;\r\n  &lt;source srcset='dice.jxr' type='image\/vnd.ms-photo'&gt;\r\n  &lt;source srcset='dice.jp2' type='image\/jp2'&gt;\r\n  &lt;img srcset='dice-quant.png' alt='dice'&gt;\r\n&lt;\/picture&gt;\r\n<\/pre>\n<\/blockquote>\n<p>(Side note: notice JPEG-XR&#8217;s unusual MIME type (<code>image\/vnd.ms-photo<\/code>).  This is because JPEG-XR was originally a proprietary Microsoft image format called Windows Media Photo or HD Photo).<\/p>\n<p>As I mentioned earlier, Chrome and Opera are the only browsers that currently support the <code>&lt;picture&gt;<\/code> element natively.  Fortunately, the <a href=\"https:\/\/github.com\/scottjehl\/picturefill\">picturefill polyfill<\/a> adds support to the browsers that need it: just download the script from the official GitHub site and put this one script tag into the &lt;head&gt;<\/code>:<\/p>\n<blockquote class=\"code\">\n<pre>\r\n&lt;script async=true src=\/path\/to\/js\/picturefill.js&gt;&lt;\/script&gt;\r\n<\/pre>\n<\/blockquote>\n<p>Picturefill out of the box supports WEBP and SVG.  If you want to add support for any of the other file formats, you must do one of the following:<\/p>\n<ol>\n<li>Add support for the other formats by adding the supplementary scripts inside the <code>src\/includes<\/code> directory of the git repo.  They are conveniently called jxr.js, jp2.js and apng.js.  If you wanted to add support for all three, you would put this inside the <code>&lt;head&gt;<\/code>, right after picturefill&#8217;s <code>&lt;script&gt;<\/code> tag:<br \/>\n<blockquote class=\"code\">\n<pre>\r\n&lt;script async=true src=\/path\/to\/picturefill.js&gt;&lt;\/script&gt;\r\n&lt;script async=true src=\/path\/to\/jxr.js&gt;&lt;\/script&gt;\r\n&lt;script async=true src=\/path\/to\/jp2.js&gt;&lt;\/script&gt;\r\n&lt;script async=true src=\/path\/to\/apng.js&gt;&lt;\/script&gt;\r\n<\/pre>\n<\/blockquote>\n<\/li>\n<li>Alternatively, if you are familar with grunt, you could add support by running the grunt inside the picturefill git repo.  For example, to support all these formats, build picturefill with this grunt task:<br \/>\n<blockquote class=\"code\">\n<pre>\r\ngrunt support-types:jxr:jp2:apng\r\n<\/pre>\n<\/blockquote>\n<p>This will create a copy of picturefill.js in the git repo&#8217;s <code>dist<\/code> directory (as well as a minified version, picturefill.min.js).\n<\/li>\n<\/ol>\n<p>Two important things to to keep in mind: <\/p>\n<ol>\n<li><strong>If you want to ensure picturefill works correctly in IE9,<\/strong> you must put in some conditional comments inside your <code>&lt;picture&gt;<\/code> for it to work correctly:<br \/>\n<blockquote class=\"code\">\n<pre>\r\n&lt;picture&gt;\r\n  <span class=\"hilite\">&lt;!--[if IE 9]&gt;&lt;video style='display: none;'&gt;&lt;![endif]--&gt;<\/span>\r\n  &lt;source srcset='dice.webp' type='image\/webp'&gt;\r\n  &lt;source srcset='dice.jxr' type='image\/vnd.ms-photo'&gt;\r\n  &lt;source srcset='dice.jp2' type='image\/jp2'&gt;\r\n  &lt;!--[if IE 9]&gt;&lt;\/video&gt;&lt;![endif]--&gt;\r\n  <span class=\"hilite\">&lt;img srcset='dice-quant.png' alt='dice'&gt;<\/span>\r\n&lt;\/picture&gt;\r\n<\/pre>\n<\/blockquote>\n<p>This is due to an odd quirk in IE9 where it won&#8217;t recognize <code>&lt;source&gt;<\/code> unless wrapped in a <code>&lt;video&gt;<\/code> tag.\n<\/li>\n<li><strong>If the images don&#8217;t show up correctly, <\/strong>make sure that all the mime types in the <code>&lt;source&gt;<\/code> elements above are set on your web server.  I have only had this issue on one of the servers I have encountered, but it&#8217;s something to keep in mind (thanks to <a href=\"https:\/\/twitter.com\/Cory_Dowd\">Cory Dowd<\/a> for reminding me about this).<\/li>\n<\/ol>\n<p><a class=\"exampleLink\" href=\"https:\/\/github.com\/scottjehl\/picturefill\">Download the latest version of Picturefill from GitHub<\/a> <\/p>\n<h3>Use Modernizr For Animated Images<\/h3>\n<p>As I mentioned before, the WEBP and APNG file formats support animations out of the box.  In order to give IE10+ animated goodness, I used CSS step animations to do the animation using a sprite sheet.  Since Modernizr currently doesn&#8217;t detect JPEG 2000, I also included a small Javascript snippet to add JPEG 2000 support for it based on some code from <a href=\"https:\/\/github.com\/leechy\/imgsupport\">Andreyka Lechev&#8217;s imgsupport.js script<\/a> (I will send a merge request to the modernizr team in order to add JPEG-2000 support to it soon).  For reference here is a link to <a href=\"https:\/\/www.useragentman.com\/tests\/html5ImageConverter\/js\/modernizr.custom.29822.js\">the custom Modernizr script and the JPEG 2000 detection script<\/a>.  Here is the spritesheet I used to generate the CSS animation in the above demo: <\/p>\n<div class=\"spritesheet\">\n<img decoding=\"async\" src=\"https:\/\/www.useragentman.com\/tests\/html5ImageConverter\/examples\/ball-pres\/b-stitched.png\" \/>\n<\/div>\n<p>I then converted this file to JPEG 2000 and JPEG-XR format.  I then created a div with a class (in this case, &#8216;b&#8217;) &#8230;<\/p>\n<blockquote class=\"code\">\n<pre>\r\n&lt;div class='b'&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<\/blockquote>\n<p>&#8230; and then used the following CSS recipe to use CSS animations on only the JPEG-2000\/JPEG-XR browsers: <\/p>\n<blockquote class=\"code\">\n<pre>\r\n\r\n\/* \r\n * The animated image in this case is 100x100, so make \r\n * the container that size\r\n *\/\r\n.b {\r\n  width: 100px;\r\n  height: 100px;\r\n}\r\n\r\n\/* WEBP supports animations .. no need for CSS *\/\r\nhtml.webp .b {\r\n  background: url('.\/b.webp');\r\n}\r\n\r\n\/* APNG also supports animations ... no need for CSS *\/\r\nhtml.apng .b {\r\n  background: url('.\/b.png');\r\n}\r\n\r\n\/* \r\n * If the browser doesn't support APNG \r\n * *but* supports CSS Animations, \r\n * use the PNG version of the sprite and animate it using \r\n * the \"bplay\" animation (coded at the bottom of the \r\n * stylesheet).  The fallback for browsers that support\r\n * animations is the PNG spritesheet ... the JPEG-2000 and\r\n * JPEG-XR spritesheets will be defined in the CSS rules\r\n * that follow.\r\n *\/ \r\nhtml.no-apng.no-webp.cssanimations .b {\r\n    background: url('.\/b-stitched.png') left center;\r\n\r\n    \/* \r\n     * the animation takes 1 second to play, there are \r\n     * 20 frames in the animation, and we loop the \r\n     * animation forever\r\n     *\/\r\n    animation: bplay 1000ms steps(20) infinite;\r\n    -webkit-animation: bplay 1000ms steps(20) infinite;\r\n}\r\n\r\n\/*\r\n * If the browser supports JPEGXR (IE10), then use the JXR \r\n * version instead.  Note that this will *not* be used by\r\n * IE9 since it doesn't support CSS animations.\r\n *\/\r\nhtml.no-apng.no-webp.jpegxr.cssanimations .b {\r\n    background: url('.\/b-stitched.jxr') left center;\r\n}\r\n\r\n\/*\r\n * Likewise, if the browser supports JPEG 2000, use\r\n * the .jp2 version of the sprite.\r\n *\/ \r\nhtml.no-apng.no-webp.jpeg2000.cssanimations .b {\r\n    background: url('.\/b-stitched.jp2') left center;\r\n}\r\n\r\n\/*\r\n * For other browsers that don't support CSS animations\r\n * at all, we fallback to the animated GIF.\r\n *\/\r\nhtml.no-apng.no-webp.no-cssanimations .b {\r\n    background: url('.\/b.gif') left center;\r\n}\r\n\r\n\/* \r\n * Here we describe the CSS animation itself. Note that\r\n * the background position is set to the negative value \r\n * of the width of the sprite sheet\r\n *\/\r\n@keyframes bplay {\r\n  100% { background-position: -2000px; }\r\n}\r\n\r\n\/* Webkit variant for older WebKit browsers *\/\r\n@-webkit-keyframes bplay {\r\n  100% { background-position: -2000px; }\r\n}\r\n<\/pre>\n<\/blockquote>\n<h2>How to create WEBP\/JPEG-XR and JPEG 2000 images<\/h2>\n<p>There are a few Photoshop and GIMP plugins you can use today to create these images, as well as a few command line tools.  Here is a great list to get you started:<\/p>\n<p><!-- noautoformat on --><\/p>\n<table class=\"dataTable\">\n<thead>\n<tr>\n<th><\/th>\n<th>WEBP<\/th>\n<th>JPEG-XR<\/th>\n<th>JPEG 2000<\/th>\n<th>APNG<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<th>Command Line<\/th>\n<td><a href=\"https:\/\/developers.google.com\/speed\/webp\/\">cwebp<\/a> by the Google WebP Team<\/td>\n<td>JxrEncApp (part of <a href=\"https:\/\/jxrlib.codeplex.com\/\">jxrlib<\/a> by Microsoft Research.  You have to compile yourself &mdash; I have done so successfully on a Mac and Windows (using <a href=\"https:\/\/www.cygwin.com\">Cygwin<\/a>) with no problems.  You can also use <a href=\"http:\/\/www.xnview.com\/en\/nconvert\/\">nconvert<\/a>, but it doesn&#8217;t compress as well as JxrEncApp in my opinion.<\/td>\n<td><a href=\"http:\/\/kakadusoftware.com\/downloads\/\">kdu_compress<\/a> by <a href=\"http:\/\/kakadusoftware.com\/software\/\">Kakadu Software<\/a> (payware, free for non-commercial use) and <a href=\"http:\/\/www.openjpeg.org\/\">OpenJPEG<\/a> (open source, but I was unsuccessful using it for alpha channeled images)<\/td>\n<td><a href=\"http:\/\/sourceforge.net\/projects\/apngasm\/\">apngasm<\/a> by Max Stepin.  I also used <a href=\"apngdis.sourceforge.net\/\">apngdis<\/a> to disassemble the frames of existing APNG files and <a href=\"http:\/\/pngquant.org\/\">pngquant<\/a> to quantize these frames to make them smaller before assembling them back into a smaller APNG file.  I finally used <a href=\"http:\/\/apng2gif.sourceforge.net\/\">apng2gif<\/a> to create a GIF fallback for older web browsers.<\/td>\n<\/tr>\n<tr>\n<th>Photoshop Plug-ins<\/th>\n<td><a href=\"http:\/\/telegraphics.com.au\/sw\/product\/WebPFormat\">WebP Format<\/a> by Toby Thain<\/td>\n<td><a href=\"http:\/\/research.microsoft.com\/en-us\/um\/redmond\/groups\/ivm\/JPEGXR\/\">JPEG XR File Format Plug-in for Photoshop<\/a> by Microsoft Research<\/td>\n<td><a href=\"http:\/\/www.fnordware.com\/j2k\/\">j2k<\/a> by fnord software.  (Note that under OSX, you can also export JPEG-2000 images using the built in Preview tool).<\/td>\n<td>None yet, but a fellow named Rei Kagetsuki has promised that <a href=\"https:\/\/www.kickstarter.com\/projects\/374397522\/apngasm-foss-animated-png-tools-and-apng-standardi\">one will be available soon<\/a> <\/td>\n<\/tr>\n<tr>\n<th>GIMP Plug-ins<\/th>\n<td><a href=\"https:\/\/code.google.com\/p\/gimp-extensions\/\">GIMP Extensions<\/a>  (Windows only)<\/td>\n<td><a href=\"http:\/\/registry.gimp.org\/node\/25508\">JPEG XR plugin<\/a> by Chrysler<\/td>\n<td><a href=\"http:\/\/registry.gimp.org\/node\/9899\">jp2\/denoise\/ihalf<\/a> by Akkana Peck<\/td>\n<td><a href=\"http:\/\/registry.gimp.org\/node\/24394\">APNG Plug-In<\/a> by daisuke<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><!-- noautoformat off --><\/p>\n<p>Note that for all the demos, I used the command line tools listed above as well as <a href=\"http:\/\/www.imagemagick.org\/\">ImageMagick<\/a> and <a href=\"https:\/\/github.com\/mozilla\/mozjpeg\">mozjpeg<\/a> for the JPEG images &mdash; I have not investigated the GIMP or Photoshop plugins yet so your milage may vary on those.  To simplify things, I created a set of BASH shell script (which I call the <a href=\"https:\/\/github.com\/zoltan-dulac\/html5ImageConverter\">HTML5 Image Converter<\/a>), that uses the command line tools listed above to create all of the files quickly from a PNG source.  One you install the above command line tools and the shell script on your system, you can do the conversion magic on still (non-animated) image using a command like this:<\/p>\n<blockquote class=\"code\">\n<pre>\r\nhtml5ImageConverter.sh --webp-quals=19.5 --jxr-quals=30 --jpg-quals=40 \\\r\n  --jp2-rates=0.2\/0.4\/0.2 --jpg-quals=40 --has-alpha image.png\r\n<\/pre>\n<\/blockquote>\n<p>where:<\/p>\n<ul>\n<li><code>--webp-quals<\/code> is the compression quality of the WEBP image (1 &#8211; most compressed, 100 &#8211; most compressed).  Default is 85.<\/li>\n<li><code>--jxr-quals<\/code> is the compression quality of the JXR image (again, 1 &#8211; most compressed, 100 &#8211; most compressed). Default is 85.<\/li>\n<li><code>--jpg-quals<\/code> is the compression quality of the JPG image (again, 1 &#8211; most compressed, 100 &#8211; most compressed). Default is 85.<\/li>\n<li><code>--jp2-rates<\/code> is the compression rate of the JP2 image.  Default is 1.0.  More information about this can be found on <a href=\"http:\/\/www.dlxs.org\/docs\/12\/class\/image\/jpeg2000.html\">this page by the University of Michigan<\/a>.<\/li>\n<li><code>--has-alpha<\/code> is optional and only be used if the image has an alpha channel.<\/li>\n<li><code>--use-mozjpeg<\/code> is optional if you want to create JPEG fallbacks compressed with mozjpeg instead of ImageMagick (it will give warnings if mozjpeg is not installed).<\/li>\n<li><code>--jxr-ie9-fix<\/code> fixes a sometimes unnoticable bug in IE9 where JPEG-XR image will have a small semi-opaque gray border around it.<\/code>\n<li><code>--jxr-nconvert<\/code> will convert JPEG-XR images with <a href=\"http:\/\/www.xnview.com\/en\/nconvert\/\">nconvert<\/a> instead of JxrEncApp.<\/ul>\n<p>This command creates images in all the formats listed above, as well as giving you a handy HTML page that shows how the image looks compared to the JPEG (just like the examples in this blog post).<\/p>\n<p>You can also create different renditions of the image you want using the <code>&lt;picture&gt;<\/code> element&#8217;s support of <code><a href=\"http:\/\/ericportis.com\/posts\/2014\/srcset-sizes\/\">srcset<\/a><\/code> using the <code>--sizes<\/code> parameter.  Here is an example where we will create three renditions, one for the image scaled down to a width of 320 pixels, another with a width of 600 pixels, and a final one of 1024 pixels:<\/p>\n<blockquote class=\"code\">\n<pre>\r\nhtml5ImageConverter.sh --sizes=320\/600\/1024  --webp-quals=50 --jpg-quals=70 \\\r\n  --jp2-rates=0.1\/0.1\/0.4 --jxr-quals=15 image.png\r\n<\/pre>\n<\/blockquote>\n<p>The WEBP, JPG and JXR compression quality of the above example are 50%, 70% and 15% respectively &mdash; you have a different quality for each rendition if you like by separating this with slashes (like the <code>--jp2-rates<\/code> does).<\/p>\n<p><strong>Note that the HTML5 Image Converter will also embed what command-line switches that were used to generate the images inside a comment in the generated HTML file. <\/strong> This is useful if you want to try different values later or if you want to replicate my results.  Hopefully this will assist others if they want to do more research on these image formats.<\/p>\n<h3>How About Creating Animated Images<\/h3>\n<p>Inside the HTML5 Image Converter&#8217;s git repository, there is another script (creatively called &#8220;The HTML5 Animated Image Converter&#8221;) that converts an APNG file to animated WEBP.  It also makes image sprites using JPEG 2000, JPEG-XR and non-animated PNG as well as a CSS stylesheet that uses the CSS3 Animation trick above for browsers that support those formats and CSS3 animations.  It finally creates an animated GIF using <a href=\"http:\/\/apng2gif.sourceforge.net\/\">apng2gif<\/a> as a fallback for browsers that don&#8217;t do CSS animations (e.g. IE9).  In order to create the animated ball demo above, I used the following command:<\/p>\n<blockquote class=\"code\">\n<pre>\r\nhtml5AnimatedImageConverter --input-apng --output=b --ms=50 --jxr-quality=80 --jp2-rate=1.0 --webp-quality=50 --apng-quant ballanim.png\r\n<\/pre>\n<\/blockquote>\n<p>where:<\/p>\n<ul>\n<li><code>--input-apng<\/code> denotes that the input is an animated PNG (note: using still images will be supported in a later release).<\/li>\n<li><code>--output=b<\/code> will create outfile files with the filenames beginning with &#8220;b.&#8221; (i.e. b.png, b.webp,  b-stitched.jxr, b-stitched.jp2, b-stitched.png, b.gif, b.css and b.html)<\/li>\n<li><code>--ms=50<\/code> tells the generator to create animations with each frame appearing for 50 milliseconds.<\/li>\n<li><code>--jxr-quality<\/code>, <code>--webp-quality<\/code> and <code>--jp2-rate<\/code> attributes set to the quality\/rate values in the same way that the HTML5 Image Animator does.<\/li>\n<\/ul>\n<p><a class=\"exampleLink\" href=\"https:\/\/github.com\/zoltan-dulac\/html5ImageConverter\">Download the HTML5 Image Converter for GitHub<\/a><\/p>\n<p>When I created this shell script, I found a few gotchas about using these command line tools:<\/p>\n<h3>JPEG-XR<\/h3>\n<p>JxrEncApp is quite difficult to understand to use at first, since it lacks documentation and it will fail silently sometimes without saying why (Microsoft: if you are reading this, please take positive steps to fix JxrEncApp so web developers can support this promising format!) <strong>(Update: Gary Sullivan from Microsoft was kind enough to <a href=\"#comment-766612 \">speak to the issues I have discussed<\/a>)<\/strong>.  However, I was fortunate that <a href=\"http:\/\/www.codeplex.com\/site\/users\/view\/christoph_hausner\">Christoph Hausner<\/a>, who has been playing around with JPEG-XR files for a while now, was kind enough to give me quite a few pointers.  Here is a summary of them:<\/p>\n<ol>\n<li>When you are converting an image using JxrEncApp, it is best doing so using an uncompressed TIFF.  If you have a PNG, JPEG or other file that you need converted, you can do so using the following ImageMagick command:<br \/>\n<blockquote class=\"pre\"><p>\n<code><br \/>\nconvert img.png -compress none img.tif<br \/>\n<\/code>\n<\/p><\/blockquote>\n<\/li>\n<li>IE9 has a known issue where it will render a light gray border around some JPEG-XR images (<a href=\"http:\/\/twitter.com\/njdoyle\">Nicholas Doyle<\/a> has <a href=\"http:\/\/calendar.perfplanet.com\/2013\/browser-specific-image-formats\/\">written this in his article about WEBP and JPEG-XR<\/a>.  I asked Christoph about this bug, and he suggested the following:<br \/>\n<blockquote class=\"person-quote\"><p>\nYou have a few options to work around this bug. You can either disable overlap filtering (jxrencapp option <code>-l 0<\/code> &#8230;  or encode all your images in 32bppPRGBA.<\/p>\n<p>Disabling the overlap filter is generally recommended only for losslessly compressed images but discouraged for lossy compression as it leads to visible block artifacts for higher compression ratios.<\/p>\n<p>The other option is to encode your alpha channel as pre-multiplied alpha. In your case you would pass <code>-define tiff:alpha=associated<\/code> to ImageMagick to create a PRGBA TIFF file, the options for jxrencapp stay the same.<\/p>\n<p>If your input image has no alpha channel, you can add a dummy (fully opaque) one, save again as PRGBA TIFF and then encode to JXR with alpha quantization -Q 2. This still encodes the dummy alpha channel losslessly and has very little overhead compared to a non-alpha image. The lossless default -Q 1 seems to unnecessarily bloat the file.\n<\/p><\/blockquote>\n<p>Note that I have added support for the <code>-l 0<\/code> fix to the HTML5 Image Converter via the <code>--jxr-ie9-fix<\/code> paramater.  I was not successful doing implementing the <code>-define tiff:alpha=associated<\/code> fix (did I mention that JxrEncApp is hard to use?)<\/li>\n<li>You can use <a href=\"http:\/\/www.xnview.com\/en\/nconvert\/\">nconvert<\/a> to convert to the JPEG-XR format (the HTML5 Image Converter will use it via the <code>--jxr-nconvert<\/code> paramater.  In practice, however, I find that JxrEncApp does a better job at compressing JPEG-XR format than nconvert does (although it <em>does<\/em> get rid of the IE9 gray-border-bug).\n<\/li>\n<\/ol>\n<h3>JPEG-2000<\/h3>\n<p>When using <a href=\"http:\/\/kakadusoftware.com\/downloads\/\">kdu_compress<\/a>, you&#8217;ll notice it does not have a flag for quality like the other image processing tools for the other image formats do.  In order to work around this, I played around with the <code>rate<\/code> option in order to control the amount of compression.  <\/p>\n<p>I would have liked to compare kdu_compress with <a href=\"http:\/\/www.openjpeg.org\/\">OpenJPEG<\/a>, but unfortunately I could figure out how to make alpha channeled JPEG 2000 files with it.  If anyone has any information on this, please let me know in the comments below.<\/p>\n<h3>APNG<\/h3>\n<p>APNG files can be quite large compared to the other file formats, due to its use of PNG&#8217;s lossless compression algorithm.  In order to shrink them down a bit, I used apngdis to produce static PNGs of all the frames, used pngquant to quanitize each of the frames, and then assembled these frames into a new APNG using apngasm.  This works for a lot use-cases, but keep in mind that a lot of times you won&#8217;t always get the same compression savings that you can with JPEG-XR, JPEG 2000 and WEBP.<\/p>\n<h3>WEBP<\/h3>\n<p>By far, the WEBP tools that Google provides are the easiest of all the tools I used for the altenative image formats.  I had no issues getting started, and I expect you will have no issues as well. Kudos to the WEBP team!<\/p>\n<h2>Conclusions<\/h2>\n<p>This is just the beginning.  There will be a lot more blog posts comparing these image formats, and I believe it is only a matter of time before one wins out.  Feel free to voice your opinion on these formats below (I&#8217;m sure that this debate will get heated at times).<\/p>\n","protected":false},"excerpt":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.useragentman.com\/blog\/wp-content\/uploads\/2015\/01\/teaser.png\" alt=\"teaser\" width=\"250\" height=\"205\" class=\"alignnone size-full wp-image-6960\" \/> WEBP, JPEG 2000, JPEG-XR, APNG &#8230; these image formats have features that are not available in the traditional GIF\/JPEG\/PNG\/SVG image stack, like <strong>animation<\/strong>, <strong>lossy compressions paired with alpha channels<\/strong> and <strong>better quality at higher compression levels<\/strong>. However, each browser seems to support only some of these formats. With the <code>&lt;picture&gt;<\/code> element, along with the picturefill polyfill, you can use these great formats today while using the older formats for an old-fashioned fallback. This blog post will explain how to use <strong>picturefill or modernizr<\/strong> to use these formats, <strong>why you would want to use these image formats<\/strong>, and <strong>what tools you can use to generate them.<\/strong> <\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-6843","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/6843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/comments?post=6843"}],"version-history":[{"count":137,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/6843\/revisions"}],"predecessor-version":[{"id":7838,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/posts\/6843\/revisions\/7838"}],"wp:attachment":[{"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/media?parent=6843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/categories?post=6843"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.useragentman.com\/blog\/wp-json\/wp\/v2\/tags?post=6843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}