MiniMagick for FileColumn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
module FileColumn # :nodoc:
  class BaseUploadedFile # :nodoc:
    def transform_with_magick
      if needs_transform?
        begin
          img = ::MiniMagick::Image::from_file(absolute_path)
        rescue ::MiniMagick::MiniMagickError
          if options[:magick][:image_required]
            @magick_errors ||= []
            @magick_errors << "invalid image"
          end
          return
        end
        if options[:magick][:versions]
          options[:magick][:versions].each_pair do |version, version_options|
            next if version_options[:lazy]
            dirname = version_options[:name]
            FileUtils.mkdir File.join(@dir, dirname)
            transform_image(img, version_options, absolute_path(dirname))
          end
        end
        if options[:magick][:size] or options[:magick][:crop] or options[:magick][:transformation] or options[:magick][:attributes]
          transform_image(img, options[:magick], absolute_path)
        end
        GC.start
      end
    end
    def create_magick_version_if_needed(version)
      # MiniMagick might not have been loaded so far.
      # We do not want to require it on every call of this method
      # as this might be fairly expensive, so we just try if ::MiniMagick
      # exists and require it if not.
      begin 
        ::MiniMagick 
      rescue NameError
        require 'mini_magick'
      end
      if version.is_a?(Symbol)
        version_options = options[:magick][:versions][version]
      else
        version_options = MagickExtension::process_options(version)
      end
      unless File.exists?(absolute_path(version_options[:name]))
        begin
          img = ::MiniMagick::Image::from_file(absolute_path)
        rescue ::MiniMagick::MiniMagickError
          # we might be called directly from the view here
          # so we just return nil if we cannot load the image
          return nil
        end
        dirname = version_options[:name]
        FileUtils.mkdir File.join(@dir, dirname)
        transform_image(img, version_options, absolute_path(dirname))
      end
      version_options[:name]
    end
    attr_reader :magick_errors
    def has_magick_errors?
      @magick_errors and !@magick_errors.empty?
    end
    private
    def needs_transform?
      options[:magick] and just_uploaded? and 
        (options[:magick][:size] or options[:magick][:versions] or options[:magick][:transformation] or options[:magick][:attributes])
    end
    def transform_image(img, img_options, dest_path)
      begin
        if img_options[:transformation]
          if img_options[:transformation].is_a?(Symbol)
            img = @instance.send(img_options[:transformation], img)
          else
            img = img_options[:transformation].call(img)
          end
        end
      img.combine_options do | i |
        if img_options[:crop]
          dx, dy = img_options[:crop].split(':').map { |x| x.to_f }
          w, h = (img.rows * dx / dy), (img.columns * dy / dx)
          i.gravity "Center"
          i.crop "#{[img.columns, w].min}x#{[img.rows, h].min}"
        end
        if img_options[:size]
          i.resize img_options[:size]
        end
        i.strip # strip unnecessary profiles
        i.depth 8 # otherwise PNG bloats, big time
        i.quality 80 # save with reasonable quality for a thumbnail
      end
      ensure
        img.write(dest_path) #do
        File.chmod options[:permissions], dest_path
      end
    end
  end
  # If you are using file_column to upload images, you can
  # directly process the images with MiniMagick,
  # a ruby extension
  # for accessing the popular imagemagick libraries. You can find
  # more information about MiniMagick at http://MiniMagick.rubyforge.org.
  #
  # You can control what to do by adding a <tt>:magick</tt> option
  # to your options hash. All operations are performed immediately
  # after a new file is assigned to the file_column attribute (i.e.,
  # when a new file has been uploaded).
  #
  # == Resizing images
  #
  # To resize the uploaded image according to an imagemagick geometry
  # string, just use the <tt>:size</tt> option:
  #
  #    file_column :image, :magick => {:size => "800x600>"}
  #
  # If the uploaded file cannot be loaded by MiniMagick, file_column will
  # signal a validation error for the corresponding attribute. If you
  # want to allow non-image files to be uploaded in a column that uses
  # the <tt>:magick</tt> option, you can set the <tt>:image_required</tt>
  # attribute to +false+:
  #
  #    file_column :image, :magick => {:size => "800x600>",
  #                                    :image_required => false }
  #
  # == Multiple versions
  #
  # You can also create additional versions of your image, for example
  # thumb-nails, like this:
  #    file_column :image, :magick => {:versions => {
  #         :thumb => {:size => "50x50"},
  #         :medium => {:size => "640x480>"}
  #       }
  #
  # These versions will be stored in separate sub-directories, named like the
  # symbol you used to identify the version. So in the previous example, the
  # image versions will be stored in "thumb", "screen" and "widescreen"
  # directories, resp. 
  # A name different from the symbol can be set via the <tt>:name</tt> option.
  #
  # These versions can be accessed via FileColumnHelper's +url_for_image_column+
  # method like this:
  #
  #    <%= url_for_image_column "entry", "image", :thumb %>
  #
  # == Cropping images
  #
  # If you wish to crop your images with a size ratio before scaling
  # them according to your version geometry, you can use the :crop directive.
  #    file_column :image, :magick => {:versions => {
  #         :square => {:crop => "1:1", :size => "50x50", :name => "thumb"},
  #         :screen => {:crop => "4:3", :size => "640x480>"},
  #         :widescreen => {:crop => "16:9", :size => "640x360!"},
  #       }
  #    }
  #
  # == Custom attributes
  #
  # To change some of the image properties like compression level before they
  # are saved you can set the <tt>:attributes</tt> option.
  # For a list of available attributes go to http://www.simplesystems.org/MiniMagick/doc/info.html
  # 
  #     file_column :image, :magick => { :attributes => { :quality => 30 } }
  # 
  # == Custom transformations
  #
  # To perform custom transformations on uploaded images, you can pass a
  # callback to file_column:
  #    file_column :image, :magick => 
  #       Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) }
  #
  # The callback you give, receives one argument, which is an instance
  # of Magick::Image, the MiniMagick image class. It should return a transformed
  # image. Instead of passing a <tt>Proc</tt> object, you can also give a
  # <tt>Symbol</tt>, the name of an instance method of your model.
  #
  # Custom transformations can be combined via the standard :size and :crop
  # features, by using the :transformation option:
  #   file_column :image, :magick => {
  #      :transformation => Proc.new { |image| ... },
  #      :size => "640x480"
  #    }
  #
  # In this case, the standard resizing operations will be performed after the
  # custom transformation.
  #
  # Of course, custom transformations can be used in versions, as well.
  #
  # <b>Note:</b> You'll need the
  # MiniMagick extension being installed  in order to use file_column's
  # imagemagick integration.
  module MagickExtension
    def self.file_column(klass, attr, options) # :nodoc:
      require 'mini_magick'
      options[:magick] = process_options(options[:magick],false) if options[:magick]
      if options[:magick][:versions]
        options[:magick][:versions].each_pair do |name, value|
          options[:magick][:versions][name] = process_options(value, name.to_s)
        end
      end
      state_method = "#{attr}_state".to_sym
      after_assign_method = "#{attr}_magick_after_assign".to_sym
      klass.send(:define_method, after_assign_method) do
        self.send(state_method).transform_with_magick
      end
      options[:after_upload] ||= []
      options[:after_upload] << after_assign_method
      klass.validate do |record|
        state = record.send(state_method)
        if state.has_magick_errors?
          state.magick_errors.each do |error|
            record.errors.add attr, error
          end
        end
      end
    end
    def self.process_options(options,create_name=true)
      case options
      when String then options = {:size => options}
      when Proc, Symbol then options = {:transformation => options }
      end
      if options[:geometry]
        options[:size] = options.delete(:geometry)
      end
      options[:image_required] = true unless options.key?(:image_required)
      if options[:name].nil? and create_name
        if create_name == true
          hash = 0
          for key in [:size, :crop]
            hash = hash ^ options[key].hash if options[key]
          end
          options[:name] = hash.abs.to_s(36)
        else
          options[:name] = create_name
        end
      end
      options
    end
  end
end

更改 vendor/plugins/file_column/lib/magick_file_column.rb 文件即可。

    Posted by devon At March 07, 2008 12:42

John Smith在2008-12-19 06:35:12说:

loan modification [url=http://www.he-directory.com/Business/Financial_Services/?s=A&p=501 ] loan modification [/url] [link=http://www.he-directory.com/Business/Financia

John Smith在2008-12-19 14:11:24说:

refinance [url=http://www.abilogic.com/dir/business/Financial_Services/Mortgages/page_2.html ] refinance [/url] [link=http://www.abilogic.com/dir/business/Fi

John Smith在2008-12-22 14:23:35说:

loan modification [url=http://www.gotlink.info/Business_Economy/Financial_Services/?p=7 ] loan modification [/url] [link=http://www.gotlink.info/Business_Economy/Financia


请登录以发表评论。