2020class ActiveStorage ::Variation
2121 attr_reader :transformations
2222
23+ class UnsupportedImageProcessingMethod < StandardError ; end
24+ class UnsupportedImageProcessingArgument < StandardError ; end
25+
26+ SUPPORTED_IMAGE_PROCESSING_METHODS = [
27+ "adaptive_blur" ,
28+ "adaptive_resize" ,
29+ "adaptive_sharpen" ,
30+ "adjoin" ,
31+ "affine" ,
32+ "alpha" ,
33+ "annotate" ,
34+ "antialias" ,
35+ "append" ,
36+ "apply" ,
37+ "attenuate" ,
38+ "authenticate" ,
39+ "auto_gamma" ,
40+ "auto_level" ,
41+ "auto_orient" ,
42+ "auto_threshold" ,
43+ "backdrop" ,
44+ "background" ,
45+ "bench" ,
46+ "bias" ,
47+ "bilateral_blur" ,
48+ "black_point_compensation" ,
49+ "black_threshold" ,
50+ "blend" ,
51+ "blue_primary" ,
52+ "blue_shift" ,
53+ "blur" ,
54+ "border" ,
55+ "bordercolor" ,
56+ "borderwidth" ,
57+ "brightness_contrast" ,
58+ "cache" ,
59+ "canny" ,
60+ "caption" ,
61+ "channel" ,
62+ "channel_fx" ,
63+ "charcoal" ,
64+ "chop" ,
65+ "clahe" ,
66+ "clamp" ,
67+ "clip" ,
68+ "clip_path" ,
69+ "clone" ,
70+ "clut" ,
71+ "coalesce" ,
72+ "colorize" ,
73+ "colormap" ,
74+ "color_matrix" ,
75+ "colors" ,
76+ "colorspace" ,
77+ "colourspace" ,
78+ "color_threshold" ,
79+ "combine" ,
80+ "combine_options" ,
81+ "comment" ,
82+ "compare" ,
83+ "complex" ,
84+ "compose" ,
85+ "composite" ,
86+ "compress" ,
87+ "connected_components" ,
88+ "contrast" ,
89+ "contrast_stretch" ,
90+ "convert" ,
91+ "convolve" ,
92+ "copy" ,
93+ "crop" ,
94+ "cycle" ,
95+ "deconstruct" ,
96+ "define" ,
97+ "delay" ,
98+ "delete" ,
99+ "density" ,
100+ "depth" ,
101+ "descend" ,
102+ "deskew" ,
103+ "despeckle" ,
104+ "direction" ,
105+ "displace" ,
106+ "dispose" ,
107+ "dissimilarity_threshold" ,
108+ "dissolve" ,
109+ "distort" ,
110+ "dither" ,
111+ "draw" ,
112+ "duplicate" ,
113+ "edge" ,
114+ "emboss" ,
115+ "encoding" ,
116+ "endian" ,
117+ "enhance" ,
118+ "equalize" ,
119+ "evaluate" ,
120+ "evaluate_sequence" ,
121+ "extent" ,
122+ "extract" ,
123+ "family" ,
124+ "features" ,
125+ "fft" ,
126+ "fill" ,
127+ "filter" ,
128+ "flatten" ,
129+ "flip" ,
130+ "floodfill" ,
131+ "flop" ,
132+ "font" ,
133+ "foreground" ,
134+ "format" ,
135+ "frame" ,
136+ "function" ,
137+ "fuzz" ,
138+ "fx" ,
139+ "gamma" ,
140+ "gaussian_blur" ,
141+ "geometry" ,
142+ "gravity" ,
143+ "grayscale" ,
144+ "green_primary" ,
145+ "hald_clut" ,
146+ "highlight_color" ,
147+ "hough_lines" ,
148+ "iconGeometry" ,
149+ "iconic" ,
150+ "identify" ,
151+ "ift" ,
152+ "illuminant" ,
153+ "immutable" ,
154+ "implode" ,
155+ "insert" ,
156+ "intensity" ,
157+ "intent" ,
158+ "interlace" ,
159+ "interline_spacing" ,
160+ "interpolate" ,
161+ "interpolative_resize" ,
162+ "interword_spacing" ,
163+ "kerning" ,
164+ "kmeans" ,
165+ "kuwahara" ,
166+ "label" ,
167+ "lat" ,
168+ "layers" ,
169+ "level" ,
170+ "level_colors" ,
171+ "limit" ,
172+ "limits" ,
173+ "linear_stretch" ,
174+ "linewidth" ,
175+ "liquid_rescale" ,
176+ "list" ,
177+ "loader" ,
178+ "log" ,
179+ "loop" ,
180+ "lowlight_color" ,
181+ "magnify" ,
182+ "map" ,
183+ "mattecolor" ,
184+ "median" ,
185+ "mean_shift" ,
186+ "metric" ,
187+ "mode" ,
188+ "modulate" ,
189+ "moments" ,
190+ "monitor" ,
191+ "monochrome" ,
192+ "morph" ,
193+ "morphology" ,
194+ "mosaic" ,
195+ "motion_blur" ,
196+ "name" ,
197+ "negate" ,
198+ "noise" ,
199+ "normalize" ,
200+ "opaque" ,
201+ "ordered_dither" ,
202+ "orient" ,
203+ "page" ,
204+ "paint" ,
205+ "pause" ,
206+ "perceptible" ,
207+ "ping" ,
208+ "pointsize" ,
209+ "polaroid" ,
210+ "poly" ,
211+ "posterize" ,
212+ "precision" ,
213+ "preview" ,
214+ "process" ,
215+ "quality" ,
216+ "quantize" ,
217+ "quiet" ,
218+ "radial_blur" ,
219+ "raise" ,
220+ "random_threshold" ,
221+ "range_threshold" ,
222+ "red_primary" ,
223+ "regard_warnings" ,
224+ "region" ,
225+ "remote" ,
226+ "render" ,
227+ "repage" ,
228+ "resample" ,
229+ "resize" ,
230+ "resize_to_fill" ,
231+ "resize_to_fit" ,
232+ "resize_to_limit" ,
233+ "resize_and_pad" ,
234+ "respect_parentheses" ,
235+ "reverse" ,
236+ "roll" ,
237+ "rotate" ,
238+ "sample" ,
239+ "sampling_factor" ,
240+ "saver" ,
241+ "scale" ,
242+ "scene" ,
243+ "screen" ,
244+ "seed" ,
245+ "segment" ,
246+ "selective_blur" ,
247+ "separate" ,
248+ "sepia_tone" ,
249+ "shade" ,
250+ "shadow" ,
251+ "shared_memory" ,
252+ "sharpen" ,
253+ "shave" ,
254+ "shear" ,
255+ "sigmoidal_contrast" ,
256+ "silent" ,
257+ "similarity_threshold" ,
258+ "size" ,
259+ "sketch" ,
260+ "smush" ,
261+ "snaps" ,
262+ "solarize" ,
263+ "sort_pixels" ,
264+ "sparse_color" ,
265+ "splice" ,
266+ "spread" ,
267+ "statistic" ,
268+ "stegano" ,
269+ "stereo" ,
270+ "storage_type" ,
271+ "stretch" ,
272+ "strip" ,
273+ "stroke" ,
274+ "strokewidth" ,
275+ "style" ,
276+ "subimage_search" ,
277+ "swap" ,
278+ "swirl" ,
279+ "synchronize" ,
280+ "taint" ,
281+ "text_font" ,
282+ "threshold" ,
283+ "thumbnail" ,
284+ "tile_offset" ,
285+ "tint" ,
286+ "title" ,
287+ "transform" ,
288+ "transparent" ,
289+ "transparent_color" ,
290+ "transpose" ,
291+ "transverse" ,
292+ "treedepth" ,
293+ "trim" ,
294+ "type" ,
295+ "undercolor" ,
296+ "unique_colors" ,
297+ "units" ,
298+ "unsharp" ,
299+ "update" ,
300+ "valid_image" ,
301+ "view" ,
302+ "vignette" ,
303+ "virtual_pixel" ,
304+ "visual" ,
305+ "watermark" ,
306+ "wave" ,
307+ "wavelet_denoise" ,
308+ "weight" ,
309+ "white_balance" ,
310+ "white_point" ,
311+ "white_threshold" ,
312+ "window" ,
313+ "window_group" ,
314+ ] . concat ( ActiveStorage . supported_image_processing_methods )
315+
316+ UNSUPPORTED_IMAGE_PROCESSING_ARGUMENTS = ActiveStorage . unsupported_image_processing_arguments
317+
23318 class << self
24319 # Returns a Variation instance based on the given variator. If the variator is a Variation, it is
25320 # returned unmodified. If it is a String, it is passed to ActiveStorage::Variation.decode. Otherwise,
@@ -56,12 +351,15 @@ def initialize(transformations)
56351 def transform ( image )
57352 ActiveSupport ::Notifications . instrument ( "transform.active_storage" ) do
58353 transformations . each do |name , argument_or_subtransformations |
354+ validate_transformation ( name , argument_or_subtransformations )
59355 image . mogrify do |command |
60356 if name . to_s == "combine_options"
61357 argument_or_subtransformations . each do |subtransformation_name , subtransformation_argument |
358+ validate_transformation ( subtransformation_name , subtransformation_argument )
62359 pass_transform_argument ( command , subtransformation_name , subtransformation_argument )
63360 end
64361 else
362+ validate_transformation ( name , argument_or_subtransformations )
65363 pass_transform_argument ( command , name , argument_or_subtransformations )
66364 end
67365 end
@@ -86,4 +384,58 @@ def pass_transform_argument(command, method, argument)
86384 def eligible_argument? ( argument )
87385 argument . present? && argument != true
88386 end
387+
388+ def validate_transformation ( name , argument )
389+ method_name = name . to_s . gsub ( "-" , "_" )
390+
391+ unless SUPPORTED_IMAGE_PROCESSING_METHODS . any? { |method | method_name == method }
392+ raise UnsupportedImageProcessingMethod , <<~ERROR . squish
393+ One or more of the provided transformation methods is not supported.
394+ ERROR
395+ end
396+
397+ if argument . present?
398+ if argument . is_a? ( String ) || argument . is_a? ( Symbol )
399+ validate_arg_string ( argument )
400+ elsif argument . is_a? ( Array )
401+ validate_arg_array ( argument )
402+ elsif argument . is_a? ( Hash )
403+ validate_arg_hash ( argument )
404+ end
405+ end
406+ end
407+
408+ def validate_arg_string ( argument )
409+ if UNSUPPORTED_IMAGE_PROCESSING_ARGUMENTS . any? { |bad_arg | argument . to_s . downcase . include? ( bad_arg ) } ; raise UnsupportedImageProcessingArgument end
410+ end
411+
412+ def validate_arg_array ( argument )
413+ argument . each do |arg |
414+ if arg . is_a? ( Integer ) || arg . is_a? ( Float )
415+ next
416+ elsif arg . is_a? ( String ) || arg . is_a? ( Symbol )
417+ validate_arg_string ( arg )
418+ elsif arg . is_a? ( Array )
419+ validate_arg_array ( arg )
420+ elsif arg . is_a? ( Hash )
421+ validate_arg_hash ( arg )
422+ end
423+ end
424+ end
425+
426+ def validate_arg_hash ( argument )
427+ argument . each do |key , value |
428+ validate_arg_string ( key )
429+
430+ if value . is_a? ( Integer ) || value . is_a? ( Float )
431+ next
432+ elsif value . is_a? ( String ) || value . is_a? ( Symbol )
433+ validate_arg_string ( value )
434+ elsif value . is_a? ( Array )
435+ validate_arg_array ( value )
436+ elsif value . is_a? ( Hash )
437+ validate_arg_hash ( value )
438+ end
439+ end
440+ end
89441end
0 commit comments