

Show HN: Using SVG to Shrink Your PNGs - labwire
http://peterhrynkow.com/how-to-compress-a-png-like-a-jpeg/

======
ahoge
There is a tool for that:

[https://github.com/mahonnaise/svgjng/](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](http://kaioa.com/b/1102/svgjng/index.html)

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

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

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

~~~
ahoge
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.

------
grownseed
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.

~~~
markburns
> 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.

------
aleem
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.

~~~
panic
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.

~~~
onion2k
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.

~~~
nitrogen
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.

~~~
Drakim
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.

~~~
panic
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...](https://static.licdn.com/scds/common/u/img/sprite/sprite_global_v8.png)
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/](https://developer.apple.com/videos/wwdc/2012/)
for more info about not wasting memory on mobile web sites.

------
ggambetta
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.

------
neckro23
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.

~~~
Someone1234
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...](https://en.wikipedia.org/wiki/Scalable_Vector_Graphics#Native_browser_support)

~~~
warfangle
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.

------
schmich
Our team used pngquant ([http://pngquant.org/](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).

~~~
tracker1
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... :-)

~~~
ashmud
Color quantizer ([http://x128.ho.ua/color-
quantizer.html](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](http://x128.ho.ua/pngutils.html)).

~~~
mark-r
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?

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

------
cr3ative
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!

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

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

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

[https://tinypng.com/](https://tinypng.com/)
[https://github.com/foobaz/lossypng](https://github.com/foobaz/lossypng)

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

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

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

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

------
cuu508
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.

------
dharma1
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

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

------
ant6n
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.

------
benshyong
This is great!

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

~~~
woah
You'd get some jaggies.

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

