Welcome to Centmin Mod Community
Become a Member

WebPerf Optimizing Image Sizes for faster page load times with optimise-images.sh

Discussion in 'Web Development & Web Performance' started by eva2000, Apr 29, 2017.

  1. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Images account for the largest portion of the static assets for a typical web page so optimizing image size is very important. You can see HTTP Archive profile as at April 15, 2017 HTTP Archive - Interesting Stats.


    upload_2017-4-29_21-44-54.png
    upload_2017-4-29_21-44-39.png

    I started writing a batch jpg and png image resizer, optimiser and profiling script called optimise-images.sh for my own usage at GitHub - centminmod/optimise-images. I thought it might be useful to other folks too. It's a work in progress as I only started writing the script ~5 days ago :)

    Various usage examples I have posted so far
    Previous related discussions for image optimisations include
    Updates:
     
    Last edited: Apr 5, 2020
  2. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Example for resizing using ImageMagick convert, and then using OptiPNG, JpegOptim and optional Mozilla MozJPEG, ZopfliPNG and Google Guetzli (work in progress for Guetzli).
    upload_2017-4-29_21-47-11.png

    Note Guetzli takes 20x times longer to optimise and usages ALOT more memory compared to JpegOptim and MozJPEG.

    upload_2017-4-29_21-47-27.png

    upload_2017-4-29_21-47-45.png

    Profile of original images
    Code (Text):
    ------------------------------------------------------------------------------
    image profile
    image name : width : height : quality : transparency : image depth (bits) : size : user: group
    ------------------------------------------------------------------------------
    images in /home/optimise-benchmarks
    logged at /home/optimise-logs/profile-log-290417-103204.log
    ------------------------------------------------------------------------------
    image : bees.png : 444 : 258 : 92 : False : 8 : 177424 : root : root
    image : dslr_canon_eos_m6_1.jpg : 1200 : 800 : 90 : False : 8 : 207430 : root : root
    image : dslr_nikon_d7200_1.jpg : 6000 : 4000 : 96 : False : 8 : 10806424 : root : root
    image : dslr_nikon_d7200_2.jpg : 4000 : 6000 : 90 : False : 8 : 3899287 : root : root
    image : png24-image1.png : 600 : 400 : 92 : False : 8 : 400998 : root : root
    image : png24-interlaced-image1.png : 600 : 400 : 92 : False : 8 : 456949 : root : root
    image : samsung_s7_mobile_1.jpg : 4032 : 3024 : 92 : False : 8 : 2100858 : root : root
    image : webp-study-source-firebreathing.png : 1024 : 752 : 92 : False : 8 : 1206455 : root : root
    
    ------------------------------------------------------------------------------
    Original or Existing Images:
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 2238      | 1954       | 92          | 2406978    | 19255825           | 18805           |
    


    Profile of optimised images
    Code (Text):
    ------------------------------------------------------------------------------
    image profile
    image name : width : height : quality : transparency : image depth (bits) : size : user: group
    ------------------------------------------------------------------------------
    images in /home/optimise-benchmarks
    logged at /home/optimise-logs/profile-log-290417-103825.log
    ------------------------------------------------------------------------------
    image : bees_optimal.png : 444 : 258 : 92 : False : 8 : 175356 : root : root
    image : bees.optipng.png : 444 : 258 : 92 : False : 8 : 175296 : root : root
    image : bees.png : 444 : 258 : 92 : False : 8 : 177424 : root : root
    image : bees.webp : 444 : 258 : 92 : False : 8 : 10520 : root : root
    image : bees.zopflipng.png : 444 : 258 : 92 : False : 8 : 175356 : root : root
    image : dslr_canon_eos_m6_1.guetzli.jpg : 1200 : 800 : 82 : False : 8 : 117227 : root : root
    image : dslr_canon_eos_m6_1.jpg : 1200 : 800 : 90 : False : 8 : 207430 : root : root
    image : dslr_canon_eos_m6_1.mozjpeg.jpg : 1200 : 800 : 82 : False : 8 : 151142 : root : root
    image : dslr_canon_eos_m6_1_optimal.jpg : 1200 : 800 : 82 : False : 8 : 161086 : root : root
    image : dslr_canon_eos_m6_1.webp : 1200 : 800 : 92 : False : 8 : 61544 : root : root
    image : dslr_nikon_d7200_1.guetzli.jpg : 2048 : 1365 : 82 : False : 8 : 283851 : root : root
    image : dslr_nikon_d7200_1.jpg : 6000 : 4000 : 96 : False : 8 : 10806424 : root : root
    image : dslr_nikon_d7200_1.mozjpeg.jpg : 2048 : 1365 : 82 : False : 8 : 358638 : root : root
    image : dslr_nikon_d7200_1_optimal.jpg : 2048 : 1365 : 82 : False : 8 : 374954 : root : root
    image : dslr_nikon_d7200_1.webp : 2048 : 1365 : 92 : False : 8 : 173414 : root : root
    image : dslr_nikon_d7200_2.guetzli.jpg : 1365 : 2048 : 82 : False : 8 : 405129 : root : root
    image : dslr_nikon_d7200_2.jpg : 4000 : 6000 : 90 : False : 8 : 3899287 : root : root
    image : dslr_nikon_d7200_2.mozjpeg.jpg : 1365 : 2048 : 82 : False : 8 : 482841 : root : root
    image : dslr_nikon_d7200_2_optimal.jpg : 1365 : 2048 : 82 : False : 8 : 516224 : root : root
    image : dslr_nikon_d7200_2.webp : 1365 : 2048 : 92 : False : 8 : 212754 : root : root
    image : png24-image1_optimal.png : 600 : 400 : 92 : False : 8 : 386195 : root : root
    image : png24-image1.optipng.png : 600 : 400 : 92 : False : 8 : 386063 : root : root
    image : png24-image1.png : 600 : 400 : 92 : False : 8 : 400998 : root : root
    image : png24-image1.webp : 600 : 400 : 92 : False : 8 : 27104 : root : root
    image : png24-image1.zopflipng.png : 600 : 400 : 92 : False : 8 : 386195 : root : root
    image : png24-interlaced-image1_optimal.png : 600 : 400 : 92 : False : 8 : 386195 : root : root
    image : png24-interlaced-image1.optipng.png : 600 : 400 : 92 : False : 8 : 386063 : root : root
    image : png24-interlaced-image1.png : 600 : 400 : 92 : False : 8 : 456949 : root : root
    image : png24-interlaced-image1.webp : 600 : 400 : 92 : False : 8 : 27104 : root : root
    image : png24-interlaced-image1.zopflipng.png : 600 : 400 : 92 : False : 8 : 386195 : root : root
    image : samsung_s7_mobile_1.guetzli.jpg : 2048 : 1536 : 82 : False : 8 : 171110 : root : root
    image : samsung_s7_mobile_1.jpg : 4032 : 3024 : 92 : False : 8 : 2100858 : root : root
    image : samsung_s7_mobile_1.mozjpeg.jpg : 2048 : 1536 : 82 : False : 8 : 246583 : root : root
    image : samsung_s7_mobile_1_optimal.jpg : 2048 : 1536 : 82 : False : 8 : 256253 : root : root
    image : samsung_s7_mobile_1.webp : 2048 : 1536 : 92 : False : 8 : 69490 : root : root
    image : webp-study-source-firebreathing_optimal.png : 1024 : 752 : 92 : False : 8 : 1200202 : root : root
    image : webp-study-source-firebreathing.optipng.png : 1024 : 752 : 92 : False : 8 : 1194091 : root : root
    image : webp-study-source-firebreathing.png : 1024 : 752 : 92 : False : 8 : 1206455 : root : root
    image : webp-study-source-firebreathing.webp : 1024 : 752 : 92 : False : 8 : 71860 : root : root
    image : webp-study-source-firebreathing.zopflipng.png : 1024 : 752 : 92 : False : 8 : 1184812 : root : root
    

    Code (Text):
    ------------------------------------------------------------------------------
    Original or Existing Images:
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 1523      | 1281       | 89          | 1072767    | 25746417           | 25143           |
    
    ------------------------------------------------------------------------------
    Optimised PNG Images (optipng):
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 667       | 452        | 92          | 535378     | 2141513            | 2091            |
    
    ------------------------------------------------------------------------------
    Optimised PNG Images (zopflipng):
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 667       | 452        | 92          | 533140     | 2132558            | 2083            |
    
    ------------------------------------------------------------------------------
    Optimised Images:
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 1166      | 945        | 87          | 432058     | 3456465            | 3375            |
    
    ------------------------------------------------------------------------------
    Optimised WebP Images:
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 1166      | 945        | 92          | 81724      | 653790             | 638             |
    

    Code (Text):
    ------------------------------------------------------------------------------
    Optimised Jpg Images (jpegoptim):
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 1665      | 1437       | 82          | 327129     | 1308517            | 1278            |
    
    ------------------------------------------------------------------------------
    Optimised Jpg Images (guetzli):
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 1665      | 1437       | 82          | 244329     | 977317             | 954             |
    
    ------------------------------------------------------------------------------
    Optimised Jpg Images (mozjpeg):
    ------------------------------------------------------------------------------
    | Avg width | Avg height | Avg quality | Avg size   | Total size (Bytes) | Total size (KB) |
    | --------- | ---------- | ----------- | --------   | ------------------ | --------------- |
    | 1665      | 1437       | 82          | 309801     | 1239204            | 1210            |
    


    Side by Side compare for one of the images
    • Original image = 10.31 MB
    • WebP = 169.35 KB
    • MozJPEG = 350.23 KB
    • Guetzli = 277.20 KB
    • JpegOPTIM = 366.17 KB
    compare-dslr-nikon-d7200-1.jpg
     
    Last edited: May 2, 2017
  3. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
  4. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Last edited: May 1, 2017
  5. elargento

    elargento Member

    352
    17
    18
    Jan 4, 2016
    Ratings:
    +44
    Local Time:
    11:19 AM
    10
    Any ideas to optimize .gif files?
     
  6. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Specifically excluded gif as bit trickier due to animated gifs etc. Probably something to add to my optimise-images.sh in future when I have a bit more spare time :)
     
  7. jair

    jair Member

    48
    7
    8
    Jan 8, 2017
    Ratings:
    +17
    Local Time:
    5:19 PM
    Is this loseless only? I believe Mozjpeg and Jpegoptim are only loseless, which does not give enough savings. What I know is that imagemagick by default is definitely not enough, on my forum I have images of 300kb, which I run through kraken.io and it becomes 50kb without any visible loss of quality. I am wondering if this script does the same or the idea is different?

    I might install and play with it a bit later.
     
  8. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    This script is by default lossy most of the time and more optimised. It's best to test it on a test directory of sample images which you can compare with your forum's imagemagick implementation.
     
  9. pamamolf

    pamamolf Premium Member Premium Member

    4,068
    427
    83
    May 31, 2014
    Ratings:
    +832
    Local Time:
    5:19 PM
    Nginx-1.25.x
    MariaDB 10.3.x
    I think it will be better to have lossless as default so the user can apply out of the box and then they should check if they need extra optimizations....
     
  10. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    optimise-images.sh has various options for this if you know what to do to change it
    Code (Text):
    IMAGICK_QUALITY='82'
    IMAGICK_WEBPQUALITY='75'
    IMAGICK_WEBPLOSSLESS='n'
    ZOPFLIPNG_LOSSY='n'
    IMAGICK_JPGOPTS=' -filter triangle -define filter:support=2 -define jpeg:fancy-upsampling=off -unsharp 0.25x0.08+8.3+0.045'
    IMAGICK_PNGOPTS=' -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=2'
    IMAGICK_WEBPOPTS=" -define webp:method=${IMAGICK_WEBPMETHOD} -define webp:alpha-quality=${IMAGICK_WEBPQUALITYALPHA} -define webp:lossless=false -quality ${IMAGICK_WEBPQUALITY}"
    
     
  11. Revenge

    Revenge Active Member

    469
    93
    28
    Feb 21, 2016
    Portugal
    Ratings:
    +354
    Local Time:
    3:19 PM
    1.9.x
    10.1.x
    This also works for gif's?
     
  12. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    gif excluded for now heh
     
  13. Revenge

    Revenge Active Member

    469
    93
    28
    Feb 21, 2016
    Portugal
    Ratings:
    +354
    Local Time:
    3:19 PM
    1.9.x
    10.1.x
    Gif's is what it consumes a lot of traffic in my site. Although i have implemented Gfycat and Img GIFV, thank's to IPS suite supporting them. It was a really big help. Gif's with hundreds of MB's transformed into 1 or 2 MB.
     
  14. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Yeah when I have more free time, I will tackle adding proper GIF optimisation support to optimise-image.sh as well :D
     
  15. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
  16. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    Updated optimise-images.sh with new profile-age & optimise-age Mode which allow you to filter and limit profiling and optimisation of images by image timestamp age :D
     
  17. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
  18. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
  19. kinhatula

    kinhatula New Member

    9
    2
    3
    Sep 6, 2017
    Ratings:
    +2
    Local Time:
    9:19 PM
    Please check this code cron for me. Is it correct or incorrect? thanks
    Domain: hangmygiasi.net

    15 1 * * * find /home/nginx/domains/hangmygiasi.net/public/wp-content/uploads/ -type d | sort | while read d; do echo "optimise-webp-nginx directory: $d"; echo "/root/tools/optimise-images/optimise-images.sh optimise-cron-age $d"; /root/tools/optimise-images/optimise-images.sh optimise-cron-age $d; done > /dev/null
     
    Last edited: Sep 7, 2017
  20. eva2000

    eva2000 Administrator Staff Member

    53,248
    12,117
    113
    May 24, 2014
    Brisbane, Australia
    Ratings:
    +18,655
    Local Time:
    12:19 AM
    Nginx 1.27.x
    MariaDB 10.x/11.4+
    better to create a bash script wrapper and but those commands into bash script to be run via cron .. Much cleaner :)