Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Using SVG to Shrink Your PNGs (peterhrynkow.com)
217 points by labwire on Jan 22, 2015 | hide | past | favorite | 40 comments


There is a tool for that:

https://github.com/mahonnaise/svgjng/

    java -jar svgjng.jar <rgba image> <svgz file name> [color quality] [alpha quality]
It tries PNG and JPEG for RGB and alpha and then uses whichever ended up smaller.

Gallery: http://kaioa.com/b/1102/svgjng/index.html

"SVGZ (auto)" means default parameters. I.e. just:

    java -jar svgjng.jar foo.png foo.svgz


Cool project. Seems dead (last commit in 2011 and no forks), but hey... if it works it works right?


The project itself is done. It does everything it's supposed to do. Some things could be done a bit more efficiently, but it seems to be fast enough. The readme is a bit outdated, but the usage bit (which is printed if you run it without arguments) covers everything.

I kinda lost interest in this project, because, back then, it actually didn't work. The SVG spec had to be fixed first and Chrome didn't even display those images at all due to a bug.

Basically, the problem with the spec was that it required the masks to use some nonsensical color space. Half of the implementations didn't, because it didn't make any sense and because the wording was extremely confusing.

Anyhow, the spec got changed and browsers started to implement this newer version of the spec. Nowadays, it actually does work.

Well, that's basically the whole story. That's why there isn't an article which promotes it. There were showstoppers which made it completely unusable.


About 3 or so years ago, the senior designer at my previous job submitted a hard design to a client containing a banner with not-quite-rounded-but-almost corners that had to have transparency and would have to change color over time. As senior dev then, I never got to approve the design before it got out and I can still remember the horror when I witnessed what he had done.

I ended up trying a whole bunch of different ways to solve the problem, one of which was very similar to this method. As the author points out however, this does not work in IE8 among other things, and at the time this was a requirement... I ended up using different combinations with different levels of quality depending on the browser, a true nightmare which ended up eating a third of the budget for no justifiable reason.

In any case, the fact that we have to go through tricks like this to achieve both transparency and decent compression is pretty disappointing. But what I find maybe even sadder is the amount of resources we sometimes spend on things which seem incredibly frivolous, to me anyway. I'm sure Sapporo have pretty deep pockets, which the author rightly took advantage of, but that doesn't make it any less superficial.


> I'm sure Sapporo have pretty deep pockets, which the author rightly took advantage of, but that doesn't make it any less superficial.

Seems a bit unfair as a comparison. He is talking about a simple trick to save time and money and you compare it to a different expensive mistake.

The visual results may be the same, but it's not necessarily the case that he rightly took advantage of anyone.


I don't think deep pockets has anything to do with it. I have plenty of clients with very shallow pockets who would gladly pay me to find a better solution than a slow 2 MB image download or a compromised visual style.


I think I have an idea on how to support IE8 and do this without SVG.

1. Create a JPG of the can and trim the edges off completely

2. Create a PNG of the can and remove the insides completely, leaving only the edges

3. Overlay the JPG on top of the PNG using CSS absolute positioning or background+foreground image or similar

Since the JPEG comprises only the inner part of the image, it doesn't affect anything. The PNG comprises the outer edges of the image and you get the desired transparency on the edges.


Good idea! To go further, you could cut the PNG into four strips (top, bottom, left, right) so the browser doesn't have to store the enormous rectangle of transparent pixels making up the insides of the PNG.


The few bytes you'd save on the png would be lost on the few bytes of additional markup you'd need in your html.


The browser still has to store that uncompressed empty area though, so it would use more memory and probably take slightly longer to paint on a slow device.


I was under the impression that PNG is actually quite good at compressing areas of a singular solid color (or in this case solid transparency). It just fails at every-pixel-is-different cases, where JPG is better.

Furthermore, I'm pretty sure a slow device would take longer to paint four separate images due to the overhead of having four of them.


In order to draw the PNG, the browser has to decode it, including the transparent pixels. I'm also pretty sure (though I haven't tested this) that the overhead of painting four smaller images is negligible in comparison to the cost of blending the entire center area.

Many sites are very bad about this, e.g. this sprite sheet from linkedin: https://static.licdn.com/scds/common/u/img/sprite/sprite_glo... which, when decoded, takes up ~9MB of almost entirely empty memory. Check out the "Optimizing Web Content in UIWebViews and Websites on iOS" talk on https://developer.apple.com/videos/wwdc/2012/ for more info about not wasting memory on mobile web sites.


Furthermore, I'm pretty sure a slow device would take longer to paint four separate images due to the overhead of having four of them.

Back in the old days of 2D game development, some games would use a technique called "dirty rectangles" to repaint selected areas of the screen that had changed. Windowing systems like X did/do something similar with "damage" or "expose" events (can't remember the exact name).

It's because the logic to handle many separate small rectangles is less expensive than the loop and memory bandwidth to paint one big one.


Nitrogen's point is that most (all?) browsers decompress the image in memory.


Yes, the website seems to waste a lot of resources: 66 requests, 1.9 MB Specially since it is so minimalist. The beer file (can-top.jpg) is 260kb, could easily shrink to half of that without losing too much quality.

Also, some code left over:

console.log("toto");


I've done this for years in the Mystery Studio game framework. Transparent PNGs were always split into a RGB and an Alpha mask. Most of the time it was fine to save the RGB as a relatively good JPEG (say 90%) but you could go crazy with the alpha mask - maybe JPEG 30% even.

The exceptions were the assets where the alpha channel was used for picking (e.g. to detect drag and drop on a puzzle piece). In that case the settings were overriden for that particular asset to something like PNG8 (which also compresses fine since most alpha masks are mostly black and white with only some grey pixels at the edges due to antialiasing).

That and auto-cropping the assets - the engine has the concept of a "virtual canvas" so we could have full-screen transparent PNGs with only a small button in it, which the pipeline would reduce to the area that had the contents; but on the engine side you just treated it as a full-screen image, so you could place it at (0, 0) and the button would still appear wherever the artist had put it.

We got crazy reductions in file size using this one weird trick! Good times.


Misleading title, but this is a really clever hack. I'm surprised I haven't heard of it before, since JPEG's lack of an alpha channel is a common complaint.


You likely haven't heard of this before because, frankly, SVG has been a "no go" area since it had such shoddy IE support until recently [0]. And like it or not IE still claims a large enough market share to matter.

IE 10 (which offered a richer SVG experience) wasn't available until Sept 2012. Since then 10+ has gained market share, but there are still a lot of XP and Vista users causing problems (or pirate Windows 7 users who cannot install SP1).

SVG is actually really cool. About damn time it is getting usable across the board. Hopefully two years from now using SVG will be a "no brainer" in terms of backwards compatibility.

[0] https://en.wikipedia.org/wiki/Scalable_Vector_Graphics#Nativ...


I've been working with SVGs quite a bit lately. Dealing with them is at times rewarding, and others extraordinarily frustrating.

Case in point: different browsers handle adding an SVG filter onto a DOM element / SVG parent element / SVG child element very differently (in Firefox, if an SVG element that holds a filter is display:none, and you apply that filter to an element that is visible, the filter not only is not applied - but the element it is applied to also becomes display:none). Unfortunately, it's also not one of those things you can feature detect for: out come the user agent tools again...

But yes, SVG is very very cool. For our use case, even IE9 is fairly up to par with it.


Our team used pngquant (http://pngquant.org/) recently to reduce complex, high-res PNGs to about 33% of their original size. It gave us the size benefits of lossy compression while retaining the PNG alpha channel. It seems to be good enough to tide us over until WebP gains traction (not holding my breath).


IIRC, you're limited to 256 colors total (including those with an alpha channel)... it works pretty well, but it really depends on the picture in question. I use pngquant all the time myself... :-)


Color quantizer (http://x128.ho.ua/color-quantizer.html) lets you use up to 12-bit (4096 colors). For command line, the author has TruePNG (http://x128.ho.ua/pngutils.html).


That's interesting, since there isn't a 12-bit PNG format. Do they leave it in 24 bit then, and just rely on better compression due to fewer unique bit combinations?


It looks that way. Irfanview reports 24bpp for images saved when I selected > 256 colors in CQ.


This is a clever alternative to PNG8. Even using some trick programs (ImageAlpha and ImageOptim) I could only get the PNG acceptably down to 457KB. Well done!


This is very useful in combination with CSS, http://sarasoueidan.com/blog/css-svg-clipping/


Ah, I figured they were gonna vectorize the PNG ;)


Cool trick, but PNGs can be lossified using a simple lossy averaging filter, using reduced and optimized color palettes etc.

https://tinypng.com/ https://github.com/foobaz/lossypng


Nice hack, doesn't work in IE8 but presumably IE8 users get the full-size PNG with transparency.


Or just disable the video and display a static JPG of the can. The video isn't that key anyway.


You aren't really shrinking a PNG though - you're making a JPEG partially transparent.


Yeah, a more accurate title would be "Using SVG to add transparency to JPEG"


A technique I've used in Android apps, is splitting PNG image into two JPGs: one with RGB data, and the other is greyscale with just the alpha channel. Store/transfer them like this, and combine them back into RGBA at runtime.


used to do this all the time back in 30kb banners and flash days. highly compressed jpeg's with vector masks. sure beat transparent png file sizes


Flash actually supports JPEG with lossless alpha (DefineBitsJPEG3). Just clipping a JPEG does of course also work.


I wonder how far they'd get by first reducing the image to 8bit with palettes (for example using image magic), and then using pngcrush etc.


This is great!


Since transparency seems to be off/on, could you use a 1 bit GIF for the mask instead?


You'd get some jaggies.


I though this was going to be about Singular Value Decomposition, a sort of compression technique.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: