Skip to content

Commit

Permalink
Enable passing :write option to manipulate! and yield the options has…
Browse files Browse the repository at this point in the history
…h to the block. Issue #711.
  • Loading branch information
chopmo committed Apr 28, 2012
1 parent aaa61ee commit 37cb9bc
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
48 changes: 44 additions & 4 deletions lib/carrierwave/processing/rmagick.rb
Expand Up @@ -238,6 +238,38 @@ def resize_and_pad(width, height, background=:transparent, gravity=::Magick::Cen
# === Yields
#
# [Magick::Image] manipulations to perform
# [Integer] Frame index if the image contains multiple frames
# [Hash] options, see below
#
# === Options
#
# The options argument to this method is also yielded as the third
# block argument.
#
# Currently, the following options are defined:
#
# ==== :write
# A hash of assignments to be evaluated in the block given to the RMagick write call.
#
# An example:
#
# manipulate! do |img, index, options|
# options[:write] = {
# :quality => 50,
# :depth => 8
# }
# img
# end
#
# This will translate to the following RMagick::Image#write call:
#
# image.write do |img|
# self.quality = 50
# self.depth = 8
# end
#
# ==== :format
# Specify the output format. If unset, the filename extension is used to determine the format.
#
# === Raises
#
Expand All @@ -251,7 +283,7 @@ def manipulate!(options={}, &block)
list = ::Magick::ImageList.new
image.each_with_index do |frame, index|
processed_frame = if block_given?
yield *[frame, index].take(block.arity)
yield *[frame, index, options].take(block.arity)
else
frame
end
Expand All @@ -260,14 +292,15 @@ def manipulate!(options={}, &block)
block_given? ? list : list.append(true)
else
frame = image.first
frame = yield( *[frame, 0].take(block.arity) ) if block_given?
frame = yield( *[frame, 0, options].take(block.arity) ) if block_given?
frame
end

write_block = create_write_block(options[:write])
if options[:format]
frames.write("#{options[:format]}:#{current_path}")
frames.write("#{options[:format]}:#{current_path}", &write_block)
else
frames.write(current_path)
frames.write(current_path, &write_block)
end
destroy_image(frames)
rescue ::Magick::ImageMagickError => e
Expand All @@ -276,6 +309,13 @@ def manipulate!(options={}, &block)

private

def create_write_block(write_options)
return nil unless write_options
assignments = write_options.map { |k, v| "self.#{k} = #{v}" }
code = "lambda { |img| " + assignments.join(";") + "}"
eval code
end

def destroy_image(image)
image.destroy! if image.respond_to?(:destroy!)
end
Expand Down
17 changes: 17 additions & 0 deletions spec/processing/rmagick_spec.rb
Expand Up @@ -73,6 +73,23 @@
end
end

describe "#manipulate!" do
it 'should support passing write options to RMagick' do
image = ::Magick::Image.read(file_path('landscape_copy.jpg'))
::Magick::Image.stub(:read => image)
::Magick::Image::Info.any_instance.should_receive(:quality=).with(50)
::Magick::Image::Info.any_instance.should_receive(:depth=).with(8)

@instance.manipulate! do |img, index, options|
options[:write] = {
:quality => 50,
:depth => 8
}
img
end
end
end

describe "test errors" do
context "invalid image file" do
before do
Expand Down

0 comments on commit 37cb9bc

Please sign in to comment.