convert PNG and JPG to sRGB

cédric (dev) said on 08/30/2018

pingo 0.98.3 is now able to handle colors more efficiently than before for PNG and JPG. it could try to keep the profiles (ICC/iCCP) or convert image data to sRGB to match what an user could expect. it picks by itself what could be done to preserve speed, quality and filesize. it is still work in progress atm

PNG

in older version, pingo used to ignore those chunks and remove them all, regardless of compression (lossy/visually lossless). the solution was to use -strip=0 to preserve how the image is rendered. however, this keeps all chunks, including those which are not related like comments, etc.

pingo 0.98
original optimized
189 KB 181 KB
pingo -s0 <targets>

RGB data from original and optimized files are just the same so this is not a lossy operation. however, pingo 0.98 does not preserve the profile, the iCCP chunk, which give some important instructions: how the image should be rendered — so this is not done in the same way

preserve the iCCP chunk

the first and most simple solution is to keep this chunk. however, you could notice sometimes that the size of the iCCP is variable according to the tool you used to edit the image. pingo could try to use deflate on it, and preserves — by default — only small iCCP chunk. you can control it with -strip=

option PNG
0 keep all chunks, including comments, etc.
1 keep iCCP, whatever the size
2 (default) keep iCCP only if the size is less or equal to 600 bytes
3 remove iCCP

on the precedent example, the iCCP chunk size is 313 bytes. by default, pingo should preserve it, so the image should be rendered just like the original. note that you do not need to add -strip=2 in the command because it is the default value

pingo 0.98.3
preserve iCCP chunk in web-lossless
original optimized
189 KB 181 KB
pingo -s0 <targets>

iCCP size

a note to myself regarding the iCCP: instead of just using deflate on the existing profile, perhaps it is possible to convert to something smaller first — without loss — and then deflate the result. i did not test this and it is not implemented in pingo atm

convert the PNG image data to sRGB

another solution is to convert the image data to sRGB. note that this is *always* lossy because the RGB values are modified. instead of using the iCCP chunk, the initial RGB are converted to the rendered RGB values. then, the iCCP chunk could be removed. this is how it is implemented in pingo

type option command line example
no additional loss (over the sRGB transformation) -srgb
pingo -s0 -srgb <targets>
add loss: the lossy filter (by default)
pingo -s0 -pngfilter=N <targets>
add loss: reduce the number of colors (by default)
pingo -s0 -pngcolor=N <targets>
add loss: reduce to paletted (by default)
pingo -s0 -pngpalette=N <targets>

by default, if you use lossy, pingo should convert the image data to sRGB and remove the iCCP. if you use web-lossless, it does not convert and keeps the iCCP chunk. the conversion of the image data to sRGB could affect compression (filesize), especially if you do a conversion without additional loss

pingo 0.98.3
PNG image data converted to sRGB (with additional loss)
original optimized
189 KB 106 KB
pingo -s0 -pngfilter=50 <targets>

on the example below, the iCCP chunk is removed from the PNG file, while the image data is converted to sRGB. however, you could choose to avoid this conversion by using -nopngsrgb: in this case, pingo will not convert RGB values, and keep instead the iCCP chunk

pingo 0.98.3
preserve iCCP chunk in lossy
original optimized
189 KB 98,8 KB
pingo -s0 -nopngsrgb -pngfilter=50 <targets>

Photoshop and pingo (PNG)

as a side note, you probably know that Photoshop could do this transformation (Convert to profile > sRGB). however, what is done in pingo should be faster, *should try* to provide more compressible data, and will perform a better image optimization — note that the image data is different from Photoshop conversion

pingo 0.98.3 (G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit)
original Photoshop (sRGB converted)
817,56 KB 9.34s — non-optimized output (2094,41 KB)
original pingo -s0 -srgb (sRGB converted)
817,56 KB 1.92s — optimized output (650,89 KB)
pingo -s0 -srgb <targets>

the Photoshop output could be optimized, but not that much. running pingo -s0 — the same optimization level — over it with could save 328.68 KB more. the filesize should be 1765.73 KB and require 4.86s to process: that is because the transformation to sRGB from Photoshop makes data less compressible

JPG

there is huge improvement in JPG handling in 0.98.3 because it is now able to process more JPG type — even if i can not claim that pingo support them all. a JPG file could have an ICC segment which does basically the same job as the iCCP chunk. this can be controlled just like PNG in pingo:

option JPG
0 keep all segments, including comments, etc.
1 keep ICC, whatever the size
2 (default) keep ICC only if the size is less or equal to 600 bytes
3 remove ICC

convert the JPG image data to sRGB

the default (or lossy) converts the initial data to what should be rendered. however, unlike what could be done with PNG, this can be performed *only* with additional loss. it will process the ICC segment instructions, convert image data to sRGB and remove the ICC segment

pingo 0.98.3
original JPG converted to sRGB (quality 75)
290,04 KB 241,77 KB
pingo -jpgquality=75 <targets>

instead of converting the image data that way, you could choose to avoid this by using -nojpgsrgb: in this case, it will apply the lossy but keep the ICC segment

pingo 0.98.3
preserve ICC segment in lossy
original optimized
290,04 KB 230,93 KB
pingo -nojpgsrgb -jpgquality=75 <targets>

JPG color type

pingo is also able to convert some JPG color type to sRGB. this can be very useful because some JPG could be rendered differently according to what software/hardware is used, even on Web:

CMYK JPG
original and rendered — OS: Windows
original (rendered by your browser) Chrome 70.0.3536.0 (rendered)
MSPaint (rendered) Firefox 61.0.2 (rendered)

by default, pingo should convert the image data to sRGB. this is done only in lossy mode, but will provide a JPG that will be rendered in the same way by most of viewer/browser. if pingo does not support the input color type, or if you use -nojpgsrgb to disable the conversion, it could try to convert to the RGB color space instead

conversion from CMYK to sRGB
JPG image data conversion from CMYK to sRGB
original — CMYK pingo (default) — sRGB
714,47 KB 70,83 KB
pingo <targets>

PNG to JPG

pingo can convert PNG to JPG for a while, but 0.98.3 is now able to process this conversion to sRGB. it uses the iCCP chunk from the PNG but it does not write the ICC segment in JPG: image data is converted to what should be expected. on the precedent example:

pingo 0.98.3
original pingo (-jpgconvert)
817,56 KB 218,34 KB
pingo -jpgconvert <targets>

Javi said on 08/31/2018

Hi Cédric,

It's great great to have the option to convert the color profiles to sRGB!

If I understand it correctly this means that the param -srgb forces the conversion to sRGB even with the -lossless param, am I right?

BTW, the grayscale images with ICC are converted to the sGray profile?

cédric (dev) said on 09/01/2018

-srgb forces the conversion to sRGB even with the -lossless param, am I right?

no. -lossless is a switch which *really* mean lossless in the strict sense — i.e without any loss. for example, the following images are actually identical for butteraugli or dssim because they compute how the image should be rendered — each pixel is exactly displayed in the same way for those images, so there is no difference

rendered image
original lossless lossless (web)
76 954 bytes 74 330 bytes 71 341 bytes
- pingo -lossless pingo -sN

lossless has the same data as original, just better optimized. however, the lossless (web) is very different: the unused data for Web could be transformed to increase compression — a similar transformation could be done by other PNG optimizers by default, like TruePNG, PngOptimizer, ECT, oxipng, etc.

image data
original lossless lossless (web)
- pingo -lossless pingo -sN

in other word: -lossless could be useful if you plan to use your PNG as heigthmap (3D). however, for Web usage, you should not use it for a simple reason: there is no difference in this context once image is rendered (but the filesize). -lossless can not be combined with any other switch, but the compression level

the grayscale images with ICC are converted to the sGray profile?

yes, grayscale should be supported

edit 09/06/2018 (0.98.14)

for -srgb, see this post

cédric (dev) said on 09/06/2018

i reviewed how this is done in 0.98.14 to make it more simple while giving maximum control to the user:

option what it does conditions
-srgb force conversion to sRGB overwrite *
-nosrgb disable conversion to sRGB for PNG and JPG -
-nopngsrgb disable conversion to sRGB for PNG only -
-nojpgsrgb disable conversion to sRGB for JPG only -
option what it does conditions
-srgb=0 disable conversion to sRGB -
-srgb=1 (default) enable conversion to sRGB in lossy modes overwrite only if smaller
-srgb=2 enable conversion to sRGB in all modes overwrite only if smaller
-srgb=3 force conversion to sRGB overwrite *

* only if file could need to be converted. if it is sRGB already and could not be optimized further, it will not overwrite the file

Pet01 said on 09/10/2018

Pingo crashes with this image or can't optimize (skip?). According to this (https://encode.ru/threads/1214-defluff-a-deflate-huffman-optimizer?p=35955&viewfull=1#post35955) the Photoshop ICC profile is corrupted...

Truecolor.png

cédric (dev) said on 09/10/2018

the Photoshop ICC profile is corrupted

no, the tRNS chunk is. should be fixed in 0.98.17, thanks for report

comment this