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 +4 -4
- data/README.md +167 -19
- data/bin/image_filter_dsl +8 -6
- data/lib/image_filter_dsl.rb +2 -1
- data/lib/image_filter_dsl/binary/struct.rb +1 -1
- data/lib/image_filter_dsl/dsl/filter_instructions.rb +101 -4
- data/lib/image_filter_dsl/engine/cli.rb +83 -0
- data/lib/image_filter_dsl/engine/image_processor.rb +2 -1
- data/lib/image_filter_dsl/serialize.rb +69 -0
- data/lib/image_filter_dsl/serializers/common.rb +57 -0
- data/lib/image_filter_dsl/serializers/intermediate.rb +65 -0
- data/lib/image_filter_dsl/serializers/json.rb +43 -0
- data/lib/image_filter_dsl/serializers/msg_pack.rb +51 -0
- data/lib/image_filter_dsl/serializers/yaml.rb +42 -0
- metadata +11 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3c5ec517d5379d54dcac83356f816f4e460ea651956600c4a406766483fff9e
|
4
|
+
data.tar.gz: a26273761002413d8f2944fce7c6d9da591a3b3124be8a640f9c375a029df739
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
15
|
+
## DSL
|
14
16
|
|
15
|
-
|
17
|
+
### Filter Block
|
18
|
+
|
19
|
+
Using `ImageFilterDsl::Dsl::Filter`
|
16
20
|
|
17
21
|
```ruby
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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.
|
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
|
|
data/bin/image_filter_dsl
CHANGED
@@ -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
|
-
|
8
|
-
else
|
9
|
-
|
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
|
data/lib/image_filter_dsl.rb
CHANGED
@@ -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
|
@@ -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
|
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.
|
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-
|
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
|
-
|
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
|