OSDN Git Service

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