image_filter_dsl 0.0.3 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c683878731b0e51f247aff3462f53272a04c13e4c31fbbf1daa14e9ec606f235
4
- data.tar.gz: 606bc6208d106f867700b051bb73c917fc55d9985e8df0071e882a90e644f4db
3
+ metadata.gz: b3c5ec517d5379d54dcac83356f816f4e460ea651956600c4a406766483fff9e
4
+ data.tar.gz: a26273761002413d8f2944fce7c6d9da591a3b3124be8a640f9c375a029df739
5
5
  SHA512:
6
- metadata.gz: 88a3935892903034fdef3c0d1e1065d3886a5b6d636b6f46d693cb53fc2a7409cb151bda74ae15b83c39f7dd850a126d83c737da55204262a1592000f9294d55
7
- data.tar.gz: 43cbfb2c910938575dbc1a83835e454d0ff1f61000a8f1a8d93247a10fb0b6fa6e2f9288f86a49e4f338a59264e498f513d316957aa693f8b6e543f673cf69db
6
+ metadata.gz: 573236b32a4096fe6d8e57106cf9e4e79e9c4571583d0b9d1ceb710e8cb2dd227cadc51597bd5d8751fd55efd86ee4038207598833a38f3f41da8d8e3c9b5e47
7
+ data.tar.gz: f3703bc27fce75391023a2e8ab056f721471f3e522326f4201fa98600f62f70b75e3fb9b7a5850208c395883746e5d8ee5d4bd0b0e847f4b1e25b101bdeb2a21
data/README.md CHANGED
@@ -4,54 +4,202 @@ _An Image Filter DSL (duh)_
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/image_filter_dsl.svg)](https://badge.fury.io/rb/image_filter_dsl)
6
6
 
7
+ {file:CHANGELOG.md Change Log}
8
+
7
9
  ## Features
8
10
 
9
11
  - DSL with customizable input and output variables, and a set of basic instructions
10
12
  - IO with serialization so Kernels can be written to binary files and loaded from binary files
11
13
  - Image Processor that generates image file by applying Filter Kernel to every pixel of input image (supports multi-threading)
12
14
 
13
- ### Sample
15
+ ## DSL
14
16
 
15
- Define filter
17
+ ### Filter Block
18
+
19
+ Using `ImageFilterDsl::Dsl::Filter`
16
20
 
17
21
  ```ruby
18
- swizzle = Filter.define [:r,:g,:b], [:r,:g,:b] do
19
- copy [:g], :t # copy green to temp
20
- copy [:r], :g # copy red to green
21
- copy [:b], :r # copy blue to red
22
- copy [:t], :b # copy temp (original green) to blue
22
+ # - First array contains input variables
23
+ # x, y, r, g, b, a, :width and :hght are automatically
24
+ # populated by image filter process
25
+ # - Second array contains output vars; r,g,b,a and optionally
26
+ # x,y for images
27
+ filter = Filter.define [:x,:y,:r,:g,:b], [:r,:g,:b] do
28
+ # Instructions go here
29
+ # instruction [input(s)], output
30
+ add [:x,:r], :g
31
+
32
+ # output can be an existing symbol in out, or a custom one up to 5 letters
33
+ # long (longer will be trimmed if serialized to a binary file)
34
+
35
+ # input can be any declared input or custom variable
23
36
  end
24
37
  ```
25
38
 
39
+ ### Instructions
40
+
41
+ Basic Use:
42
+
43
+ ``instruction [argument1,argument2,...], :output_variable``
44
+
45
+ __Math__
46
+
47
+ - `add` add 2 or more input values, storing in output (<code>a+b</code>)
48
+
49
+ ```ruby
50
+ add [:r,5], :r # replace r with r + 5
51
+ ```
52
+
53
+ - `mult` add 2 or more inputs, storing in out (<code>a*b</code>)
54
+
55
+ ```ruby
56
+ mult [:r,2], :r # Replace r with r * 2
57
+ ```
58
+
59
+ - `div` divide 2 inputs
60
+
61
+ ```ruby
62
+ div [:r, 2], :g # Write r/2 to g
63
+ ```
64
+
65
+ - `mod` store modulo of two inputs in output
66
+
67
+ ```ruby
68
+ mod [2,4], :t # Write 2$4 (2) to t
69
+ ```
70
+
71
+ - `abs` store absolute value of input in output
72
+
73
+ ```ruby
74
+ abs [-5], :r # Writes abs(5) to r
75
+ ```
76
+
77
+ __Collection__
78
+
79
+ - `min` store smallest of inputs in output (accepts 2 or more values)
80
+
81
+ ```ruby
82
+ min [:r,255,:g], :s # Writes smallest of r, 255 and g to s
83
+ ```
84
+
85
+ - `max` store largest of inputs in output (accepts 2 or more values)
86
+
87
+ ```ruby
88
+ max [:r,0,:g], :s # Writes largest of r, 0 and g to s
89
+ ```
90
+
91
+ - `avg` store average of inputs in output (accepts 2 or more values)
92
+
93
+ ```ruby
94
+ avg [:r,:g,:b], :ca # Writes (r+g+b)/3 to ca
95
+ ```
96
+
97
+
98
+ __Logic/Conversion/Memory__
99
+
100
+ - `above` choose one of two values based on greater than comparison (2 or 4 values) `[n1,n1,true_val,false_val]` (If not specified, `true_val` is 1 and `false_val` is 0)
101
+
102
+ ```ruby
103
+ # if r > g, store 0 in g, else store g in g (keep g the same)
104
+ above [:r,:g,0,:g], :g
105
+ ```
106
+
107
+ - `below` choose one of two values based on less than comparison (2 or 4 values) `[n1,n1,true_val,false_val]` (If not specified, `true_val` is 1 and `false_val` is 0)
108
+
109
+ ```ruby
110
+ # if r < g, store 0 in r, else store r in r (keep r the same)
111
+ below [:r,:g,0,:r], :r
112
+ ```
113
+
114
+ - `between` choose one of two values based on whether value is between two others (3 or 5 values) `[min,max,value,true_val,false_val]` (If not specified, `true_val` is 1 and `false_val` is 0)
115
+
116
+ ```ruby
117
+ # Returns value since val > 1 && val < 3
118
+ below [1,3,2], :r
119
+ # Returns 1 since -1 < 1
120
+ below [1,-1,5], :r
121
+ ```
122
+
123
+ - `switch` choose one of two values based on condition value (1/1.0 = true, 0/0.0 = false) `[cond,true_val,false_val]`
124
+
125
+ ```ruby
126
+ # If c is true, store r in a, else store g in a
127
+ switch [:c,:r,:g], :a
128
+ ```
129
+
130
+ - `eq` if two input values are equal, store 1, else 0 (_2 values_) (`[val1,val2]`)
131
+ - `bnot` if input is 1 or 1.0, store 0, else 1 (_1 value_) (`[bool]`)
132
+ - `band` if _all_ input values are 1 or 1.0, store 1, else 0 (_1+ values_) (`[val1,val2,...]`)
133
+ - `bor` if _any_ input values are 1 or 1.0, store 1, else 0 (_1+ values_) (`[val1,val2,...]`)
134
+ - `copy` copy input directly to output (`[src]`)
135
+ - `ceil` nearest whole integer of input, rounded up (_1 value_) (`[val]`)
136
+ - `floor` nearest whole integer of input, rounded down (_1 value_) (`[val]`)
137
+ - `clamp` input clamped to be no less than min, no greater than max (`[min,max,val]`)
138
+ - `float` cast input to float (_1 value_) (`[val]`)
139
+ - `round` round first input value to second value decimals (`[value,decimal_count]`)
140
+ - `mix` Mix two values together with a ratio (0*a + (1-r)*b) (`[ratio,a,b]`)
141
+
142
+ ```ruby
143
+ # store (0.3*r) + (0.7*g) in b
144
+ mix [0.3,:r,:g], :b
145
+ ```
146
+
147
+ __Generators__
148
+
149
+ - `rand` random float between min and max (`[min,max]`)
150
+ - `sin` sine function on single value
151
+ - `cos` cosine function on single value
152
+ - `tan` tangent function on single value
153
+
154
+ ### Sample
155
+
156
+ Define filter
157
+
158
+ ```
159
+ swizzle = Filter.define [:r,:g,:b], [:r,:g,:b] do
160
+ copy [:g], :t # copy green to temp
161
+ copy [:r], :g # copy red to green
162
+ copy [:b], :r # copy blue to red
163
+ copy [:t], :b # copy temp (original green) to blue
164
+ end
165
+ ```
166
+
26
167
  Optionally write filter kernal to binary file on disk
27
168
 
28
169
  ```ruby
29
- ImageFilterDsl::Engine::IO.write("./swizzle.ifdkk", swizzle)
170
+ ImageFilterDsl::Engine::IO.write("./swizzle.ifdk", swizzle)
30
171
  ```
31
172
 
32
173
  Use filter kernal to process image
33
174
 
34
175
  ```ruby
35
- # From binary kernal file
36
- processor = ImageFilterDsl::Engine::ImageProcessor.new('./swizzle.ifdk')
37
- # OR from filter object
38
- processor = ImageFilterDsl::Engine::ImageProcessor.new(swizzle)
39
- # or use aliases in main module
40
- processor = ImageFilterDsl.image_processor(swizzle)
41
-
42
- # Process image and store output
43
- processor.process_image('./my_source.png', './my_output.png')
176
+ # From binary kernal file
177
+ processor = ImageFilterDsl::Engine::ImageProcessor.new('./swizzle.ifdk')
178
+ # OR from filter object
179
+ processor = ImageFilterDsl::Engine::ImageProcessor.new(swizzle)
180
+ # or use aliases in main module
181
+ processor = ImageFilterDsl.image_processor(swizzle)
182
+
183
+ # Process image and store output
184
+ processor.process_image('./my_source.png', './my_output.png')
44
185
  ```
45
186
 
46
- - See `./sample_filters/samples.rb`
47
- - See Also: [image_filter_dsl_samples](https://bitbucket.org/WadeH/image_filter_dsl_samples/src/master/) for samples
187
+ - See `./sample_filters/samples.rb` for sample filters
188
+ - See Also: [image_filter_dsl_samples](https://bitbucket.org/WadeH/image_filter_dsl_samples/src/master/) for more samples
48
189
 
49
190
  ## Gem
50
191
 
51
192
  Either
193
+
52
194
  - Build into a gem using included `gemspec` file; includes CLI functionality
53
195
  - Install using gem with `gem install image_filter_dsl`
54
196
 
197
+ ## CLI
198
+
199
+ Image Filter DSL can be made to process an image from a binary kernal using
200
+ its CLI tool, `image_filter_dsl`
201
+
202
+ - Usage: `image_filter_dsl <kernel_file> <image_in> <image_out>`
55
203
 
56
204
  ## License
57
205
 
@@ -2,9 +2,11 @@
2
2
 
3
3
  require 'image_filter_dsl'
4
4
 
5
- printf "Image Filter DSL > Process Image\n"
6
- if ARGV.length == 0
7
- printf "Usage: image_filter_dsl <kernel_file> <image_in> <image_out>\n"
8
- else
9
- ImageFilterDsl.cli_process_image(ARGV)
10
- end
5
+ # printf "Image Filter DSL > Process Image\n"
6
+ # if ARGV.length == 0
7
+ # printf "Usage: image_filter_dsl <kernel_file> <image_in> <image_out>\n"
8
+ # else
9
+ # ImageFilterDsl.cli_process_image(ARGV)
10
+ # end
11
+
12
+ ImageFilterDsl::Engine::CLI.run
@@ -5,7 +5,8 @@ require_relative './image_filter_dsl/binary/struct.rb'
5
5
  require_relative './image_filter_dsl/binary/serialize.rb'
6
6
  require_relative './image_filter_dsl/engine/io.rb'
7
7
  require_relative './image_filter_dsl/engine/image_processor.rb'
8
-
8
+ require_relative './image_filter_dsl/serialize.rb'
9
+ require_relative './image_filter_dsl/engine/cli.rb'
9
10
  ##
10
11
  # Image Filter DSL Library
11
12
  # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
@@ -22,7 +22,7 @@ module ImageFilterDsl
22
22
  # Constants used in header
23
23
  HEADER_VALUES = {
24
24
  header: "ifdKernel",
25
- version: 0.01
25
+ version: 0.02
26
26
  }
27
27
 
28
28
  ##
@@ -3,6 +3,8 @@
3
3
  # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
4
4
  # @author Wade H. <vdtdev.prod@gmail.com>
5
5
  module ImageFilterDsl
6
+ ##
7
+ # Module defining DSL
6
8
  module Dsl
7
9
  ##
8
10
  # Module defining filter kernel instruction logic
@@ -31,7 +33,17 @@ module ImageFilterDsl
31
33
  round: 0xd6,
32
34
  switch: 0xd7,
33
35
  eq: 0xd8,
34
- bnot: 0xd9
36
+ bnot: 0xd9,
37
+ mix: 0xda,
38
+ between: 0xdb,
39
+ clamp: 0xdc,
40
+ band: 0xdd,
41
+ bor: 0xde,
42
+ # generation
43
+ rand: 0xf0,
44
+ sin: 0xf1,
45
+ cos: 0xf2,
46
+ tan: 0xf3
35
47
  }
36
48
 
37
49
  ##
@@ -113,9 +125,11 @@ module ImageFilterDsl
113
125
 
114
126
  ##
115
127
  # Above instruction
116
- # @param [Array] i input values (a,b,trueVal,falseVal)
128
+ # @param [Array] i input values `(a,b,trueVal,falseVal)`
129
+ # `trueVal` defaults to `1`, `falseVal` defaults to `0`
117
130
  # @return [Integer|Float] output value
118
131
  def self.above(i)
132
+ i = [i,1,0].flatten if i.length == 2
119
133
  if(i[0]>i[1])
120
134
  if i.length < 3
121
135
  1
@@ -133,9 +147,11 @@ module ImageFilterDsl
133
147
 
134
148
  ##
135
149
  # Below instruction
136
- # @param [Array] i input values (a,b,trueVal,falseVal)
150
+ # @param [Array] i input values `(a,b,trueVal,falseVal)`
151
+ # `trueVal` defaults to `1`, `falseVal` defaults to `0`
137
152
  # @return [Integer|Float] output value
138
153
  def self.below(i)
154
+ i = [i,1,0].flatten if i.length == 2
139
155
  if(i[0]<i[1])
140
156
  if i.length < 3
141
157
  1
@@ -151,6 +167,28 @@ module ImageFilterDsl
151
167
  end
152
168
  end
153
169
 
170
+ ##
171
+ # Between instruction (check if value is between two others)
172
+ # @param [Array] i input values `[min, max, value, trueVal, falseVal]`
173
+ # `trueVal` defaults to `1`, `falseVal` defaults to `0`
174
+ # @return [Integer] 1 if true, 0 if false
175
+ def self.between(i)
176
+ i = [i,1,0].flatten if i.length == 3
177
+ a,b,v,t,f = i
178
+ r = (v>=a) && (v<=b)
179
+ (r)? t : f
180
+ end
181
+
182
+ ##
183
+ # Clamp value between a min and a max
184
+ # @param [Array] i input values `[min,max,val]`
185
+ # @return [Integer|Float] Value forced to be no greater than `max`
186
+ # and no less than `min`
187
+ def self.clamp(i)
188
+ a,b,v = i
189
+ [b,[a,v].max].min
190
+ end
191
+
154
192
  ##
155
193
  # Floor instruction
156
194
  # @param [Array] i input value (v)
@@ -186,7 +224,7 @@ module ImageFilterDsl
186
224
  ##
187
225
  # 'Switch' instruction (basically if)
188
226
  #
189
- # switch [condition (0/1/0.0/1.0), trueval, falseval]
227
+ # switch condition (0/1/0.0/1.0), trueval, falseval]
190
228
  # @param [Array] i input value (condition, true val, false val)
191
229
  # @return [Integer|Float] output value
192
230
  def self.switch(i)
@@ -220,6 +258,65 @@ module ImageFilterDsl
220
258
  1
221
259
  end
222
260
  end
261
+
262
+ ##
263
+ # Logical AND instruction
264
+ # @param [Array] i input values (ints or floats)
265
+ # @return [Integer] 1 if all values are `1` or `1.0`, else 0
266
+ def self.band(i)
267
+ (i.reduce(:+).to_i == i.length)? 1 : 0
268
+ end
269
+
270
+ ##
271
+ # Logical OR instruction
272
+ # @param [Array] i input values (ints or floats)
273
+ # @return [Integer] 1 if any values are `1` or `1.0`, else 0
274
+ def self.bor(i)
275
+ (i.reduce(:+).to_i > 0)? 1 : 0
276
+ end
277
+
278
+ ##
279
+ # Mix two values with a ratio
280
+ # @param [Array] i input values (ratio (0-1.0), a, b)
281
+ # @return [Float] output value of ((ratio*a) + ((1.0-ratio)*b))
282
+ def self.mix(i)
283
+ ratio, a, b = i
284
+ (ratio*a)+((1.0-ratio)*b)
285
+ end
286
+
287
+ ##
288
+ # Random number instruction
289
+ # @param [Array] i input values (min, max)
290
+ # @return [Float] Random number between min and max
291
+ def self.rand(i)
292
+ r=Random.new
293
+ min,max = i
294
+ (-min) + (r.rand * (max + min))
295
+ end
296
+
297
+ ##
298
+ # Sine function
299
+ # @param [Array] i input value to use sin on
300
+ # @return [Float] Sine of input value
301
+ def self.sin(i)
302
+ Math.sin(i[0])
303
+ end
304
+
305
+ ##
306
+ # Cosine function
307
+ # @param [Array] i input value to use cos on
308
+ # @return [Float] Cosine of input value
309
+ def self.cos(i)
310
+ Math.cos(i[0])
311
+ end
312
+
313
+ ##
314
+ # Tangent function
315
+ # @param [Array] i input value to use tan on
316
+ # @return [Float] Tangent of input value
317
+ def self.tan(i)
318
+ Math.tan(i[0])
319
+ end
223
320
  end
224
321
  end
225
322
  end
@@ -0,0 +1,83 @@
1
+ ##
2
+ # Image Filter DSL Library
3
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
4
+ # @author Wade H. <vdtdev.prod@gmail.com>
5
+ module ImageFilterDsl
6
+ module Engine
7
+ ##
8
+ # CLI Argument parser and handler module
9
+ module CLI
10
+ extend self
11
+
12
+ Options = Struct.new(:action, :filter, :input, :output)
13
+ RequiredArgs = {
14
+ process: [:filter, :input, :output],
15
+ compile: [:input, :output]
16
+ }
17
+
18
+ def parse(args)
19
+ opts = Options.new
20
+ args=args.map{|s|s.strip}
21
+
22
+ p = args[0]
23
+
24
+ if !p.nil? && p.downcase == '--process'
25
+ opts.action = :process
26
+ elsif !p.nil? && p.downcase == '--compile'
27
+ opts.action = :compile
28
+ end
29
+
30
+ unless opts.action.nil?
31
+ case opts.action
32
+ when :process
33
+ f,i,o = args[1..-1]
34
+ opts.filter = f
35
+ opts.input = i
36
+ opts.output = o
37
+ when :compile
38
+ s,k = args[1..-1]
39
+ opts.input = s
40
+ opts.output = k
41
+ end
42
+ end
43
+
44
+ return opts
45
+ end
46
+
47
+ def run()
48
+ options = parse(ARGV)
49
+ if options.action.nil?
50
+ show_usage
51
+ else
52
+ p options
53
+ if RequiredArgs[options.action].select{|o| options[o].nil?}.length == 0
54
+ do_action(options)
55
+ else
56
+ show_usage(options.action)
57
+ end
58
+ end
59
+ end
60
+
61
+ def show_usage(action=nil)
62
+ if !action.nil?
63
+ print "Invalid arguments for #{action.to_s}\n"
64
+ end
65
+ print [
66
+ "Usage: image_filter_dsl <action<",
67
+ "\t--process <kernel_file> <image in> <image out>\t\tProcess image with binary kernel",
68
+ "\t--compile <source_file> <output_kernel>\t\tCompile given ruby source to binary kernel"
69
+ ].join("\n")
70
+ print "\n"
71
+ end
72
+
73
+ def do_action(opts)
74
+ if opts.action == :process
75
+ ip = ImageFilterDsl.image_processor(opts.filter)
76
+ ip.process_image(opts.input, opts.output)
77
+ elsif opts.action == :compile
78
+ print "(Not yet implemented :)\n"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -13,6 +13,8 @@ module ImageFilterDsl
13
13
 
14
14
  attr_accessor :kernel, :config
15
15
 
16
+
17
+
16
18
  ##
17
19
  # Constructor
18
20
  # @param [Dsl::Kernel::FilterKernel|String] filter_kernel FilterKernel object or path to binary kernel file
@@ -121,7 +123,6 @@ module ImageFilterDsl
121
123
  b = clr.b(pixel)
122
124
  a = clr.a(pixel)
123
125
 
124
-
125
126
  inputs = Hash[*@kernel.inputs.map{|k|[k,0]}.flatten]
126
127
  inputs[:x] = x if inputs.keys.include?(:x)
127
128
  inputs[:y] = y if inputs.keys.include?(:y)
@@ -0,0 +1,69 @@
1
+ require_relative './serializers/common.rb'
2
+ require_relative './serializers/msg_pack.rb'
3
+ require_relative './serializers/json.rb'
4
+ require_relative './serializers/yaml.rb'
5
+ require_relative './serializers/intermediate.rb'
6
+ ##
7
+ # Image Filter DSL Library
8
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
9
+ # @author Wade H. <vdtdev.prod@gmail.com>
10
+ module ImageFilterDsl
11
+ ##
12
+ # Module providing access to kernel serialization and
13
+ # deserialization functionality. Actual serialization/deserialization
14
+ # logic defined in modules within `Serializers`
15
+ module Serialize
16
+ extend self
17
+ # include Serialize::Json
18
+ # include Serializers::Json
19
+
20
+ ##
21
+ # Intermediate serializer module
22
+ INTERMEDIATE = Serializers::Intermediate
23
+
24
+ ##
25
+ # Available serializers, mapping format symbol to
26
+ # module
27
+ SERIALIZERS = {
28
+ json: Serializers::Json,
29
+ msgpack: Serializers::MsgPack,
30
+ yaml: Serializers::Yaml
31
+ }
32
+ ##
33
+ # Available serializer symbols
34
+ FORMATS = SERIALIZERS.keys
35
+
36
+ ##
37
+ # Serialize kernel, optionally using intermediate step
38
+ # @param [ImageFilterDsl::Dsl::Kernel] kernel Kernel
39
+ # @param [Symbol] format Format to serialize to from FORMATS, or
40
+ # `nil` to convert to intermediate
41
+ # @return [Hash|String] serialized kernel
42
+ def from_kernel(kernel, format=nil)
43
+ i = INTERMEDIATE.from_kernel(kernel)
44
+ if format.nil?
45
+ return i
46
+ else
47
+ m = SERIALIZERS[format]
48
+ return m.send(:serialize, i)
49
+ end
50
+ end
51
+
52
+ ##
53
+ # Deserialize to kernel, optionally using intermediate step
54
+ # @param [Hash|String] data Serialized data
55
+ # @param [Symbol] format Format to convert from from FORMATS, or
56
+ # `nil` to convert from intermediate
57
+ # @return [Kernel] Kernal from deserialization
58
+ def to_kernel(data,format=nil)
59
+ if format.nil?
60
+ return INTERMEDIATE.to_kernel(data)
61
+ else
62
+ i = SERIALIZERS[format].send(:deserialize, data)
63
+ return INTERMEDIATE.to_kernel(i)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+
@@ -0,0 +1,57 @@
1
+ #
2
+ # Image Filter DSL Library
3
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
4
+ # @author Wade H. <vdtdev.prod@gmail.com>
5
+ module ImageFilterDsl
6
+ module Serializers
7
+ ##
8
+ # Common helper methods for serializers; Include in serializer modules
9
+ # with `include Common`
10
+ module Common
11
+ extend self
12
+ ##
13
+ # Normalize symbol/value, stripping out
14
+ # any colons and converting to symbol; Non strings
15
+ # are returned unaltered; if array, logic is applied to all items
16
+ # @param [String|Number|Symbol|Array] val
17
+ # @return [Symbol|Number|Array] Normalized value
18
+ def normalize_sym(val)
19
+ if val.is_a?(String)
20
+ val.gsub(':','').to_sym
21
+ elsif val.is_a?(Array)
22
+ val.map{|v|normalize_sym(v)}
23
+ else
24
+ val
25
+ end
26
+ end
27
+ ##
28
+ # 'Fix' hash, converting keys to symbols (if keys provided)
29
+ # and converting values/arrays of values so any strings are
30
+ # normalized and cast to symbols using {normalize_sym}
31
+ # @param [Hash] hash Hash to fix
32
+ # @param [Array] keys Optional array of key symbols to check for and
33
+ # convert string equivalents over to symbols if found
34
+ # @return [Hash] Fixed copy of input hash
35
+ def fix_hash(hash,keys=[])
36
+ h2=hash.dup
37
+ unless keys.length == 0
38
+ keys.each do |k|
39
+ if !h2.has_key?(k) && h2.has_key?(k.to_s)
40
+ h2[k] = h2[k.to_s]
41
+ h2.delete k.to_s
42
+ end
43
+ end
44
+ end
45
+ h2.keys.each do |k|
46
+ if h2[k].is_a?(Array)
47
+ h2[k] = h2[k].map{|v|normalize_sym(v)}
48
+ else
49
+ h2[k] = normalize_sym(h2[k])
50
+ end
51
+ end
52
+ return h2
53
+ end
54
+ end
55
+ end
56
+ end
57
+
@@ -0,0 +1,65 @@
1
+ ##
2
+ # Image Filter DSL Library
3
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
4
+ # @author Wade H. <vdtdev.prod@gmail.com>
5
+ module ImageFilterDsl
6
+ ##
7
+ # Kernel data serializers
8
+ module Serializers
9
+ ##
10
+ # Provides serialization/deserialization for Kernels
11
+ # to an intermediate format representing kernel as hash.
12
+ # Used by other serializers as intermediate between serializing
13
+ # from and deserializing to kernels
14
+ module Intermediate
15
+ include Common
16
+ extend self
17
+ ##
18
+ # Convert kernel to intermediate hash struct
19
+ # @param [ImageFilterDsl::Dsl::Kernel] kernel Source kernel
20
+ # @return [Hash] Intermediate hash version of kernel
21
+ def from_kernel(kernel)
22
+ data = {
23
+ inputs: kernel.inputs,
24
+ outputs: kernel.outputs
25
+ }
26
+ data[:instructions] = kernel.instructions.map do |i|
27
+ {op: i.op, in: i.inputs, out: i.out}
28
+ end
29
+ data
30
+ end
31
+
32
+ ##
33
+ # Convert intermediate kernel hash to kernel object
34
+ # @param [Hash] data Intermediate kernel data
35
+ # @return [ImageFilterDsl::Dsl::Kernel] Constructed kernel
36
+ def to_kernel(data)
37
+ ins = data[:instructions].map{|i| fix_instruction_symbols(i) }
38
+ filt = ImageFilterDsl::Dsl::Filter.define(data[:inputs],data[:outputs]) do
39
+ ins.each do |i|
40
+ send(i[:op], i[:in], i[:out])
41
+ end
42
+ end
43
+ return filt
44
+ end
45
+
46
+ private
47
+
48
+ def fix_instruction_symbols(ins_hash)
49
+ fix_hash(ins_hash,[:op,:in,:out])
50
+ # r_k=Proc.new {|k| (ins_hash.has_key?(k))? k : k.to_s}
51
+ # op_h = r_k.call(:op)
52
+ # in_h = r_k.call(:in)
53
+ # out_h = r_k.call(:out)
54
+ # norm_sym = Proc.new {|s| (s.is_a?(String))? s.gsub(':','').to_sym : s}
55
+ # {
56
+ # op: norm_sym.call(ins_hash[op_h]),
57
+ # in: ins_hash[in_h].map { |i|
58
+ # norm_sym.call(i)
59
+ # },
60
+ # out: norm_sym.call(ins_hash[out_h])
61
+ # }
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,43 @@
1
+ require 'json'
2
+ ##
3
+ # Image Filter DSL Library
4
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
5
+ # @author Wade H. <vdtdev.prod@gmail.com>
6
+ module ImageFilterDsl
7
+ module Serializers
8
+ ##
9
+ # Provides serialization/deserialization to/from JSON using
10
+ # intermediate serializer
11
+ module Json
12
+ include Common
13
+ extend self
14
+ ##
15
+ # Serialize kernel to JSON string
16
+ # @param [Hash] kernel Kernel in intermediate format
17
+ # @return [String] JSON serialized version of kernel
18
+ def serialize(kernel)
19
+ {
20
+ header: ImageFilterDsl::Binary::Struct::HEADER_VALUES,
21
+ inputs: kernel[:inputs],
22
+ outputs: kernel[:outputs],
23
+ instructions: kernel[:instructions]
24
+ }.to_json
25
+ end
26
+ ##
27
+ # Deserialize JSON kernel to intermediate format
28
+ # @param [String] data JSON kernel data
29
+ # @return [Hash] Intermediate format of kernel data
30
+ def deserialize(data)
31
+ data = JSON.load(data)
32
+ data = fix_hash(data,[:inputs,:outputs,:instructions])
33
+ data[:instructions] = data[:instructions].map {|i| fix_hash(i,[:op,:in,:out])}
34
+
35
+ {
36
+ inputs: data[:inputs],
37
+ outputs: data[:outputs],
38
+ instructions: data[:instructions]
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require 'msgpack'
2
+ ##
3
+ # Image Filter DSL Library
4
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
5
+ # @author Wade H. <vdtdev.prod@gmail.com>
6
+ module ImageFilterDsl
7
+ module Serializers
8
+ ##
9
+ # Provides serialization/deserialization to/from MessagePack strings
10
+ # using intermediate serializer
11
+ module MsgPack
12
+ include Common
13
+ extend self
14
+ ##
15
+ # 'Header' added to start of array packed with MsgPack
16
+ HEADER = ['mp',ImageFilterDsl::Binary::Struct::HEADER_VALUES.values].flatten
17
+ ##
18
+ # Serialize kernel to MessagePack string
19
+ # @param [Hash] kernel Kernel in intermediate format
20
+ # @return [String] MessagePack serialized version of kernel
21
+ def serialize(kernel)
22
+ [
23
+ HEADER,
24
+ kernel[:inputs],
25
+ kernel[:outputs],
26
+ kernel[:instructions].map do |i|
27
+ [i[:op],i[:in],i[:out]]
28
+ end
29
+ ].to_msgpack
30
+ end
31
+ ##
32
+ # Deserialize MessagePack kernel to intermediate format
33
+ # @param [String] data MessagePack kernel data
34
+ # @return [Hash] Intermediate format of kernel data
35
+ def deserialize(data)
36
+ data = MessagePack.unpack(data)
37
+ head,inps,outs,ins=data
38
+ d = {
39
+ inputs: normalize_sym(inps),
40
+ outputs: normalize_sym(outs),
41
+ instructions: ins.map do |i|
42
+ op,iin,iout=i
43
+ fix_hash({op: op, in: iin, out: iout})
44
+ end
45
+ }
46
+
47
+ return d
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,42 @@
1
+ require 'yaml'
2
+ ##
3
+ # Image Filter DSL Library
4
+ # (c) 2018-2020 VDTDEV/Wade H. ~ MIT License
5
+ # @author Wade H. <vdtdev.prod@gmail.com>
6
+ module ImageFilterDsl
7
+ module Serializers
8
+ ##
9
+ # Provides serialization/deserialization to/from YAML using
10
+ # intermediate serializer
11
+ module Yaml
12
+ include Common
13
+ extend self
14
+ ##
15
+ # Serialize kernel to YAML string
16
+ # @param [Hash] kernel Kernel in intermediate format
17
+ # @return [String] YAML serialized version of kernel
18
+ def serialize(kernel)
19
+ {
20
+ header: ImageFilterDsl::Binary::Struct::HEADER_VALUES,
21
+ inputs: kernel[:inputs],
22
+ outputs: kernel[:outputs],
23
+ instructions: kernel[:instructions]
24
+ }.to_yaml
25
+ end
26
+ ##
27
+ # Deserialize YAML kernel to intermediate format
28
+ # @param [String] data YAML kernel data
29
+ # @return [Hash] Intermediate format of kernel data
30
+ def deserialize(data)
31
+ data = YAML.load(data)
32
+ data = fix_hash(data,[:inputs,:outputs,:instructions])
33
+ data[:instructions] = data[:instructions].map {|i| fix_hash(i,[:op,:in,:out])}
34
+ {
35
+ inputs: data[:inputs],
36
+ outputs: data[:outputs],
37
+ instructions: data[:instructions]
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_filter_dsl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wade H.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-02 00:00:00.000000000 Z
11
+ date: 2020-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chunky_png
@@ -89,13 +89,21 @@ files:
89
89
  - lib/image_filter_dsl/dsl/filter.rb
90
90
  - lib/image_filter_dsl/dsl/filter_instructions.rb
91
91
  - lib/image_filter_dsl/dsl/kernel.rb
92
+ - lib/image_filter_dsl/engine/cli.rb
92
93
  - lib/image_filter_dsl/engine/image_processor.rb
93
94
  - lib/image_filter_dsl/engine/io.rb
95
+ - lib/image_filter_dsl/serialize.rb
96
+ - lib/image_filter_dsl/serializers/common.rb
97
+ - lib/image_filter_dsl/serializers/intermediate.rb
98
+ - lib/image_filter_dsl/serializers/json.rb
99
+ - lib/image_filter_dsl/serializers/msg_pack.rb
100
+ - lib/image_filter_dsl/serializers/yaml.rb
94
101
  homepage: https://bitbucket.org/WadeH/image_filter_dsl
95
102
  licenses:
96
103
  - MIT
97
104
  metadata:
98
105
  source_code_uri: https://bitbucket.org/WadeH/image_filter_dsl
106
+ documentation_uri: https://rubydoc.info/gems/image_filter_dsl/0.1.1
99
107
  post_install_message:
100
108
  rdoc_options: []
101
109
  require_paths:
@@ -111,8 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
119
  - !ruby/object:Gem::Version
112
120
  version: '0'
113
121
  requirements: []
114
- rubyforge_project:
115
- rubygems_version: 2.7.8
122
+ rubygems_version: 3.0.0
116
123
  signing_key:
117
124
  specification_version: 4
118
125
  summary: Image Filter DSL