OSDN Git Service

8bef0445167e9fea6a2438f9c01b503f1c5adf8f
[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 mime_type
65     "image/#{self.dext}"
66   end
67   
68   def url subdir = nil
69     '/resource_pictures/' + (subdir.to_s.empty? ? '' : subdir.to_s + '/' ) + filename
70   end
71   
72   def thumbnail(rimg)
73     tw, th = ResourcePicture.fix_size_both(64, 64, rimg.columns, rimg.rows)
74     ResourcePicture.resize(rimg.to_blob, tw, th).to_blob
75   end
76   
77   def copy_data(op)
78     attr = {:width => op.width, :height => op.height, :ext => op.ext, :filesize => op.filesize, 
79       :original_picture_id => op.id, :artist_id => op.artist_id
80     }
81     self.attributes = attr
82   end
83   
84   def data_to_mgk picture_data
85     begin
86       mgk = Magick::Image.from_blob(picture_data).shift
87     rescue 
88       self.errors.add :base, 'magick failed'
89       return false
90     end
91     mgk
92   end
93   
94   def op_mgk
95     d = self.original_picture.restore
96     return false unless d
97     self.data_to_mgk d
98   end
99   
100   def new_picture mgk
101     pc = Picture.new
102     pc.copy_data self
103     pc.store mgk
104     pc
105   end
106   
107   
108   def to_gif?
109     self.dext == 'png' and self.flag_gif_convert >= 0
110   end
111   
112   def self.png_to_gif(data)
113     res = nil
114     begin
115       mgk = Magick::Image.from_blob(data).shift
116       mgk.format = 'gif'
117       res = mgk
118     rescue
119       res = false
120     end
121     res
122   end
123   
124   def store
125     res = false
126     self.copy_data self.original_picture
127     mgk = self.op_mgk
128     return false unless mgk
129     OriginalPicture.transaction do
130       pc = self.new_picture mgk
131       if res = pc.valid?
132         self.picture_id = pc.id
133         if res = self.save
134           res = self.store_picture_with_gif(mgk)
135         end
136       else
137         self.errors.add :base, 'picture does not create'
138       end
139       raise ActiveRecord::Rollback unless res
140     end
141     res
142   end
143   
144   def store_picture_with_gif(mgk)
145     if res = self.store_picture(mgk)
146       if self.to_gif?
147         if gifmgk = ResourcePicture.png_to_gif(mgk.to_blob)
148           res = self.store_picture(gifmgk)
149         else
150           self.errors.add :base, 'picture data can not conv to gif'
151           res = false
152         end
153       end
154     else
155       self.errors.add :base, 'resource picture io does not work'
156     end
157     res
158   end
159   
160   def store_picture(mgk)
161     res = false
162     tdata = self.flag_thumbnail >= 0 ? thumbnail(mgk) : mgk.to_blob
163     fdata = mgk.to_blob
164     return false unless PictureIO.resource_picture_io.put(tdata, self.filename)
165     PictureIO.resource_picture_io.put(fdata, self.filename, 'full')
166   end
167   
168   def restore(subdir = nil)
169     PictureIO.resource_picture_io.get self.filename, subdir
170   end
171   
172   def self.default_page_size
173     25
174   end
175   
176   def self.max_page_size
177     100
178   end
179   
180   def self.page prm = nil
181     page = prm.to_i
182     page = 1 if page < 1
183     page
184   end
185   
186   def self.page_size prm = self.default_page_size
187     page_size = prm.to_i
188     page_size = self.max_page_size if page_size > self.max_page_size
189     page_size = self.default_page_size if page_size < 1
190     page_size
191   end
192   
193   def self.offset cnt, prm = nil
194     offset = prm.to_i
195     offset = cnt - 1 if offset >= cnt
196     offset = cnt - offset.abs if offset < 0
197     offset = 0 if offset < 0
198     offset
199   end
200   
201   def self.list opt = {}, page = 1, page_size = self.default_page_size
202     opt.merge!(self.list_opt) unless opt[:include]
203     opt.merge!({:order => 'updated_at desc', :limit => page_size, :offset => (page -1) * page_size})
204     ResourcePicture.find(:all, opt)
205   end
206   
207   def self.list_opt
208     {:include => [:license, :artist]}
209   end
210   
211   def self.list_json_opt
212     {:include => [:license, :artist]}
213   end
214   
215   def self.show rid, opt = {}
216     r = ResourcePicture.find(rid, :include => self.show_include_opt(opt))
217 #    raise ActiveRecord::Forbidden unless c.visible?(au)
218     r
219   end
220   
221   def self.show_include_opt opt = {}
222     res = [:license, :artist]
223     res.push(opt[:include]) if opt[:include]
224     res
225   end
226   
227   def self.show_json_include_opt
228     {:include => [:license, :artist]}
229   end
230   
231   def self.visible_count
232     ResourcePicture.count
233   end
234   
235   def credit_template
236     "#{self.classname.tableize}/credit"
237   end
238   
239   def credit_data
240     begin
241       @credit_data = JSON.parse(self.credit) unless @credit_data
242     rescue 
243     end
244     @credit_data
245   end
246   
247   def flags
248     begin
249       @flags = JSON.parse(self.settings) unless @flags
250     rescue 
251     end
252     @flags
253   end
254   
255   def flags=(s)
256     @flags = s
257   end
258   
259   def flag_open
260     @flag_open = flags["open"] unless @flag_open
261     @flag_open
262   end
263   
264   def flag_commercial
265     @flag_commercial = flags["commercial"] unless @flag_commercial
266     @flag_commercial
267   end
268   
269   def flag_official
270     @flag_official = flags["official"] unless @flag_official
271     @flag_official
272   end
273   
274   def flag_attribution
275     @flag_attribution = flags["attribution"] unless @flag_attribution
276     @flag_attribution
277   end
278   
279   def flag_derive
280     @flag_derive = flags["derive"] unless @flag_derive
281     @flag_derive
282   end
283   
284   def flag_thumbnail
285     @flag_thumbnail = flags["thumbnail"] unless @flag_thumbnail
286     @flag_thumbnail
287   end
288   
289   def flag_gif_convert
290     @flag_gif_convert = flags["gif_convert"] unless @flag_gif_convert
291     @flag_gif_convert
292   end
293   
294   def flag_reverse
295     @flag_reverse = flags["reverse"] unless @flag_reverse
296     @flag_reverse
297   end
298   
299   def flag_resize
300     @flag_resize = flags["resize"] unless @flag_resize
301     @flag_resize
302   end
303   
304   def flag_sync_vh
305     @flag_sync_vh = flags["sync_vh"] unless @flag_sync_vh
306     @flag_sync_vh
307   end
308   
309   def flag_overlap
310     @flag_overlap = flags["overlap"] unless @flag_overlap
311     @flag_overlap
312   end
313   
314 end