OSDN Git Service

9c1514f3a52b3a9f0c8554b498555eb4761c6d7e
[pettanr/pettanr.git] / app / models / resource_picture.rb
1 #素材
2 class ResourcePicture < ActiveRecord::Base
3   belongs_to :artist
4   belongs_to :license
5   belongs_to :picture
6   has_many :panel_pictures
7   belongs_to :original_picture
8   
9   validates :ext, :presence => true, :length => {:maximum => 4}, :inclusion => {:in => ['png', 'jpeg', 'gif']}
10   validates :width, :presence => true, :numericality => true, :natural_number => true
11   validates :height, :presence => true, :numericality => true, :natural_number => true
12   validates :filesize, :presence => true, :numericality => {:greater_than => 0, :less_than_or_equal_to => 2000000}, :natural_number => true
13   validates :artist_id, :presence => true, :numericality => true, :existence => true
14   validates :license_id, :presence => true, :numericality => true, :existence => true
15   validates :original_picture_id, :presence => true, :numericality => true, :existence => true
16   validates :artist_name, :presence => true
17   validates :classname, :presence => true, :length => {:maximum => 50}
18   validates :picture_id, :presence => true, :numericality => true, :existence => true
19   
20   before_destroy :destroy_with_file
21   
22   def destroy_with_file
23     PictureIO.resource_picture_io.delete self.filename
24     PictureIO.resource_picture_io.class.subdirs.each do |d|
25       next if d.empty?
26       PictureIO.resource_picture_io.delete(self.filename, d) if PictureIO.resource_picture_io.exist?(self.filename, d)
27     end
28   end
29   
30   def self.resize(data, dw, dh)
31     Magick::Image.from_blob(data).shift.resize(dw, dh)
32   end
33   
34   #サイズの調整(limw,limhに必ず収まるように合わせる)
35   def self.fix_size_both(limw, limh, w, h)
36     wr = if w > limw
37       limw*100/w
38     else
39       100
40     end
41     hr = if h > limh
42       limh*100/h
43     else
44       100
45     end
46     res = if wr < hr
47       #幅の方が圧縮率が高い
48       [w*wr/100, h*wr/100]
49     else
50       #高さの方が圧縮率が高い
51       [w*hr/100, h*hr/100]
52     end
53     res
54   end
55   
56   def dext
57     self.ext.downcase
58   end
59   
60   def filename
61     "#{self.id}.#{self.dext}"
62   end
63   
64   def gifname
65     "#{self.id}.gif"
66   end
67   
68   def mime_type
69     "image/#{self.dext}"
70   end
71   
72   def url subdir = nil
73     '/resource_pictures/' + (subdir.to_s.empty? ? '' : subdir.to_s + '/' ) + filename
74   end
75   
76   def thumbnail(rimg)
77     tw, th = ResourcePicture.fix_size_both(MagicNumber['thumbnail_width'], MagicNumber['thumbnail_height'], rimg.columns, rimg.rows)
78     ResourcePicture.resize(rimg.to_blob, tw, th).to_blob
79   end
80   
81   def opt_img_tag
82     tw, th = ResourcePicture.fix_size_both(MagicNumber['thumbnail_width'], MagicNumber['thumbnail_height'], self.width, self.height)
83     {:src => self.url, :width => tw, :height => th}
84   end
85   
86   def copy_data(op)
87     attr = {:width => op.width, :height => op.height, :ext => op.ext, :filesize => op.filesize, 
88       :original_picture_id => op.id, :artist_id => op.artist_id, :md5 => op.md5
89     }
90     self.attributes = attr
91   end
92   
93   def data_to_mgk picture_data
94     begin
95       mgk = Magick::Image.from_blob(picture_data).shift
96     rescue 
97       self.errors.add :base, 'magick failed'
98       return false
99     end
100     mgk
101   end
102   
103   def op_mgk
104     d = self.original_picture.restore
105     return false unless d
106     self.data_to_mgk d
107   end
108   
109   def new_picture mgk
110     pc = Picture.new
111     pc.copy_data self
112     pc.store mgk
113     pc
114   end
115   
116   
117   def to_gif?
118     self.dext == 'png' and self.flag_gif_convert >= 0
119   end
120   
121   def self.png_to_gif(data)
122     res = nil
123     begin
124       mgk = Magick::Image.from_blob(data).shift
125       mgk.format = 'gif'
126       res = mgk
127     rescue
128       res = false
129     end
130     res
131   end
132   
133   def store
134     res = false
135     self.copy_data self.original_picture
136     mgk = self.op_mgk
137     return false unless mgk
138     OriginalPicture.transaction do
139       pc = self.new_picture mgk
140       if res = pc.valid?
141         self.picture_id = pc.id
142         if res = self.save
143           res = self.store_picture_with_gif(mgk)
144         end
145       else
146         self.errors.add :base, 'picture does not create'
147       end
148       raise ActiveRecord::Rollback unless res
149     end
150     res
151   end
152   
153   def store_picture_with_gif(mgk)
154     if res = self.store_picture(mgk, self.filename)
155       if self.to_gif?
156         if gifmgk = ResourcePicture.png_to_gif(mgk.to_blob)
157           res = self.store_picture(gifmgk, self.gifname)
158         else
159           self.errors.add :base, 'picture data can not conv to gif'
160           res = false
161         end
162       end
163     else
164       self.errors.add :base, 'resource picture io does not work'
165     end
166     res
167   end
168   
169   def store_picture(mgk, fn)
170     res = false
171     tdata = self.flag_thumbnail >= 0 ? thumbnail(mgk) : mgk.to_blob
172     fdata = mgk.to_blob
173     return false unless PictureIO.resource_picture_io.put(tdata, fn)
174     PictureIO.resource_picture_io.put(fdata, fn, 'full')
175   end
176   
177   def restore(subdir = nil)
178     PictureIO.resource_picture_io.get self.filename, subdir
179   end
180   
181   def self.default_page_size
182     25
183   end
184   
185   def self.max_page_size
186     100
187   end
188   
189   def self.page prm = nil
190     page = prm.to_i
191     page = 1 if page < 1
192     page
193   end
194   
195   def self.page_size prm = self.default_page_size
196     page_size = prm.to_i
197     page_size = self.max_page_size if page_size > self.max_page_size
198     page_size = self.default_page_size if page_size < 1
199     page_size
200   end
201   
202   def self.offset cnt, prm = nil
203     offset = prm.to_i
204     offset = cnt - 1 if offset >= cnt
205     offset = cnt - offset.abs if offset < 0
206     offset = 0 if offset < 0
207     offset
208   end
209   
210   def self.list opt = {}, page = 1, page_size = self.default_page_size
211     opt.merge!(self.list_opt) unless opt[:include]
212     opt.merge!({:order => 'updated_at desc', :limit => page_size, :offset => (page -1) * page_size})
213     ResourcePicture.find(:all, opt)
214   end
215   
216   def self.list_opt
217     {:include => [:license, :artist]}
218   end
219   
220   def self.list_json_opt
221     {:include => [:license, :artist]}
222   end
223   
224   def self.show rid, opt = {}
225     r = ResourcePicture.find(rid, :include => self.show_include_opt(opt))
226 #    raise ActiveRecord::Forbidden unless c.visible?(au)
227     r
228   end
229   
230   def self.show_include_opt opt = {}
231     res = [:license, :artist]
232     res.push(opt[:include]) if opt[:include]
233     res
234   end
235   
236   def self.show_json_include_opt
237     {:include => [:license, :artist]}
238   end
239   
240   def self.visible_count
241     ResourcePicture.count
242   end
243   
244   def credit_template
245     "#{self.classname.tableize}/attributes/credit"
246   end
247   
248   def credit_data
249     begin
250       @credit_data = JSON.parse(self.credit) unless @credit_data
251     rescue 
252     end
253     @credit_data
254   end
255   
256   def flags
257     begin
258       @flags = JSON.parse(self.settings) unless @flags
259     rescue 
260     end
261     @flags
262   end
263   
264   def flags=(s)
265     @flags = s
266   end
267   
268   def flag_open
269     @flag_open = flags["open"] unless @flag_open
270     @flag_open
271   end
272   
273   def flag_commercial
274     @flag_commercial = flags["commercial"] unless @flag_commercial
275     @flag_commercial
276   end
277   
278   def flag_official
279     @flag_official = flags["official"] unless @flag_official
280     @flag_official
281   end
282   
283   def flag_attribution
284     @flag_attribution = flags["attribution"] unless @flag_attribution
285     @flag_attribution
286   end
287   
288   def flag_derive
289     @flag_derive = flags["derive"] unless @flag_derive
290     @flag_derive
291   end
292   
293   def flag_thumbnail
294     @flag_thumbnail = flags["thumbnail"] unless @flag_thumbnail
295     @flag_thumbnail
296   end
297   
298   def flag_gif_convert
299     @flag_gif_convert = flags["gif_convert"] unless @flag_gif_convert
300     @flag_gif_convert
301   end
302   
303   def flag_reverse
304     @flag_reverse = flags["reverse"] unless @flag_reverse
305     @flag_reverse
306   end
307   
308   def flag_resize
309     @flag_resize = flags["resize"] unless @flag_resize
310     @flag_resize
311   end
312   
313   def flag_sync_vh
314     @flag_sync_vh = flags["sync_vh"] unless @flag_sync_vh
315     @flag_sync_vh
316   end
317   
318   def flag_overlap
319     @flag_overlap = flags["overlap"] unless @flag_overlap
320     @flag_overlap
321   end
322   
323 end