lib/carrierwave/processing/rmagick.rb in carrierwave-0.6.2 vs lib/carrierwave/processing/rmagick.rb in carrierwave-0.7.0

- old
+ new

@@ -88,10 +88,14 @@ end def resize_and_pad(width, height, background=:transparent, gravity=::Magick::CenterGravity) process :resize_and_pad => [width, height, background, gravity] end + + def resize_to_geometry_string(geometry_string) + process :resize_to_geometry_string => [geometry_string] + end end ## # Changes the image encoding format to the given format # @@ -222,10 +226,32 @@ filled end end ## + # Resize the image per the provided geometry string. + # + # === Parameters + # + # [geometry_string (String)] the proportions in which to scale image + # + # === Yields + # + # [Magick::Image] additional manipulations to perform + # + def resize_to_geometry_string(geometry_string) + manipulate! do |img| + new_img = img.change_geometry(geometry_string) do |new_width, new_height| + img.resize(new_width, new_height) + end + destroy_image(img) + new_img = yield(new_img) if block_given? + new_img + end + end + + ## # Manipulate the image with RMagick. This method will load up an image # and then pass each of its frames to the supplied block. It will then # save the image to disk. # # === Gotcha @@ -236,46 +262,95 @@ # most cases. # # === 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 + # + # ==== :read + # A hash of assignments to be given to the RMagick read call. + # + # The options available are identical to those for write, but are passed in directly, like this: + # + # manipulate! :read => { :density => 300 } + # + # ==== :format + # Specify the output format. If unset, the filename extension is used to determine the format. + # # === Raises # # [CarrierWave::ProcessingError] if manipulation failed. # def manipulate!(options={}, &block) cache_stored_file! if !cached? - image = ::Magick::Image.read(current_path) + read_block = create_info_block(options[:read]) + image = ::Magick::Image.read(current_path, &read_block) + frames = if image.size > 1 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 list << processed_frame if processed_frame end 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_info_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 raise CarrierWave::ProcessingError, I18n.translate(:"errors.messages.rmagick_processing_error", :e => e) end private + + def create_info_block(options) + return nil unless options + assignments = 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