chunky_png 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
data/chunky_png.gemspec CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
3
3
 
4
4
  # Do not change the version and date fields by hand. This will be done
5
5
  # automatically by the gem release script.
6
- s.version = "0.6.0"
7
- s.date = "2010-02-25"
6
+ s.version = "0.7.0"
7
+ s.date = "2010-03-15"
8
8
 
9
9
  s.summary = "Pure ruby library for read/write, chunk-level access to PNG files"
10
10
  s.description = <<-EOT
data/lib/chunky_png.rb CHANGED
@@ -27,7 +27,7 @@ module ChunkyPNG
27
27
 
28
28
  # The current version of ChunkyPNG. This value will be updated automatically
29
29
  # by them gem:release rake task.
30
- VERSION = "0.6.0"
30
+ VERSION = "0.7.0"
31
31
 
32
32
  ###################################################
33
33
  # PNG international standard defined constants
@@ -67,8 +67,8 @@ module ChunkyPNG
67
67
  ds.transparency_chunk = encoding_palette.to_trns_chunk unless encoding_palette.opaque?
68
68
  end
69
69
 
70
- data = encode_png_pixelstream(encoding[:color_mode], encoding[:interlace])
71
- ds.data_chunks = Chunk::ImageData.split_in_chunks(data)
70
+ data = encode_png_pixelstream(encoding[:color_mode], encoding[:interlace], encoding[:compression])
71
+ ds.data_chunks = Chunk::ImageData.split_in_chunks(data, encoding[:compression])
72
72
  ds.end_chunk = Chunk::End.new
73
73
  return ds
74
74
  end
@@ -86,9 +86,11 @@ module ChunkyPNG
86
86
  def determine_png_encoding(constraints = {})
87
87
 
88
88
  if constraints == :fast_rgb
89
- encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR }
89
+ encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR, :compression => Zlib::BEST_SPEED }
90
90
  elsif constraints == :fast_rgba
91
- encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA }
91
+ encoding = { :color_mode => ChunkyPNG::COLOR_TRUECOLOR_ALPHA, :compression => Zlib::BEST_SPEED }
92
+ elsif constraints == :best_compression
93
+ encoding = { :compression => Zlib::BEST_COMPRESSION }
92
94
  else
93
95
  encoding = constraints
94
96
  end
@@ -103,6 +105,8 @@ module ChunkyPNG
103
105
  encoding[:color_mode] ||= encoding_palette.best_colormode
104
106
  end
105
107
 
108
+ encoding[:compression] ||= Zlib::DEFAULT_COMPRESSION
109
+
106
110
  encoding[:interlace] = case encoding[:interlace]
107
111
  when nil, false, ChunkyPNG::INTERLACING_NONE then ChunkyPNG::INTERLACING_NONE
108
112
  when true, ChunkyPNG::INTERLACING_ADAM7 then ChunkyPNG::INTERLACING_ADAM7
@@ -116,26 +120,28 @@ module ChunkyPNG
116
120
  # mode, possibly with interlacing.
117
121
  # @param [Integer] color_mode The color mode to use for encoding.
118
122
  # @param [Integer] interlace The interlacing method to use.
119
- # @param [String] The PNG encoded canvas as string.
120
- def encode_png_pixelstream(color_mode = ChunkyPNG::COLOR_TRUECOLOR, interlace = ChunkyPNG::INTERLACING_NONE)
123
+ # @param [Integer] compression The Zlib compression level.
124
+ # @return [String] The PNG encoded canvas as string.
125
+ def encode_png_pixelstream(color_mode = ChunkyPNG::COLOR_TRUECOLOR, interlace = ChunkyPNG::INTERLACING_NONE, compression = ZLib::DEFAULT_COMPRESSION)
121
126
 
122
127
  if color_mode == ChunkyPNG::COLOR_INDEXED && (encoding_palette.nil? || !encoding_palette.can_encode?)
123
128
  raise "This palette is not suitable for encoding!"
124
129
  end
125
130
 
126
131
  case interlace
127
- when ChunkyPNG::INTERLACING_NONE then encode_png_image_without_interlacing(color_mode)
128
- when ChunkyPNG::INTERLACING_ADAM7 then encode_png_image_with_interlacing(color_mode)
132
+ when ChunkyPNG::INTERLACING_NONE then encode_png_image_without_interlacing(color_mode, compression)
133
+ when ChunkyPNG::INTERLACING_ADAM7 then encode_png_image_with_interlacing(color_mode, compression)
129
134
  else raise "Unknown interlacing method!"
130
135
  end
131
136
  end
132
137
 
133
138
  # Encodes the canvas according to the PNG format specification with a given color mode.
134
139
  # @param [Integer] color_mode The color mode to use for encoding.
135
- # @param [String] Th PNG encoded canvas as string.
136
- def encode_png_image_without_interlacing(color_mode)
140
+ # @param [Integer] compression The Zlib compression level.
141
+ # @return [String] The PNG encoded canvas as string.
142
+ def encode_png_image_without_interlacing(color_mode, compression = ZLib::DEFAULT_COMPRESSION)
137
143
  stream = ""
138
- encode_png_image_pass_to_stream(stream, color_mode)
144
+ encode_png_image_pass_to_stream(stream, color_mode, compression)
139
145
  stream
140
146
  end
141
147
 
@@ -146,13 +152,14 @@ module ChunkyPNG
146
152
  # one by one, concatenating the resulting strings.
147
153
  #
148
154
  # @param [Integer] color_mode The color mode to use for encoding.
149
- # @param [String] Th PNG encoded canvas as string.
150
- def encode_png_image_with_interlacing(color_mode)
155
+ # @param [Integer] compression The Zlib compression level.
156
+ # @return [String] The PNG encoded canvas as string.
157
+ def encode_png_image_with_interlacing(color_mode, compression = ZLib::DEFAULT_COMPRESSION)
151
158
  stream = ""
152
159
  0.upto(6) do |pass|
153
160
  subcanvas = self.class.adam7_extract_pass(pass, self)
154
161
  subcanvas.encoding_palette = encoding_palette
155
- subcanvas.encode_png_image_pass_to_stream(stream, color_mode)
162
+ subcanvas.encode_png_image_pass_to_stream(stream, color_mode, compression)
156
163
  end
157
164
  stream
158
165
  end
@@ -160,17 +167,20 @@ module ChunkyPNG
160
167
  # Encodes the canvas to a stream, in a given color mode.
161
168
  # @param [String, IO, :<<] stream The stream to write to.
162
169
  # @param [Integer] color_mode The color mode to use for encoding.
163
- def encode_png_image_pass_to_stream(stream, color_mode)
170
+ # @param [Integer] compression The Zlib compression level.
171
+ def encode_png_image_pass_to_stream(stream, color_mode, compression = ZLib::DEFAULT_COMPRESSION)
164
172
 
165
- case color_mode
166
- when ChunkyPNG::COLOR_TRUECOLOR_ALPHA
173
+ if compression < Zlib::BEST_COMPRESSION && color_mode == ChunkyPNG::COLOR_TRUECOLOR_ALPHA
174
+ # Fast RGBA saving routine
167
175
  stream << pixels.pack("xN#{width}" * height)
168
176
 
169
- when ChunkyPNG::COLOR_TRUECOLOR
177
+ elsif compression < Zlib::BEST_COMPRESSION && color_mode == ChunkyPNG::COLOR_TRUECOLOR
178
+ # Fast RGB saving routine
170
179
  line_packer = 'x' + ('NX' * width)
171
180
  stream << pixels.pack(line_packer * height)
172
181
 
173
182
  else
183
+ # Normal saving routine
174
184
  pixel_size = Color.bytesize(color_mode)
175
185
  pixel_encoder = case color_mode
176
186
  when ChunkyPNG::COLOR_TRUECOLOR then lambda { |color| Color.to_truecolor_bytes(color) }
@@ -184,7 +194,7 @@ module ChunkyPNG
184
194
  previous_bytes = Array.new(pixel_size * width, 0)
185
195
  each_scanline do |line|
186
196
  unencoded_bytes = line.map(&pixel_encoder).flatten
187
- stream << encode_png_scanline_up(unencoded_bytes, previous_bytes, pixel_size).pack('C*')
197
+ stream << encode_png_scanline_paeth(unencoded_bytes, previous_bytes, pixel_size).pack('C*')
188
198
  previous_bytes = unencoded_bytes
189
199
  end
190
200
  end
@@ -191,8 +191,8 @@ module ChunkyPNG
191
191
  Zlib::Inflate.inflate(data_chunks.map { |c| c.content }.join(''))
192
192
  end
193
193
 
194
- def self.split_in_chunks(data, chunk_size = 2147483647)
195
- streamdata = Zlib::Deflate.deflate(data)
194
+ def self.split_in_chunks(data, level = Zlib::DEFAULT_COMPRESSION, chunk_size = 2147483647)
195
+ streamdata = Zlib::Deflate.deflate(data, level)
196
196
  # TODO: Split long streamdata over multiple chunks
197
197
  [ ChunkyPNG::Chunk::ImageData.new('IDAT', streamdata) ]
198
198
  end
@@ -30,6 +30,27 @@ describe ChunkyPNG::Canvas::PNGEncoding do
30
30
 
31
31
  File.unlink(filename)
32
32
  end
33
+
34
+ it "should save an image using the normal routine correctly" do
35
+ canvas = reference_canvas('operations')
36
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::DEFAULT_COMPRESSION).and_return('')
37
+ canvas.to_blob
38
+ end
39
+
40
+
41
+ it "should save an image using the :best_compression routine correctly" do
42
+ canvas = reference_canvas('operations')
43
+ canvas.should_not_receive(:encode_png_scanline)
44
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::BEST_SPEED).and_return('')
45
+ canvas.to_blob(:fast_rgba)
46
+ end
47
+
48
+ it "should save an image using the :best_compression routine correctly" do
49
+ canvas = reference_canvas('operations')
50
+ canvas.should_receive(:encode_png_scanline_paeth).at_least(:once).and_return([5, 0, 0, 0, 0, 0, 0])
51
+ Zlib::Deflate.should_receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('')
52
+ canvas.to_blob(:best_compression)
53
+ end
33
54
  end
34
55
 
35
56
  describe '#encode_scanline' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chunky_png
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-02-25 00:00:00 -05:00
12
+ date: 2010-03-15 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency