chunky_png 1.3.2 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 323e9e7a7ff35bce40522c1f9f26763168fef3e0
4
- data.tar.gz: a82e301e630948b3ecdc34bc7edfc3dc89bbdb93
3
+ metadata.gz: dba372d700355f7ad31ef72fc4615c6425ffbfeb
4
+ data.tar.gz: 090bfa0d2238e1568fffd5b21cc0d12f0c69106a
5
5
  SHA512:
6
- metadata.gz: 2a62b78538767364a849f3c555e1cc3d8204a9dfb58638cf264033bb65d265ff7858c0c873858699906b627a0bcdbf7fbe46ab481a502663a01086470ae70420
7
- data.tar.gz: 8be957364e9c0e2aae3b1a4789f370e24db4a5fc62e2458dab4d3e416b93bffd099a43f0bc3934177dfa0d22dfb222ed91a6db279d304655560da41f17a8131f
6
+ metadata.gz: b8fb329422a0509b8707321d15ef5c5a7cd6e3082e2cbdee61b490825b1bc1902cdbb8b484e1003c2dc5990435a935c391b76f86addb587f57424651e145b3a8
7
+ data.tar.gz: a2e0bbfc3a15c46e0f2d43ea1724d3821936ccc79c4957acf4f27f31f090e9902b33bae5a9cb6a72008d3ccae09aef6fb695498c5a55b1ecb03d6b8e954ca26e
@@ -0,0 +1,38 @@
1
+ # ChunkyPNG benchmark suite
2
+
3
+ I would like the performance of this library as good as possible, and I will
4
+ gladly accept changes to this library that improves performance.
5
+
6
+ The library comes with a basic benchmark suite is intended to test the speed
7
+ of PNG decoding and encoding against different ruby interpreters. Execute them
8
+ using rake. You can set the number of runs by passing the N environment variable.
9
+
10
+ bundle exec rake benchmark:encoding
11
+ bundle exec rake benchmark:decoding
12
+
13
+ bundle exec rake benchmark N=10 # Run all of them with 10 iterations
14
+
15
+ You can use rvm to run the benchmarks against different interpreters. Of course,
16
+ make sure that the chunky_png is installed for all your interpreters.
17
+
18
+ rvm 1.8.7,1.9.3,rbx bundle exec rake benchmark N=10
19
+
20
+ ## Results
21
+
22
+ What is a speed improvement on one interpreter doesn't necessarily mean the
23
+ performance will be better on other interpreters as well. Please make sure to
24
+ benchamrk different RUby interpreters. When it comes to different Ruby
25
+ interpreters, the priority is the performance on recent MRI versions.
26
+
27
+ Some very old benchmark result (using N=50) on my 2007 iMac can be found in
28
+ [this gist](https://gist.github.com/wvanbergen/495323).
29
+
30
+ ## Why is this relevant?
31
+
32
+ ChunkyPNG is a pure Ruby library to handle PNG files. Decoding a PNG requires
33
+ a lot of integer math and bitwise operations, and moderate use of the unpack
34
+ method to read binary data. Encoding is a good test for `Array#pack`, and
35
+ depending on the encoding options, also requires a lot of calculations.
36
+ Therefore, the library is a good benchmark candidate for these methods and
37
+ algorithms. It has been used to improve the `Array#pack` and `String#unpack`
38
+ methods in Rubinius.
@@ -0,0 +1,50 @@
1
+ # Contributing to ChunkyPNG
2
+
3
+ I will gladly accept any contributions from anybody to improve this library. However, I like to keep
4
+ the scope and complexity of this project relatively small. This way, with the limited amount of time I
5
+ dedicate to this project, this library remains a solid piece of software that many people rely on in
6
+ their workflow.
7
+
8
+ ## Scope
9
+
10
+ The scope of this library is defined as:
11
+
12
+ 1. Reading and writing any PNG image that conforms to the spec, with proper handling of images that do not.
13
+ 2. Basic canvas drawing and compositing operations to create new or edit existing images.
14
+ 3. Remain compatible with Ruby versions that are widely used.
15
+
16
+ I will close issues and pull requests that go beyond this scope. If you want to work on something,
17
+ but are not sure if it will be in scope, feel free to reach out to me!
18
+
19
+ ## Reporting bugs
20
+
21
+ - First, see if somebody else has reported the problem already.
22
+ - Try to include as much relevant information as possible, so I can recreate the problem.
23
+ - If possible, include the PNG image that is causing the issue.
24
+ - If possible, include a code snippet that exposes the problem.
25
+
26
+ ## Pull requests
27
+
28
+ Title and description:
29
+
30
+ - If you are not yet done, please include `[WIP]` in the title of your pull request.
31
+ - Explain why your changes are relevant in the description of your pull request.
32
+ - If your changes improve performance, include benchmark methodology and results in the PR.
33
+ See BENCHMARKING.md for more information.
34
+
35
+ Code:
36
+
37
+ - Don't break backwards compatibility.
38
+ - Follow code conventions. They are not defined, so look at the code around you.
39
+ - Add Yardoc comments as documentation.
40
+
41
+ Specs:
42
+
43
+ - Always include specs that test your changes, to prevent me from breaking your code later.
44
+ - If your specs use PNG files, try to keep them as small as possible to keep the test suite snappy.
45
+ - Make sure that the specs are passing for all Rubies on [Travis CI](https://travis-ci.org/wvanbergen/chunky_png/).
46
+
47
+ Misc:
48
+
49
+ - Add an entry to CHANGELOG.md.
50
+ - Do not change `ChunkyPNG::VERSION`
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2013 Willem van Bergen
1
+ Copyright (c) 2010-2014 Willem van Bergen
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -13,21 +13,21 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
15
15
  s.description = <<-EOT
16
- This pure Ruby library can read and write PNG images without depending on an external
16
+ This pure Ruby library can read and write PNG images without depending on an external
17
17
  image library, like RMagick. It tries to be memory efficient and reasonably fast.
18
-
19
- It supports reading and writing all PNG variants that are defined in the specification,
20
- with one limitation: only 8-bit color depth is supported. It supports all transparency,
21
- interlacing and filtering options the PNG specifications allows. It can also read and
18
+
19
+ It supports reading and writing all PNG variants that are defined in the specification,
20
+ with one limitation: only 8-bit color depth is supported. It supports all transparency,
21
+ interlacing and filtering options the PNG specifications allows. It can also read and
22
22
  write textual metadata from PNG files. Low-level read/write access to PNG chunks is
23
23
  also possible.
24
-
24
+
25
25
  This library supports simple drawing on the image canvas and simple operations like
26
- alpha composition and cropping. Finally, it can import from and export to RMagick for
26
+ alpha composition and cropping. Finally, it can import from and export to RMagick for
27
27
  interoperability.
28
-
29
- Also, have a look at OilyPNG at http://github.com/wvanbergen/oily_png. OilyPNG is a
30
- drop in mixin module that implements some of the ChunkyPNG algorithms in C, which
28
+
29
+ Also, have a look at OilyPNG at http://github.com/wvanbergen/oily_png. OilyPNG is a
30
+ drop in mixin module that implements some of the ChunkyPNG algorithms in C, which
31
31
  provides a massive speed boost to encoding and decoding.
32
32
  EOT
33
33
 
@@ -37,10 +37,10 @@ Gem::Specification.new do |s|
37
37
  s.license = 'MIT'
38
38
 
39
39
  s.add_development_dependency('rake')
40
- s.add_development_dependency('rspec', '~> 2.2')
40
+ s.add_development_dependency('rspec', '~> 3')
41
41
 
42
42
  s.rdoc_options << '--title' << s.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
43
- s.extra_rdoc_files = ['README.rdoc', 'BENCHMARKS.rdoc']
43
+ s.extra_rdoc_files = ['README.rdoc']
44
44
 
45
45
  s.files = `git ls-files`.split($/)
46
46
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
@@ -177,7 +177,7 @@ module ChunkyPNG
177
177
 
178
178
  new_pixels = []
179
179
  for cy in 0...crop_height do
180
- new_pixels += pixels.slice((cy + y) * width + x, crop_width)
180
+ new_pixels.concat pixels.slice((cy + y) * width + x, crop_width)
181
181
  end
182
182
  replace_canvas!(crop_width, crop_height, new_pixels)
183
183
  end
@@ -582,16 +582,16 @@ module ChunkyPNG
582
582
  # @param [Integer] color The ChunkyPNG color to convert.
583
583
  # @param [Boolean] include_alpha Flag indicates whether a fourth element
584
584
  # representing alpha channel should be included in the returned array.
585
- # @return [Array<Fixnum>[0]] The hue of the color (0-360)
586
- # @return [Array<Fixnum>[1]] The saturation of the color (0-1)
587
- # @return [Array<Fixnum>[2]] The value of the color (0-1)
588
- # @return [Array<Fixnum>[3]] Optional fourth element for alpha, included if
585
+ # @return [Array[0]] The hue of the color (0-360)
586
+ # @return [Array[1]] The saturation of the color (0-1)
587
+ # @return [Array[2]] The value of the color (0-1)
588
+ # @return [Array[3]] Optional fourth element for alpha, included if
589
589
  # include_alpha=true (0-255)
590
590
  # @see http://en.wikipedia.org/wiki/HSL_and_HSV
591
591
  def to_hsv(color, include_alpha = false)
592
592
  hue, chroma, max, min = hue_and_chroma(color)
593
593
  value = max
594
- saturation = chroma.zero? ? 0 : chroma.fdiv(value)
594
+ saturation = chroma.zero? ? 0.0 : chroma.fdiv(value)
595
595
 
596
596
  include_alpha ? [hue, saturation, value, a(color)] :
597
597
  [hue, saturation, value]
@@ -619,7 +619,7 @@ module ChunkyPNG
619
619
  def to_hsl(color, include_alpha = false)
620
620
  hue, chroma, max, min = hue_and_chroma(color)
621
621
  lightness = 0.5 * (max + min)
622
- saturation = chroma.zero? ? 0 : chroma.fdiv(1 - (2*lightness-1).abs)
622
+ saturation = chroma.zero? ? 0.0 : chroma.fdiv(1 - (2 * lightness - 1).abs)
623
623
 
624
624
  include_alpha ? [hue, saturation, lightness, a(color)] :
625
625
  [hue, saturation, lightness]
@@ -650,7 +650,7 @@ module ChunkyPNG
650
650
  end
651
651
  hue = 60 * hue_prime
652
652
 
653
- return hue, chroma, max, min
653
+ return hue.round, chroma, max, min
654
654
  end
655
655
  private :hue_and_chroma
656
656
 
@@ -1,8 +1,8 @@
1
1
  module ChunkyPNG
2
-
3
- # Creates a {ChunkyPNG::Dimension} instance using arguments that can be interpreted
2
+
3
+ # Creates a {ChunkyPNG::Dimension} instance using arguments that can be interpreted
4
4
  # as width and height.
5
- #
5
+ #
6
6
  # @overload Dimension(width, height)
7
7
  # @param [Integer] width The width-component of the dimension.
8
8
  # @param [Integer] height The height-component of the dimension.
@@ -15,7 +15,7 @@ module ChunkyPNG
15
15
  #
16
16
  # @overload Dimension(ary)
17
17
  # @param [Array] ary An array with the desired width as first element and the
18
- # desired height as second element, e.g. <tt>[10, 20]</tt>.
18
+ # desired height as second element, e.g. <tt>[10, 20]</tt>.
19
19
  # @return [ChunkyPNG::Dimension] The instantiated dimension.
20
20
  #
21
21
  # @overload Dimension(hash)
@@ -31,7 +31,7 @@ module ChunkyPNG
31
31
  case args.length
32
32
  when 2; ChunkyPNG::Dimension.new(*args)
33
33
  when 1; build_dimension_from_object(args.first)
34
- else raise ArgumentError,
34
+ else raise ArgumentError,
35
35
  "Don't know how to construct a dimension from #{args.inspect}"
36
36
  end
37
37
  end
@@ -59,7 +59,7 @@ module ChunkyPNG
59
59
  end
60
60
  end
61
61
  private_class_method :build_dimension_from_object
62
-
62
+
63
63
  # Class that represents the dimension of something, e.g. a {ChunkyPNG::Canvas}.
64
64
  #
65
65
  # This class contains some methods to simplify performing dimension related checks.
@@ -71,23 +71,23 @@ module ChunkyPNG
71
71
 
72
72
  # @return [Integer] The width-component of this dimension.
73
73
  attr_accessor :width
74
-
74
+
75
75
  # @return [Integer] The height-component of this dimension.
76
76
  attr_accessor :height
77
-
77
+
78
78
  # Initializes a new dimension instance.
79
79
  # @param [Integer] width The width-component of the new dimension.
80
80
  # @param [Integer] height The height-component of the new dimension.
81
81
  def initialize(width, height)
82
82
  @width, @height = width.to_i, height.to_i
83
83
  end
84
-
84
+
85
85
  # Returns the area of this dimension.
86
86
  # @return [Integer] The area in number of pixels.
87
87
  def area
88
88
  width * height
89
89
  end
90
-
90
+
91
91
  # Checks whether a point is within bounds of this dimension.
92
92
  # @param [ChunkyPNG::Point, ...] A point-like to bounds-check.
93
93
  # @return [true, false] True iff the x and y coordinate fall in this dimension.
@@ -96,16 +96,17 @@ module ChunkyPNG
96
96
  point = ChunkyPNG::Point(*point_like)
97
97
  point.x >= 0 && point.x < width && point.y >= 0 && point.y < height
98
98
  end
99
-
99
+
100
100
  # Checks whether 2 dimensions are identical.
101
101
  # @param [ChunkyPNG::Dimension] The dimension to compare with.
102
102
  # @return [true, false] <tt>true</tt> iff width and height match.
103
103
  def eql?(other)
104
+ return false unless other.respond_to?(:width) && other.respond_to?(:height)
104
105
  other.width == width && other.height == height
105
106
  end
106
-
107
+
107
108
  alias_method :==, :eql?
108
-
109
+
109
110
  # Compares the size of 2 dimensions.
110
111
  # @param [ChunkyPNG::Dimension] The dimension to compare with.
111
112
  # @return [-1, 0, 1] -1 if the other dimension has a larger area, 1 of this
@@ -113,13 +114,13 @@ module ChunkyPNG
113
114
  def <=>(other)
114
115
  other.area <=> area
115
116
  end
116
-
117
+
117
118
  # Casts this dimension into an array.
118
119
  # @return [Array<Integer>] <tt>[width, height]</tt> for this dimension.
119
120
  def to_a
120
121
  [width, height]
121
122
  end
122
-
123
+
123
124
  alias_method :to_ary, :to_a
124
125
  end
125
126
  end
@@ -1,5 +1,5 @@
1
1
  module ChunkyPNG
2
2
  # The current version of ChunkyPNG.
3
3
  # Set it and commit the change this before running rake release.
4
- VERSION = "1.3.2"
4
+ VERSION = "1.3.3"
5
5
  end
@@ -5,31 +5,31 @@ describe ChunkyPNG::Canvas::Adam7Interlacing do
5
5
 
6
6
  describe '#adam7_pass_sizes' do
7
7
  it "should get the pass sizes for a 8x8 image correctly" do
8
- adam7_pass_sizes(8, 8).should == [
8
+ expect(adam7_pass_sizes(8, 8)).to eql [
9
9
  [1, 1], [1, 1], [2, 1], [2, 2], [4, 2], [4, 4], [8, 4]
10
10
  ]
11
11
  end
12
12
 
13
13
  it "should get the pass sizes for a 12x12 image correctly" do
14
- adam7_pass_sizes(12, 12).should == [
14
+ expect(adam7_pass_sizes(12, 12)).to eql [
15
15
  [2, 2], [1, 2], [3, 1], [3, 3], [6, 3], [6, 6], [12, 6]
16
16
  ]
17
17
  end
18
18
 
19
19
  it "should get the pass sizes for a 33x47 image correctly" do
20
- adam7_pass_sizes(33, 47).should == [
20
+ expect(adam7_pass_sizes(33, 47)).to eql [
21
21
  [5, 6], [4, 6], [9, 6], [8, 12], [17, 12], [16, 24], [33, 23]
22
22
  ]
23
23
  end
24
24
 
25
25
  it "should get the pass sizes for a 1x1 image correctly" do
26
- adam7_pass_sizes(1, 1).should == [
26
+ expect(adam7_pass_sizes(1, 1)).to eql [
27
27
  [1, 1], [0, 1], [1, 0], [0, 1], [1, 0], [0, 1], [1, 0]
28
28
  ]
29
29
  end
30
30
 
31
31
  it "should get the pass sizes for a 0x0 image correctly" do
32
- adam7_pass_sizes(0, 0).should == [
32
+ expect(adam7_pass_sizes(0, 0)).to eql [
33
33
  [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]
34
34
  ]
35
35
  end
@@ -37,38 +37,38 @@ describe ChunkyPNG::Canvas::Adam7Interlacing do
37
37
  it "should always maintain the same amount of pixels in total" do
38
38
  [[8, 8], [12, 12], [33, 47], [1, 1], [0, 0]].each do |(width, height)|
39
39
  pass_sizes = adam7_pass_sizes(width, height)
40
- pass_sizes.inject(0) { |sum, (w, h)| sum + (w*h) }.should == width * height
40
+ expect(pass_sizes.inject(0) { |sum, (w, h)| sum + (w*h) }).to eql width * height
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
45
  describe '#adam7_multiplier_offset' do
46
46
  it "should get the multiplier and offset values for pass 1 correctly" do
47
- adam7_multiplier_offset(0).should == [3, 0, 3, 0]
47
+ expect(adam7_multiplier_offset(0)).to eql [3, 0, 3, 0]
48
48
  end
49
-
49
+
50
50
  it "should get the multiplier and offset values for pass 2 correctly" do
51
- adam7_multiplier_offset(1).should == [3, 4, 3, 0]
51
+ expect(adam7_multiplier_offset(1)).to eql [3, 4, 3, 0]
52
52
  end
53
-
53
+
54
54
  it "should get the multiplier and offset values for pass 3 correctly" do
55
- adam7_multiplier_offset(2).should == [2, 0, 3, 4]
55
+ expect(adam7_multiplier_offset(2)).to eql [2, 0, 3, 4]
56
56
  end
57
-
57
+
58
58
  it "should get the multiplier and offset values for pass 4 correctly" do
59
- adam7_multiplier_offset(3).should == [2, 2, 2, 0]
59
+ expect(adam7_multiplier_offset(3)).to eql [2, 2, 2, 0]
60
60
  end
61
-
61
+
62
62
  it "should get the multiplier and offset values for pass 5 correctly" do
63
- adam7_multiplier_offset(4).should == [1, 0, 2, 2]
63
+ expect(adam7_multiplier_offset(4)).to eql [1, 0, 2, 2]
64
64
  end
65
65
 
66
66
  it "should get the multiplier and offset values for pass 6 correctly" do
67
- adam7_multiplier_offset(5).should == [1, 1, 1, 0]
67
+ expect(adam7_multiplier_offset(5)).to eql [1, 1, 1, 0]
68
68
  end
69
-
69
+
70
70
  it "should get the multiplier and offset values for pass 7 correctly" do
71
- adam7_multiplier_offset(6).should == [0, 0, 1, 1]
71
+ expect(adam7_multiplier_offset(6)).to eql [0, 0, 1, 1]
72
72
  end
73
73
  end
74
74
 
@@ -83,10 +83,10 @@ describe ChunkyPNG::Canvas::Adam7Interlacing do
83
83
  ChunkyPNG::Canvas.new(4, 4, 1023344895), # r = 60
84
84
  ChunkyPNG::Canvas.new(8, 4, 1175063295), # r = 70
85
85
  ]
86
-
86
+
87
87
  canvas = ChunkyPNG::Image.new(8,8)
88
88
  submatrices.each_with_index { |m, pass| adam7_merge_pass(pass, canvas, m) }
89
- canvas.should == reference_image('adam7')
89
+ expect(canvas).to eql reference_image('adam7')
90
90
  end
91
91
  end
92
92
 
@@ -96,11 +96,11 @@ describe ChunkyPNG::Canvas::Adam7Interlacing do
96
96
  1.upto(7) do |pass|
97
97
  it "should extract pass #{pass} correctly" do
98
98
  sm = adam7_extract_pass(pass - 1, @canvas)
99
- sm.pixels.length.should == sm.width * sm.height
100
- sm.pixels.uniq.length.should == 1
101
- ChunkyPNG::Color.r(sm[0,0]).should == pass * 10
99
+ expect(sm.pixels.length).to eql sm.width * sm.height
100
+ expect(sm.pixels.uniq.length).to eql 1
101
+ expect(ChunkyPNG::Color.r(sm[0,0])).to eql pass * 10
102
102
  end
103
103
  end
104
104
  end
105
105
 
106
- end
106
+ end
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ChunkyPNG::Canvas do
4
-
4
+
5
5
  describe '#to_data_url' do
6
6
  it "should export a sample canvas to an RGBA stream correctly" do
7
7
  canvas = ChunkyPNG::Canvas.new(2, 2, [ChunkyPNG::Color.rgba(1,2,3,4), ChunkyPNG::Color.rgba(5,6,7,8),
8
8
  ChunkyPNG::Color.rgba(4,3,2,1), ChunkyPNG::Color.rgba(8,7,6,5)])
9
9
 
10
- canvas.to_data_url.should == "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEUBAgMEAwIFBgcIBwazgAAdAAAABHRSTlMEAQgFhYDlfQAAAAxJREFUeJxjUmAKAAAAwAB1GNhIEwAAAABJRU5ErkJggg=="
10
+ expect(canvas.to_data_url).to eql "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEUBAgMEAwIFBgcIBwazgAAdAAAABHRSTlMEAQgFhYDlfQAAAAxJREFUeJxjUmAKAAAAwAB1GNhIEwAAAABJRU5ErkJggg=="
11
11
  end
12
12
  end
13
13
  end
@@ -1,15 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ChunkyPNG::Canvas do
4
-
4
+
5
5
  describe '.from_data_url' do
6
6
  it "should import an image from a data URL" do
7
7
  data_url = reference_canvas('operations').to_data_url
8
- ChunkyPNG::Canvas.from_data_url(data_url).should == reference_canvas('operations')
8
+ expect(ChunkyPNG::Canvas.from_data_url(data_url)).to eql reference_canvas('operations')
9
9
  end
10
-
10
+
11
11
  it "should raise an exception if the string is not a proper data URL" do
12
- lambda { ChunkyPNG::Canvas.from_data_url('whatever') }.should raise_error(ChunkyPNG::SignatureMismatch)
12
+ expect { ChunkyPNG::Canvas.from_data_url('whatever') }.to raise_error(ChunkyPNG::SignatureMismatch)
13
13
  end
14
14
  end
15
15
  end