给attachment_fu添加图片压缩处理的功能

JavaEye提供了很多图片上传的功能,比如个人头像,博客相册,帖子附件等等,这些功能都是用 attachment_fu插件实现的。

为了避免图片过大,给用户带来浏览速度的麻烦,我们最近加上了图片压缩功能:比如用户上传的是BMP格式,自动转化成PNG。再比如用户上传动态GIF头像,自动取第一帧作为头像。
而attachment_fu插件本身并没有这个功能,我们来看一下如何实现:

attachment_fu支持多个图像处理的库,我推荐使用mini_magick,下面的代码以它为例,给MiniMagick::Image添加压缩的方法:
module MiniMagick
  class Image
    def compressing(convert_gif)
      format = self[:format]
      if convert_gif && format == "GIF"
        #convert 1st frame for animation gif
        run_command("convert","#{@path}[0]", "#{@path}")
      elsif format == "BMP"
        format("PNG")
      end
    end
  end
end


然后我们只需要修改attachment_fu插件的源代码,在mini_magick_processor.rb的 resize_image方法开头添加一行:
img.compressing(true)


在process_attachment_with_processing方法修改with_image block,添加2行:
img.compressing(false)
self.temp_path = img


但是这样做有一个缺点,就是需要直接修改plugin的源代码,这样在升级plugin的时候,会带来一些麻烦:你得记住自己做的改动,然后再手工合并。我们可以利用ruby open class的特性在外部来修改:
Technoweenie::AttachmentFu::Processors::MiniMagickProcessor.module_eval do
  def resize_image_with_compressing(img, size)
    img.compressing(true)
    resize_image_without_compressing(img, size)
  end
  
  alias_method_chain :resize_image, :compressing
  
  def process_attachment_with_processing_with_compressing
    with_image do |img|
      img.compressing(false)
      self.temp_path = img
    end if image?
    process_attachment_with_processing_without_compressing
  end
  
  alias_method_chain :process_attachment_with_processing, :compressing
end


我们可以把这段代码和最开始的压缩方法代码放在一个initializer里面,这样就实现了无侵入的plugin hack,虽然代码比直接修改要复杂一些,但对于plugin升级和维护会很方便,如果你有其他的插件需要自定制,也可以考虑采用这种方式。

除了格式转化达到压缩效果以外,你也可以使用更高PNG或者JPG格式的压缩率,或者添加水印功能,具体的命令api可参考magick文档。

你可能感兴趣的:(Ruby)