Subversion Repositories filter_foundry

Rev

Rev 295 | Rev 304 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
141 dmarschall 1
 
294 daniel-mar 2
 
221 daniel-mar 3
Implementation detail differences
4
=================================
141 dmarschall 5
 
144 dmarschall 6
FilterFoundry tries to be as compatible with Filter Factory as possible.
294 daniel-mar 7
However, there are some differences which are explained in this documentation.
141 dmarschall 8
 
294 daniel-mar 9
Various implementations
10
-----------------------
141 dmarschall 11
 
294 daniel-mar 12
In the source-code file funcs.c, some functions are implemented twice:
13
One instance is the default implementation (older Filter Foundry versions used),
14
and one instance is a 100% replica of the Filter Factory code, obtained
15
from the "OPER" resource.
16
(More information at https://misc.daniel-marschall.de/projects/filter_factory/res_oper.html )
297 daniel-mar 17
If required, the compiler-definitions `use_filterfactory_implementation_*`
294 daniel-mar 18
can be set or unset to select the implementation.
19
 
295 daniel-mar 20
In Filter Foundry 1.7.0.8, following functions have been updated to the Filter Factory replica:
297 daniel-mar 21
- `rnd(x)`
22
- `cos(x)`
23
- `sin(x)`
24
- `tan(x)`
25
- `r2x(d,m)`
26
- `r2y(d,m)`
27
- `rad(d,m,z)`
28
- `c2d(x,y)`
29
- `c2m(x,y)`
30
- `sqr(x)`
31
- `d`
32
- `m`
33
- `M`
294 daniel-mar 34
 
35
 
36
sqr(x)
37
------
38
 
39
Filter Factory:
40
 
41
	sqr(x)=x for x < 0
295 daniel-mar 42
 
43
	Can be tested with following expression:
44
	sqr(-20)+21 == 1
294 daniel-mar 45
 
46
Filter Foundry (prior to 1.7.0.8):
47
 
48
	sqr(x)=0 for x < 0
49
 
297 daniel-mar 50
 
158 dmarschall 51
i, u, v (Testcase iuv.afs)
141 dmarschall 52
-------
53
 
54
Filter Foundry <1.7 uses the same formulas as in Filter Factory:
55
 
221 daniel-mar 56
    i=((76*r)+(150*g)+(29*b))/256            // Output range is 0..254
57
    u=((-19*r)+(-37*g)+(56*b))/256           // Output range is -55..55
58
    v=((78*r)+(-65*g)+(-13*b))/256           // Output range is -77..77
141 dmarschall 59
 
60
Filter Foundry 1.7 uses more accurate formulas:
61
 
221 daniel-mar 62
    i=(299*r+587*g+114*b)/1000               // Output range is 0..255
63
    u=(-147407*r-289391*g+436798*b)/2000000  // Output range is -55..55
64
    v=614777*r-514799*g-99978*b)/2000000     // Output range is -78..78
141 dmarschall 65
 
192 daniel-mar 66
Both formulas follow the same YUV standard but have different accuracy.
141 dmarschall 67
 
68
 
69
get(i) (Testcase getput.afs)
70
------
71
 
72
Filter Foundry:
73
 
221 daniel-mar 74
    get(x)=0 if x>255 or x<0
75
 
141 dmarschall 76
Filter Factory:
77
 
221 daniel-mar 78
    get(x)=x if x>255 or x<0
141 dmarschall 79
 
221 daniel-mar 80
Note: The result "x" was most likely not intended but a result of an undefined behavior
81
 
82
 
141 dmarschall 83
r, g, b at empty canvas (Testcase emptycanvas.afs)
84
-----------------------
85
 
221 daniel-mar 86
In Filter Factory, an empty (transparent) canvas of a new file is initialized as `r=g=b=0`
141 dmarschall 87
 
221 daniel-mar 88
Filter Foundry initializes it as `r=g=b=255`
141 dmarschall 89
 
90
 
294 daniel-mar 91
rnd(a,b) (Testcases rnd*)
289 daniel-mar 92
--------
93
 
94
Filter Factory uses Donald E. Knuth's subtractive random number generator algorithm,
95
which has been published in "The Art of Computer Programming, volume 2: Seminumerical Algorithms".
96
Addison-Wesley, Reading, MA, second edition, 1981.
97
 
98
Beginning with Filter Foundry 1.7.0.8, the same PRNG was implemented,
99
so that the output of rnd(a,b) is exactly the same now.
100
 
101
 
294 daniel-mar 102
rst(i) (Testcases rnd*.afs and rst_*.afs)
103
------
141 dmarschall 104
 
289 daniel-mar 105
Filter Factory contains an undocumented function that sets the seed for the random number generator.
141 dmarschall 106
 
289 daniel-mar 107
Filter Factory and FilterFoundry beginning with 1.7.0.8 accept a seed between 0 and 32767, inclusively.
108
If the argument is not within this range, the operation "and 0x7FFF" will be applied to it
109
to extract the low 15 bits.
141 dmarschall 110
 
289 daniel-mar 111
There are many differences in the implementation between FilterFactory and FilterFoundry in regards rst(i):
141 dmarschall 112
 
289 daniel-mar 113
**Filter Factory:**
143 dmarschall 114
 
289 daniel-mar 115
If rst(i) is called in Filter Factory, an internal Seed-Variable is set.
116
It does NOT influence any calls of rnd(a,b), because a lookup-table needs to be built first.
117
The building of the lookup-table is probably done before the processing of the first pixel (x,y,z=0).
118
It is suspected that the call of rst(i) will take effect on the next calculation.
119
Due to a bug (or feature?), the random state is not reset to its initial state (0) before the
120
filter is applied. The preview image processing will modify the random state, and once the filter
121
is actually applied (pressing "OK"), the random state that was set in the preview picture, will be used.
122
This could be considered as a bug, but it is probably required, otherwise the call of rst(i)
123
(inside the preview calculation) won't affect the rnd(a,b) in the real run.
124
However, in a standalone filter without dialog/preview, there is no preview that could set
125
the internal seed, so the rnd(a,b) functions will always work using the default seed 0,
126
and only the subsequent calls will use the rst(i) of the previous call.
221 daniel-mar 127
 
289 daniel-mar 128
**Filter Foundry:**
143 dmarschall 129
 
289 daniel-mar 130
In Filter Foundry, the function rnd(a,b) retrieves a random number in "realtime"; therefore, if the
131
seed is changed via rst(i), there is an immediate effect on the next call of the rnd(a,b) function.
132
 
133
For example, following filter would generate an one-colored picture without any randomness:
221 daniel-mar 134
        R: rst(123), rnd(0,255)
135
        G: rnd(0,255)
136
        B: rnd(0,255)
144 dmarschall 137
 
289 daniel-mar 138
If you want to generate a random pixel image with a non-default seed, you need to make sure
139
that rst(i) is called only once at the beginning (channel 0, coordinate 0|0):
294 daniel-mar 140
        R: (x== 0 && y ==0) ? rst(123) : 0, rnd(0,255)
221 daniel-mar 141
        G: rnd(0,255)
142
        B: rnd(0,255)
144 dmarschall 143
 
289 daniel-mar 144
In Filter Foundry, rst(i) can be called by branches and variables/sliders can
145
be used as arguments of rst(i).
144 dmarschall 146
 
147
 
143 dmarschall 148
Evaluation of conditional branches
149
----------------------------------
150
 
221 daniel-mar 151
**Filter Foundry:**
144 dmarschall 152
 
221 daniel-mar 153
Only the branches which will be chosen due to the conditional expression will be evaluated.
154
 
155
This means that following filter would generate a black canvas: (Testcase conditional_eval_1.afs)
156
 
157
        R: 1==0 ? put(255,0) : 0
158
        G: get(0)
159
        B: 0
160
 
161
In boolean expressions, the evaluation will be aborted if the result is already determined.
162
 
163
So, this will also generate a black canvas: (Testcase conditional_eval_2.afs)
164
 
165
        R: 1==0 && put(255,0) ? 0: 0
166
        G: get(0)
167
        B: 0
168
 
169
This will also generate a black canvas: (Testcase conditional_eval_3.afs)
170
 
171
        R: 1==1 || put(255,0) ? 0 : 0
172
        G: get(0)
173
        B: 0
174
 
175
**Filter Factory:**
176
 
177
Each branch inside a if-then-else expression will be evaluated.
178
This means that following filter would generate a green canvas: (Testcase conditional_eval_1.afs)
179
 
180
        R: 1==0 ? put(255,0) : 0
181
        G: get(0)
182
        B: 0
183
 
184
Also, all arguments of an boolean expression will be fully evaluated.
185
So, this will also generate a green canvas: (Testcase conditional_eval_2.afs)
186
 
187
        R: 1==0 && put(255,0) ? 0: 0
188
        G: get(0)
189
        B: 0
190
 
191
This will also generate a green canvas: (Testcase conditional_eval_3.afs)
192
 
193
        R: 1==1 || put(255,0) ? 0 : 0
194
        G: get(0)
195
        B: 0