Autoconverting PNGs to sRGB

Tools like PNGOUT blithely strip out color profiles (the iCCP chunk), which arguably makes the tools lossy because it changes the appearance of non-sRGB images in nearly all modern browsers.

I’ve found a solution. Gimp will offer to autoconvert to sRGB when opening an affected image. Saving and using PNGOUT is then perfectly fine. The original and Gimp-assisted recompressed images will give identical screenshots from a browser to the extent that every pixel will have the same RGB value with both image files. This is exactly what I want.

However, I’m dealing with hundreds of images and opening them in Gimp this way and then saving them is not an automated process. How can I automatically properly convert PNGs to the sRGB color profile prior to recompressing them?

Note: I’ve tried ImageMagick’s convert with various sRGB.icc profiles, but every time I’ve tried it’s a bit lossy (like giving #cccdcc instead of #cccccc) and thus ruins the ability to use PNG’s greyscale storage for grey images, both of which are undesired.

Answer

I finally solved it.

I’d used the ICC profiles available on the ICC’s website, which was strangely enough a mistake, since they introduce the errors I mentioned in the question.

GraphicsMagick (slightly lossy)

GraphicsMagick does this in a very slightly lossy method (brighter colors are reduced by one, like from #cccccc to #cbcbcb). However, this doesn’t ruin greys and allows for better recompression.

Since this is likely the easier method to apply if strict perfection isn’t needed, I’ve included it. Get a proper sRGB ICC profile, like the one in the assorted profiles pack offered by Little CMS or the one included with Ghostscript, and run the following:

gm convert in.png -profile /path/to/srgb.icc -strip out.png

Gimp automation (non-lossy)

After I found that GraphicsMagick was inexact, I worked out a Script-Fu script which uses Gimp’s exact method. To prepare to use it, save the following contents to ~/.gimp-2.8/scripts/png-to-srgb.scm

(define (png-to-srgb pattern)
  (let* (
      (filelist (cadr (file-glob pattern 1)))
    )
    (while (not (null? filelist))
      (let* (
          (filename (car filelist))
          (image (car (file-png-load RUN-NONINTERACTIVE filename filename)))
        )
        (begin
          (plug-in-icc-profile-apply-rgb RUN-NONINTERACTIVE image 0 0)
          (file-png-save2 RUN-NONINTERACTIVE
              image (car (gimp-image-get-active-drawable image))
              filename filename
              0 9 0 0 0 0 0 0 0)
          (gimp-image-delete image)
          (set! filelist (cdr filelist))
        )
      )
    )
  )
)

Then the conversion can be accomplished with the following:

gimp-console -i -d -f -b '(png-to-srgb "file.png")' -b '(gimp-quit 0)'

This does not allow separate input and output filenames because it can be replaced with *.png if desired.

Attribution
Source : Link , Question Author : Olathe , Answer Author : Olathe

Leave a Comment