Subversion Repositories filter_foundry

Rev

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

Rev Author Line No. Line
141 dmarschall 1
 
2
Implementation detail differences			Daniel Marschall
158 dmarschall 3
=================================			08 January 2018
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
 
18
	i=((76*r)+(150*g)+(29*b))/256            Output range is 0..254
146 dmarschall 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
 
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
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
	get(x)=0 if x>255 or x<0
36
 
37
Filter Factory:
38
	get(x)=x if x>255 or x<0
39
	[Note: The result "x" was most likely not intended but a result of an undefined behavior]
40
 
41
 
42
r, g, b at empty canvas (Testcase emptycanvas.afs)
43
-----------------------
44
 
45
In Filter Factory, an empty (transparent) canvas of a new file is initialized as r=g=b=0
46
 
47
Filter Foundry initializes it as r=g=b=255
48
 
49
 
50
rnd(a,b) and rst(i) (Testcases rst_*.afs)
51
-------------------
52
 
192 daniel-mar 53
Filter Foundry's implementation of rst(i) (an undocumented function that sets the seed for the PRG)
54
and rnd(a,b) (generate a random number between a and b, inclusively)
144 dmarschall 55
differs from the implementation of Filter Factory in many ways.
141 dmarschall 56
 
144 dmarschall 57
1. In Filter Foundry, the random seed is automatically initialized with seed 691204.
58
   In Filter Factory, the random seed is automatically initialized with seed 0.   
141 dmarschall 59
 
144 dmarschall 60
2. In Filter Foundry, the argument i of the function rst(i) is limited to the
141 dmarschall 61
   type "unsigned int" (argument of the function srand() in the C StdLib),
62
   so the allowed range is 0..4294967295.
63
 
64
   In Filter Factory, the argument i must be between 0 and 32767, inclusively.
142 dmarschall 65
   If the argument is not within this range, the operation "and 0x7FFF" will be applied to it
141 dmarschall 66
   to extract the low 15 bits.
143 dmarschall 67
 
192 daniel-mar 68
3. In Filter Foundry, the function rnd(a,b) retrieves a random number in realtime; therefore, if the
144 dmarschall 69
   seed is changed via rst(i), there is an immediate effect on the next call of the rnd(a,b) function.
70
   For example, following filter would generate an one-colored picture without any randomness:
71
	R: rst(123), rnd(0,255)
72
	G: rnd(0,255)
73
	B: rnd(0,255)
74
   If you want to generate a random pixel image with a non-default seed, you need to make sure
75
   that rst(i) is called only once at the beginning (channel 0, coordinate 0|0):
76
	R: (x==0 && y==0) ? rst(123) : 0, rnd(0,255)
77
	G: rnd(0,255)
78
	B: rnd(0,255)
143 dmarschall 79
 
144 dmarschall 80
   In Filter Factory, the rnd(a,b) function is more complex.
81
   As soon as the function rnd(a,b) is used once, rst(i) will not have any effect.
82
   So, if you want to use rst(i), you must make sure to call it before using rnd(a,b).
83
   Following filter will generate a random pixel picture:
84
	R: rst(123), rnd(0,255)
85
	G: rnd(0,255)
86
	B: rnd(0,255)
87
   Following filter would generate a different random pixel picture:
88
	R: rst(456), rnd(0,255)
89
	G: rnd(0,255)
90
	B: rnd(0,255)
91
   Following filter would generate the same random pixel picture:
92
	R: rst(456), rnd(0,255)+rst(123)  <-- note that rst() always returns 0, so the '+' operator is OK
93
	G: rnd(0,255)
94
	B: rnd(0,255)+rst(456)            <-- the last rst(456) call is to mitigate a bug; see below.
95
 
96
4. In Filter Factory, due to a bug, the random state is not reset to its initial state (0) before the filter is applied:
97
   The preview image processing will modify the random state, and once the filter is actually applied (pressing "OK"),
98
   the random state that was set in the preview picture, will be used.
99
   Example:
100
	R: rnd(0,255), rst(123)    <-- note that the rst(123) is ignored because rnd() was already called.
101
	G: rnd(0,255)
102
	B: rnd(0,255)
103
   This filter will produce a random pixel picture with the initial default random seed 0,
104
   but only for the first calculation (i.e. in the preview picture processing, or in a standalone filter without dialog).
105
   Any further calculation will result in a random pixel picture with random seed 123,
106
   since the random seed 123 will be taken from the previous run.
107
 
108
   Furthermore, the random state can't be changed again, not even at the beginning of the red channel before any rnd() call.
109
   Example:
110
	R: rst(333), rnd(0,255)
111
	G: rnd(0,255)
112
	B: rnd(0,255)+rst(555)
113
   This filter will produce a picture with random seed 333 on the first calculation,
114
   and at every further calculation, a random picture with seed 555.
115
   Another example:
116
	R: rst(ctl(0)), rnd(0,255)
117
	G: rnd(0,255)
118
	B: rnd(0,255)+rst(555)
119
   In this filter, the slider value is ignored and the resulting picture will always be the same.
120
 
121
 
143 dmarschall 122
Evaluation of conditional branches
123
----------------------------------
124
 
144 dmarschall 125
Filter Foundry:
126
	Only the branches which will be chosen due to the conditional expression will be evaluated.
127
	This means that following filter would generate a black canvas: (Testcase conditional_eval_1.afs)
128
	R: 1==0 ? put(255,0) : 0
129
	G: get(0)
130
	B: 0
131
	In boolean expressions, the evaluation will be aborted if the result is already determined.
132
	So, this will also generate a black canvas: (Testcase conditional_eval_2.afs)
133
	R: 1==0 && put(255,0) ? 0: 0
134
	G: get(0)
135
	B: 0
136
	This will also generate a black canvas: (Testcase conditional_eval_3.afs)
137
	R: 1==1 || put(255,0) ? 0 : 0
138
	G: get(0)
139
	B: 0
140
 
143 dmarschall 141
Filter Factory:
142
	Each branch inside a if-then-else expression will be evaluated.
143
	This means that following filter would generate a green canvas: (Testcase conditional_eval_1.afs)
144 dmarschall 144
	R: 1==0 ? put(255,0) : 0
145
	G: get(0)
146
	B: 0
143 dmarschall 147
	Also, all arguments of an boolean expression will be fully evaluated.
148
	So, this will also generate a green canvas: (Testcase conditional_eval_2.afs)
144 dmarschall 149
	R: 1==0 && put(255,0) ? 0: 0
150
	G: get(0)
151
	B: 0
152
	This will also generate a green canvas: (Testcase conditional_eval_3.afs)
153
	R: 1==1 || put(255,0) ? 0 : 0
154
	G: get(0)
155
	B: 0