From 97a8933fd6c6a2fdf800a73e5044f95c9566e252 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Tue, 5 Aug 2014 05:06:40 +0200 Subject: [PATCH 01/12] getting pngquant version --- lib/image_optim/bin_resolver.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/image_optim/bin_resolver.rb b/lib/image_optim/bin_resolver.rb index 70afa95d..af0ff1a0 100644 --- a/lib/image_optim/bin_resolver.rb +++ b/lib/image_optim/bin_resolver.rb @@ -84,7 +84,7 @@ def accessible?(name) def version(name) case name.to_sym - when :advpng, :gifsicle, :jpegoptim, :optipng + when :advpng, :gifsicle, :jpegoptim, :optipng, :pngquant capture_output("#{name} --version")[/\d+(\.\d+){1,}/] when :svgo capture_output("#{name} --version 2>&1")[/\d+(\.\d+){1,}/] From 0dce5057123657df159be9f87a9c4396fd8cf021 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Tue, 5 Aug 2014 05:06:53 +0200 Subject: [PATCH 02/12] checking pngquant version --- lib/image_optim/bin_resolver.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/image_optim/bin_resolver.rb b/lib/image_optim/bin_resolver.rb index af0ff1a0..ed2def0e 100644 --- a/lib/image_optim/bin_resolver.rb +++ b/lib/image_optim/bin_resolver.rb @@ -114,6 +114,13 @@ def check!(bin) when c = is < '1.17' warn "Note that `#{bin}` (#{c}) does not use zopfli" end + when :pngquant + case bin.version + when c = is < '2.0' + fail BadBinVersion, "`#{bin}` (#{c}) is not supported" + when c = is < '2.1' + warn "Note that `#{bin}` (#{c}) may be lossy even with quality `100-`" + end end end From 466096416ad246c112b440feedd947bf45c6e4c6 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Thu, 7 Aug 2014 02:09:17 +0200 Subject: [PATCH 03/12] pngquant worker (kudos to adammathys for #32 and smasry for #40) --- bin/image_optim | 4 ++ lib/image_optim.rb | 2 +- lib/image_optim/non_negative_integer_range.rb | 11 +++++ lib/image_optim/worker/pngquant.rb | 43 +++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 lib/image_optim/non_negative_integer_range.rb create mode 100644 lib/image_optim/worker/pngquant.rb diff --git a/bin/image_optim b/bin/image_optim index b4c0e93a..8bef697b 100755 --- a/bin/image_optim +++ b/bin/image_optim @@ -3,11 +3,13 @@ require 'image_optim/runner' require 'image_optim/true_false_nil' +require 'image_optim/non_negative_integer_range' options = {} option_parser = OptionParser.new do |op| ImageOptim::TrueFalseNil.add_to_option_parser(op) + ImageOptim::NonNegativeIntegerRange.add_to_option_parser(op) op.banner = <<-TEXT.gsub(/^\s*\|/, '') |#{ImageOptim.full_version} @@ -66,6 +68,8 @@ option_parser = OptionParser.new do |op| [Integer, 'N'] when Array >= type [Array, 'a,b,c'] + when ImageOptim::NonNegativeIntegerRange == type + [type, 'M-N'] else fail "Unknown type #{type}" end diff --git a/lib/image_optim.rb b/lib/image_optim.rb index 09b95f6f..05c12305 100644 --- a/lib/image_optim.rb +++ b/lib/image_optim.rb @@ -201,7 +201,7 @@ def apply_threading(enum) end %w[ - pngcrush pngout optipng advpng + pngcrush pngout optipng advpng pngquant jhead jpegoptim jpegtran gifsicle svgo diff --git a/lib/image_optim/non_negative_integer_range.rb b/lib/image_optim/non_negative_integer_range.rb new file mode 100644 index 00000000..14608128 --- /dev/null +++ b/lib/image_optim/non_negative_integer_range.rb @@ -0,0 +1,11 @@ +class ImageOptim + # Denote range of non negative integers for worker option + class NonNegativeIntegerRange + # Add handling of range of non negative integers in OptionParser instance + def self.add_to_option_parser(option_parser) + option_parser.accept(self, /(\d+)(?:-|\.\.)(\d+)/) do |_, m, n| + m.to_i..n.to_i + end + end + end +end diff --git a/lib/image_optim/worker/pngquant.rb b/lib/image_optim/worker/pngquant.rb new file mode 100644 index 00000000..f85c1bda --- /dev/null +++ b/lib/image_optim/worker/pngquant.rb @@ -0,0 +1,43 @@ +require 'image_optim/worker' +require 'image_optim/option_helpers' +require 'image_optim/non_negative_integer_range' + +class ImageOptim + class Worker + # http://pngquant.org/ + class Pngquant < Worker + QUALITY_OPTION = + option(:quality, 100..100, NonNegativeIntegerRange, 'min..max - don\'t '\ + 'save below min, use less colors below max (both in range `0..100`; '\ + 'in yaml - `!ruby/range 0..100`)') do |v| + min = OptionHelpers.limit_with_range(v.begin, 0..100) + min..OptionHelpers.limit_with_range(v.end, min..100) + end + + SPEED_OPTION = + option(:speed, 3, 'speed/quality trade-off: '\ + '`1` - slow, '\ + '`3` - default, '\ + '`11` - fast & rough') do |v| + OptionHelpers.limit_with_range(v.to_i, 1..11) + end + + # Always run first + def run_order + -5 + end + + def optimize(src, dst) + args = %W[ + --quality=#{quality.begin}-#{quality.end} + --speed=#{speed} + --output=#{dst} + --force + -- + #{src} + ] + execute(:pngquant, *args) && optimized?(src, dst) + end + end + end +end From f0c6a7fede1c06cd8649f28c2b2951c7acb2bce4 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Thu, 7 Aug 2014 20:24:50 +0200 Subject: [PATCH 04/12] add generated pngquant worker options to readme --- README.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.markdown b/README.markdown index a995fcbe..eb7b8188 100644 --- a/README.markdown +++ b/README.markdown @@ -256,6 +256,10 @@ Worker can be disabled by passing `false` instead of options hash. ### :advpng => * `:level` — Compression level: `0` - don't compress, `1` - fast, `2` - normal, `3` - extra, `4` - extreme *(defaults to `4`)* +### :pngquant => +* `:quality` — min..max - don't save below min, use less colors below max (both in range `0..100`; in yaml - `!ruby/range 0..100`) *(defaults to `100..100`)* +* `:speed` — speed/quality trade-off: `1` - slow, `3` - default, `11` - fast & rough *(defaults to `3`)* + ### :jhead => Worker has no options From 15268b599e865a0f9b381c36c7926c199e6fc6d3 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Thu, 20 Mar 2014 00:36:27 +0100 Subject: [PATCH 05/12] add generator script and a 64 colour test png --- spec/images/quant/64.png | Bin 0 -> 869 bytes spec/images/quant/generate | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 spec/images/quant/64.png create mode 100755 spec/images/quant/generate diff --git a/spec/images/quant/64.png b/spec/images/quant/64.png new file mode 100644 index 0000000000000000000000000000000000000000..0ae1e8d74fd056081eb6bd4eb47816788be1ed2b GIT binary patch literal 869 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58911L)MWvCLm;J)>=ES4z)+>ez|hdb!0-zw z)bN6Vq11qZ;Z*_ygVhWM2JwP9y8>;15^PD{?k)`fL2$v|<&zm0nBIB1IEGZ*dV75% z?*RuM=8ZKUe*4c+N?u`6#AMEX@H{gE!<0F@_c65H`^vaMh2av5!>zB(0cngL!VH;A z3TOEpX0a;xGA!Y2FtKOI6l*YHoS?>V=?}w_NRZN53?84ECyXi{4UK_I8*gh~b0?f& f0wqge+T}kU&ysq+|Fb19FEDtz`njxgN@xNAH@5>g literal 0 HcmV?d00001 diff --git a/spec/images/quant/generate b/spec/images/quant/generate new file mode 100755 index 00000000..1db4d47b --- /dev/null +++ b/spec/images/quant/generate @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +Dir.chdir(File.dirname(__FILE__)) + +require 'shellwords' + +palettes = [64] +side = 256 + +palettes.each do |palette| + IO.popen(%W[ + convert + -depth 8 + -size #{side}x#{side} + -strip + rgb:- + PNG24:#{palette}.png + ].shelljoin, 'w') do |f| + (side * side).times do |i| + color = i * palette / (side * side) * 0x10000 / palette + f << [color / 0x100, color % 0x100, 0].pack('C*') + end + end + system "identify -format 'Wrote %f with %k unique colors\n' #{palette}.png" +end From 35cfc67b645ddd5176c24b0da0c4337f6a0a7b66 Mon Sep 17 00:00:00 2001 From: Adam Mueller Date: Tue, 4 Feb 2014 14:41:36 -0800 Subject: [PATCH 06/12] add installation instructions for pngquant (linux, part of #32) --- README.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.markdown b/README.markdown index eb7b8188..e4ddbe21 100644 --- a/README.markdown +++ b/README.markdown @@ -81,13 +81,13 @@ Besides permanently setting environment variables in `~/.profile`, `~/.bash_prof ### Linux - Debian/Ubuntu ```bash -sudo apt-get install -y advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush +sudo apt-get install -y advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush pngquant ``` ### Linux - RHEL/Fedora/Centos ```bash -sudo yum install -y advancecomp gifsicle jhead libjpeg optipng +sudo yum install -y advancecomp gifsicle jhead libjpeg optipng pngquant ``` You may also need to install `libjpeg-turbo-utils` instead of `libjpeg`: From 1d53b5188122d4308c15001eb66cab1418f8a8fd Mon Sep 17 00:00:00 2001 From: Samer Masry Date: Wed, 5 Mar 2014 16:29:51 -0800 Subject: [PATCH 07/12] add installation instructions for pngquant (macports, part of #40) --- README.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index e4ddbe21..f3d7c935 100644 --- a/README.markdown +++ b/README.markdown @@ -127,7 +127,7 @@ make && cp -f pngcrush /usr/local/bin ### OS X: Macports ```bash -sudo port install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush +sudo port install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush pngquant ``` ### OS X: Brew From 894ef626bc3a9606fe5ca177bf86815c7baec956 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Thu, 7 Aug 2014 20:27:30 +0200 Subject: [PATCH 08/12] add installation instructions for pngquant (brew and addition for debian/ubuntu old version) --- README.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index f3d7c935..0a4d4082 100644 --- a/README.markdown +++ b/README.markdown @@ -84,6 +84,8 @@ Besides permanently setting environment variables in `~/.profile`, `~/.bash_prof sudo apt-get install -y advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush pngquant ``` +If you get an old version of `pngquant`, please check how to install up-to-date version or compile from source at [http://pngquant.org/](http://pngquant.org/). + ### Linux - RHEL/Fedora/Centos ```bash @@ -133,7 +135,7 @@ sudo port install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush png ### OS X: Brew ```bash -brew install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush +brew install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush pngquant ``` ### pngout installation (optional) From b0642a43a0ffc1d9334eabaafd666fd981f112c6 Mon Sep 17 00:00:00 2001 From: Adam Mueller Date: Tue, 4 Feb 2014 15:42:46 -0800 Subject: [PATCH 09/12] add pngquant to travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 15b20a96..bc3a1295 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ script: - '! bundle show rubocop || bundle exec rubocop' # run rubocop only if it is bundled before_install: - sudo apt-get update -qq - - sudo apt-get install -qq advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush + - sudo apt-get install -qq advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush pngquant - wget http://static.jonof.id.au/dl/kenutils/pngout-20130221-linux.tar.gz - tar -xzf pngout-*-linux.tar.gz - mv pngout-*-linux pngout-linux From 3c065474782246e1353416d617f22643fc9cf1f3 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Thu, 7 Aug 2014 20:27:19 +0200 Subject: [PATCH 10/12] mention pngquant in readme and gemspec summary --- README.markdown | 1 + image_optim.gemspec | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.markdown b/README.markdown index 0a4d4082..47e0e578 100644 --- a/README.markdown +++ b/README.markdown @@ -18,6 +18,7 @@ Optimize (lossless compress) images (jpeg, png, gif, svg) using external utiliti * [optipng](http://optipng.sourceforge.net/) * [pngcrush](http://pmt.sourceforge.net/pngcrush/) * [pngout](http://www.advsys.net/ken/util/pngout.htm) +* [pngquant](http://pngquant.org/) * [svgo](https://github.com/svg/svgo) Based on [ImageOptim.app](http://imageoptim.com/). diff --git a/image_optim.gemspec b/image_optim.gemspec index 41679973..51ae79c2 100644 --- a/image_optim.gemspec +++ b/image_optim.gemspec @@ -3,7 +3,7 @@ Gem::Specification.new do |s| s.name = 'image_optim' s.version = '0.14.0' - s.summary = %q{Optimize (lossless compress) images (jpeg, png, gif, svg) using external utilities (advpng, gifsicle, jpegoptim, jpegtran, optipng, pngcrush, pngout, svgo)} + s.summary = %q{Optimize (lossless compress) images (jpeg, png, gif, svg) using external utilities (advpng, gifsicle, jpegoptim, jpegtran, optipng, pngcrush, pngout, pngquant, svgo)} s.homepage = "http://github.com/toy/#{s.name}" s.authors = ['Ivan Kuchin'] s.license = 'MIT' From fb0037518359709acf761fbb34862a7d66116e35 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Fri, 8 Aug 2014 01:42:18 +0200 Subject: [PATCH 11/12] reorganise before_install of travis --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index bc3a1295..92b08010 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,12 +17,14 @@ script: before_install: - sudo apt-get update -qq - sudo apt-get install -qq advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush pngquant + - npm install -g svgo + - mkdir ~/bin + # pngout: - wget http://static.jonof.id.au/dl/kenutils/pngout-20130221-linux.tar.gz - tar -xzf pngout-*-linux.tar.gz - - mv pngout-*-linux pngout-linux - - npm install -g svgo + - mv pngout-*-linux/x86_64/pngout ~/bin env: - - PATH=pngout-linux/x86_64:$PATH + - PATH=~/bin:$PATH matrix: allow_failures: - rvm: ruby-head From 30e0643f3006116a7b997abb7ff75c106b841ea6 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Fri, 8 Aug 2014 03:01:26 +0200 Subject: [PATCH 12/12] switch to building pngquant from source for travis --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 92b08010..86332380 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,9 +16,13 @@ script: - '! bundle show rubocop || bundle exec rubocop' # run rubocop only if it is bundled before_install: - sudo apt-get update -qq - - sudo apt-get install -qq advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush pngquant + - sudo apt-get install -qq advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush - npm install -g svgo - mkdir ~/bin + # pngquant: + - git clone git://github.com/pornel/pngquant.git + - pushd pngquant && git checkout $(git describe --tags --abbrev=0) && make && popd + - mv pngquant/pngquant ~/bin # pngout: - wget http://static.jonof.id.au/dl/kenutils/pngout-20130221-linux.tar.gz - tar -xzf pngout-*-linux.tar.gz