<commit_before>var childProcess = require('child_process'),
    _ = require('underscore'),
    passError = require('assetgraph/lib/util/passError'),
    seq = require('seq'),
    pipeImageThroughChildProcessAndBuffer = require('../util/pipeImageThroughChildProcessAndBuffer');

module.exports = function (queryObj) {
    return function optimizePngs(assetGraph, cb) {
        seq(assetGraph.findAssets(_.extend({type: 'Png'}, queryObj)))
            .parEach(function (pngAsset) {
                var pngtopnmProcess = childProcess.spawn('pngtopnm'),
                    ppmhistProcess = childProcess.spawn('ppmhist', ['-noheader']),
                    numColors = 0;
                ppmhistProcess.stdout.on('data', function (chunk) {
                    numColors += (chunk.toString('ascii').match(/\n/g) || []).length;
                }).on('end', function () {
                    if (numColors > 1 && numColors < 256) {
                        pipeImageThroughChildProcessAndBuffer.pngquant(String(numColors))(pngAsset.rawSrc, passError(this, function (optimizedSrc) {
                            pngAsset.rawSrc = optimizedSrc;
                            this();
                        }.bind(this)));
                    } else {
                        this();
                    }
                }.bind(this)).on('error', this);
                pngtopnmProcess.stdout.pipe(ppmhistProcess.stdin);
                pngtopnmProcess.stdin.end(pngAsset.rawSrc);
            })
            .parEach(function (pngAsset) {
                pipeImageThroughChildProcessAndBuffer.pngcrush("-rem alla")(pngAsset.rawSrc, passError(this, function (optimizedSrc) {
                    pngAsset.rawSrc = optimizedSrc;
                    this();
                }.bind(this)));
            })
            .parEach(function (pngAsset) {
                pipeImageThroughChildProcessAndBuffer.optipng()(pngAsset.rawSrc, passError(this, function (optimizedSrc) {
                    pngAsset.rawSrc = optimizedSrc;
                    this();
                }.bind(this)));
            })
            .seq(function () {
                cb();
            })
            .catch(cb);
    };
};<commit_msg>transforms.optimizePngs: pngquant to 2 colors if the image has less than 2 colors ('pngquant 1 ... ' throws an error).<commit_after>var childProcess = require('child_process'),
    _ = require('underscore'),
    passError = require('assetgraph/lib/util/passError'),
    seq = require('seq'),
    pipeImageThroughChildProcessAndBuffer = require('../util/pipeImageThroughChildProcessAndBuffer');

module.exports = function (queryObj) {
    return function optimizePngs(assetGraph, cb) {
        seq(assetGraph.findAssets(_.extend({type: 'Png'}, queryObj)))
            .parEach(function (pngAsset) {
                var pngtopnmProcess = childProcess.spawn('pngtopnm'),
                    ppmhistProcess = childProcess.spawn('ppmhist', ['-noheader']),
                    numColors = 0;
                ppmhistProcess.stdout.on('data', function (chunk) {
                    numColors += (chunk.toString('ascii').match(/\n/g) || []).length;
                }).on('end', function () {
                    if (numColors < 256) {
                        pipeImageThroughChildProcessAndBuffer.pngquant(String(numColors < 2 ? 2 : numColors))(pngAsset.rawSrc, passError(this, function (optimizedSrc) {
                            pngAsset.rawSrc = optimizedSrc;
                            this();
                        }.bind(this)));
                    } else {
                        this();
                    }
                }.bind(this)).on('error', this);
                pngtopnmProcess.stdout.pipe(ppmhistProcess.stdin);
                pngtopnmProcess.stdin.end(pngAsset.rawSrc);
            })
            .parEach(function (pngAsset) {
                pipeImageThroughChildProcessAndBuffer.pngcrush("-rem alla")(pngAsset.rawSrc, passError(this, function (optimizedSrc) {
                    pngAsset.rawSrc = optimizedSrc;
                    this();
                }.bind(this)));
            })
            .parEach(function (pngAsset) {
                pipeImageThroughChildProcessAndBuffer.optipng()(pngAsset.rawSrc, passError(this, function (optimizedSrc) {
                    pngAsset.rawSrc = optimizedSrc;
                    this();
                }.bind(this)));
            })
            .seq(function () {
                cb();
            })
            .catch(cb);
    };
};
{'fraction_non_alphanumeric': 0.12577777777777777, 'fraction_numerical': 0.003111111111111111, 'mean_word_length': 1.7196374622356496, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7564265', 'n_tokens_mistral': 1235, 'n_tokens_neox': 1133, 'n_words': 180}