Category Archives: grunt

Using ImageMagick to manipulate PNGs stably

This seems to be an issue that has been talked about in a number of places, however I found it very hard to find the correct solution, which is why I have documented it here.

Often as part of the build process for a webapp you’ll want to take original images and shrink them down to be the correct dimensions (either because they require certain dimensions to be accepted, such as icons, or because you want to save space by stripping out unnecessary data). For JPGs you can do this pretty easily like

convert orig.jpg -strip -resize 500x500 build/out.jpg

The -strip removes any EXIF header information both anonymizing the image and saving potentially a few Kb of asset size.

This process is ‘stable’ because if you repeat it (within the same version of ImageMagick), the resulting file’s data will be identical. This means that you won’t get a new version of the built image in your (git) repository each time you run this command.

However recently when trying to do the same for PNGs (because I required transparency) I noticed that each time they were being built, git was committing a new version into the repository. This is bad news because it both grows the size of the repository by storing pointless identical versions of the file, and also makes it a lot harder tracking through history to see what changed because you have loads of PNG images being committed each time you do a build.

Looking at the output of identify -verbose I could see that the part that was changing each time was below:

  Properties:
    date:create: 2016-12-01T19:24:13+03:00
    date:modify: 2016-12-01T19:24:13+03:00
    png:tIME: 2016-12-01T16:24:13Z

So it appears that PNG format wants to store the update/create time in the image’s header itself. That was what was changing each time.

Searching on the internet I found a number of suggestions about how to strip these out with the convert command, and I saw that the header changed a bit but I couldn’t find any that were also removing the ‘png:tIME’ element. Finally I managed to come up with the following flags which convert the image stably:

convert orig.png -strip -define png:exclude-chunks=date,time build/out.png

The identify command still outputs the date: property sections but these are now being taken from the create time (ctime) and modify time (mtime) of the file itself rather than from the header and so are not stored in version control.

You might be wondering why I don’t just create a lazy build system that only updates the asset if the mod time of the source asset is greater than that of the built asset – if I was doing this on a bigger project that would be the best way, but as this was just for a small project I wanted to do quickly I thought that doing this would be the easiest way!

Stop Grunt minifying libraries all the time

Recently I’ve been playing around with using a proper build system for my latest Angular project. I chose to start with grunt which seems very powerful if quite difficult to set up (mostly because yeoman did most of the initial config with it). However I find it very strange that by default the grunt-usemin plugin tries to minify and then concat all of the libraries even those such as jquery or angular. This is both not very efficient (as there are already .min.js files distributed with them), also it probably can’t do it as well as they can. So, I started doing a bit of research as to how this could be avoided and came up with the following.

Firstly install the grunt-usemin-uglifynew module:

npm install --save-dev grunt-usemin-uglifynew

Then, change your Gruntfile to look like this:

  var uglifyNew = require('grunt-usemin-uglifynew');
  grunt.initConfig({
    ...
    useminPrepare: {
    ...
      options: {
        flow: {
          html: {
            steps: {
              js_min: [uglifyNew, 'concat'],
              js: ['concat', 'uglifyjs'],
    ...
    usemin: {
      ...
      options: {
        blockReplacements: {
            // copy of js block replacement fn from fileprocessor.js
            js_min: function (block) {
              var defer = block.defer ? 'defer ' : '';
              var async = block.async ? 'async ' : '';
              return '<script ' + defer + async + 'src="' + block.dest + '"><\/script>';
            }
        },

and your html file(s) to look like:

    <!-- build:js_min(.) scripts/vendor.js -->
    <!-- bower:js -->
    <script src="bower_components/jquery/dist/jquery.js"></script>
    <script src="bower_components/angular/angular.js"></script>
    <script src="bower_components/angular-route/angular-route.js"></script>
    <!-- endbower -->
    <!-- endbuild -->

        <!-- build:js({.tmp,app}) scripts/scripts.js -->
        <script src="scripts/app.js"></script>
        <script src="scripts/controllers/main.js"></script>
        <script src="scripts/controllers/about.js"></script>
        <!-- endbuild -->

Basically this splits the js processor into two – js (the normal one) remains unchanged and continues to concat all the files in the block and then minify them. The other one, js_min just tries to find the .min.js file and then concats into a single file (I wish there was an easy way to avoid having to concat them – I think it should really just copy the .min.js to the build directory and update the links to point to them there)