Subversion Repositories filter_foundry

Rev

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

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