pyfast 4.13.1__cp36-abi3-win_amd64.whl → 4.14.0__cp36-abi3-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fast/bin/FAST.dll CHANGED
Binary file
Binary file
Binary file
Binary file
Binary file
fast/bin/UFFviewer.exe CHANGED
Binary file
fast/bin/_fast.pyd CHANGED
Binary file
fast/bin/jpeg62.dll ADDED
Binary file
fast/bin/runPipeline.exe CHANGED
Binary file
fast/bin/systemCheck.exe CHANGED
Binary file
fast/bin/tiff.dll CHANGED
Binary file
fast/bin/zlib1.dll ADDED
Binary file
fast/fast.py CHANGED
@@ -154,6 +154,8 @@ def getDefaultIntensityWindow(type: "fast::DataType") -> "float":
154
154
 
155
155
  def deleteArray(data: "void *", type: "fast::DataType") -> "void":
156
156
  return _fast.deleteArray(data, type)
157
+ PixelConnectivity_Closests = _fast.PixelConnectivity_Closests
158
+ PixelConnectivity_All = _fast.PixelConnectivity_All
157
159
  class vectori(object):
158
160
  thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
159
161
  __repr__ = _swig_repr
@@ -6568,6 +6570,222 @@ def ColorToGrayscale_getStaticNameOfClass() -> "std::string":
6568
6570
  def ColorToGrayscale_create() -> "std::shared_ptr< fast::ColorToGrayscale >":
6569
6571
  return _fast.ColorToGrayscale_create()
6570
6572
 
6573
+ class DrawCubicHermiteSpline(ProcessObject):
6574
+ r"""
6575
+ Draw cubic hermite splines on an input Image
6576
+
6577
+ Inputs:
6578
+ - 0: Image
6579
+
6580
+ Outputs
6581
+ - 0: Image
6582
+
6583
+ """
6584
+
6585
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
6586
+
6587
+ def __init__(self, *args, **kwargs):
6588
+ raise AttributeError("No constructor defined")
6589
+ __repr__ = _swig_repr
6590
+
6591
+ @staticmethod
6592
+ def New() -> "std::shared_ptr< fast::DrawCubicHermiteSpline >":
6593
+ return _fast.DrawCubicHermiteSpline_New()
6594
+
6595
+ def getNameOfClass(self) -> "std::string":
6596
+ return _fast.DrawCubicHermiteSpline_getNameOfClass(self)
6597
+
6598
+ @staticmethod
6599
+ def getStaticNameOfClass() -> "std::string":
6600
+ return _fast.DrawCubicHermiteSpline_getStaticNameOfClass()
6601
+ CloseSpline_No = _fast.DrawCubicHermiteSpline_CloseSpline_No
6602
+ CloseSpline_Smooth = _fast.DrawCubicHermiteSpline_CloseSpline_Smooth
6603
+ CloseSpline_Straight = _fast.DrawCubicHermiteSpline_CloseSpline_Straight
6604
+
6605
+ @staticmethod
6606
+ def create(*args, **kwargs) -> "std::shared_ptr< fast::DrawCubicHermiteSpline >":
6607
+ r"""
6608
+ Create instance
6609
+
6610
+ :type controlPoints: std::vector< Vector2f,std::allocator< Vector2f > >
6611
+ :param controlPoints:
6612
+ :type close: int
6613
+ :param close:
6614
+ :type value: float
6615
+ :param value:
6616
+ :type color: :py:class:`Color`
6617
+ :param color:
6618
+ :type fill: boolean
6619
+ :param fill:
6620
+ :type controlPointsInPixels: boolean
6621
+ :param controlPointsInPixels:
6622
+ :rtype: :py:class:`DrawCubicHermiteSpline`
6623
+ :return: instance
6624
+ """
6625
+ return _fast.DrawCubicHermiteSpline_create(*args, **kwargs)
6626
+
6627
+ def setControlPoints(self, controlPoints: "std::vector< Vector2f,std::allocator< Vector2f > >") -> "void":
6628
+ return _fast.DrawCubicHermiteSpline_setControlPoints(self, controlPoints)
6629
+ __swig_destroy__ = _fast.delete_DrawCubicHermiteSpline
6630
+
6631
+ # Register DrawCubicHermiteSpline in _fast:
6632
+ _fast.DrawCubicHermiteSpline_swigregister(DrawCubicHermiteSpline)
6633
+
6634
+ def DrawCubicHermiteSpline_New() -> "std::shared_ptr< fast::DrawCubicHermiteSpline >":
6635
+ return _fast.DrawCubicHermiteSpline_New()
6636
+
6637
+ def DrawCubicHermiteSpline_getStaticNameOfClass() -> "std::string":
6638
+ return _fast.DrawCubicHermiteSpline_getStaticNameOfClass()
6639
+
6640
+ def DrawCubicHermiteSpline_create(*args, **kwargs) -> "std::shared_ptr< fast::DrawCubicHermiteSpline >":
6641
+ r"""
6642
+ Create instance
6643
+
6644
+ :type controlPoints: std::vector< Vector2f,std::allocator< Vector2f > >
6645
+ :param controlPoints:
6646
+ :type close: int
6647
+ :param close:
6648
+ :type value: float
6649
+ :param value:
6650
+ :type color: :py:class:`Color`
6651
+ :param color:
6652
+ :type fill: boolean
6653
+ :param fill:
6654
+ :type controlPointsInPixels: boolean
6655
+ :param controlPointsInPixels:
6656
+ :rtype: :py:class:`DrawCubicHermiteSpline`
6657
+ :return: instance
6658
+ """
6659
+ return _fast.DrawCubicHermiteSpline_create(*args, **kwargs)
6660
+
6661
+ class FillHoles(ProcessObject):
6662
+ r"""
6663
+ Fill holes in image/segmentation
6664
+
6665
+ Inputs:
6666
+ - 0: Image
6667
+
6668
+ Outputs
6669
+ - 0: Image
6670
+
6671
+ """
6672
+
6673
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
6674
+
6675
+ def __init__(self, *args, **kwargs):
6676
+ raise AttributeError("No constructor defined")
6677
+ __repr__ = _swig_repr
6678
+
6679
+ @staticmethod
6680
+ def New() -> "std::shared_ptr< fast::FillHoles >":
6681
+ return _fast.FillHoles_New()
6682
+
6683
+ def getNameOfClass(self) -> "std::string":
6684
+ return _fast.FillHoles_getNameOfClass(self)
6685
+
6686
+ @staticmethod
6687
+ def getStaticNameOfClass() -> "std::string":
6688
+ return _fast.FillHoles_getStaticNameOfClass()
6689
+
6690
+ @staticmethod
6691
+ def create() -> "std::shared_ptr< fast::FillHoles >":
6692
+ return _fast.FillHoles_create()
6693
+ __swig_destroy__ = _fast.delete_FillHoles
6694
+
6695
+ # Register FillHoles in _fast:
6696
+ _fast.FillHoles_swigregister(FillHoles)
6697
+
6698
+ def FillHoles_New() -> "std::shared_ptr< fast::FillHoles >":
6699
+ return _fast.FillHoles_New()
6700
+
6701
+ def FillHoles_getStaticNameOfClass() -> "std::string":
6702
+ return _fast.FillHoles_getStaticNameOfClass()
6703
+
6704
+ def FillHoles_create() -> "std::shared_ptr< fast::FillHoles >":
6705
+ return _fast.FillHoles_create()
6706
+
6707
+ class DrawCircle(ProcessObject):
6708
+ r"""
6709
+ Draw circles on an input Image
6710
+
6711
+ Inputs:
6712
+ - 0: Image
6713
+
6714
+ Outputs
6715
+ - 0: Image
6716
+
6717
+ """
6718
+
6719
+ thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
6720
+
6721
+ def __init__(self, *args, **kwargs):
6722
+ raise AttributeError("No constructor defined")
6723
+ __repr__ = _swig_repr
6724
+
6725
+ @staticmethod
6726
+ def New() -> "std::shared_ptr< fast::DrawCircle >":
6727
+ return _fast.DrawCircle_New()
6728
+
6729
+ def getNameOfClass(self) -> "std::string":
6730
+ return _fast.DrawCircle_getNameOfClass(self)
6731
+
6732
+ @staticmethod
6733
+ def getStaticNameOfClass() -> "std::string":
6734
+ return _fast.DrawCircle_getStaticNameOfClass()
6735
+
6736
+ @staticmethod
6737
+ def create(*args, **kwargs) -> "std::shared_ptr< fast::DrawCircle >":
6738
+ r"""
6739
+ Create instance
6740
+
6741
+ :type centroids: std::vector< Vector2f,std::allocator< Vector2f > >
6742
+ :param centroids: List of centroid coordinates.
6743
+ :type radii: std::vector< float,std::allocator< float > >
6744
+ :param radii: Radius for each circle/centroid. If only one radius is given, it will be used for all circles.
6745
+ :type value: float
6746
+ :param value: Value to use to draw circles
6747
+ :type color: :py:class:`Color`
6748
+ :param color: Color to use to draw circles
6749
+ :type fill: boolean
6750
+ :param fill: Whether to fill the circle or not
6751
+ :type inPixels: boolean
6752
+ :param inPixels: Whether the centroids and radii are given in pixels or in millimeters
6753
+ :rtype: :py:class:`DrawCircle`
6754
+ :return: instance
6755
+ """
6756
+ return _fast.DrawCircle_create(*args, **kwargs)
6757
+ __swig_destroy__ = _fast.delete_DrawCircle
6758
+
6759
+ # Register DrawCircle in _fast:
6760
+ _fast.DrawCircle_swigregister(DrawCircle)
6761
+
6762
+ def DrawCircle_New() -> "std::shared_ptr< fast::DrawCircle >":
6763
+ return _fast.DrawCircle_New()
6764
+
6765
+ def DrawCircle_getStaticNameOfClass() -> "std::string":
6766
+ return _fast.DrawCircle_getStaticNameOfClass()
6767
+
6768
+ def DrawCircle_create(*args, **kwargs) -> "std::shared_ptr< fast::DrawCircle >":
6769
+ r"""
6770
+ Create instance
6771
+
6772
+ :type centroids: std::vector< Vector2f,std::allocator< Vector2f > >
6773
+ :param centroids: List of centroid coordinates.
6774
+ :type radii: std::vector< float,std::allocator< float > >
6775
+ :param radii: Radius for each circle/centroid. If only one radius is given, it will be used for all circles.
6776
+ :type value: float
6777
+ :param value: Value to use to draw circles
6778
+ :type color: :py:class:`Color`
6779
+ :param color: Color to use to draw circles
6780
+ :type fill: boolean
6781
+ :param fill: Whether to fill the circle or not
6782
+ :type inPixels: boolean
6783
+ :param inPixels: Whether the centroids and radii are given in pixels or in millimeters
6784
+ :rtype: :py:class:`DrawCircle`
6785
+ :return: instance
6786
+ """
6787
+ return _fast.DrawCircle_create(*args, **kwargs)
6788
+
6571
6789
  class GaussianSmoothing(ProcessObject):
6572
6790
  r"""
6573
6791
  Smoothing by convolution with a Gaussian mask
@@ -12146,7 +12364,7 @@ class SeededRegionGrowing(ProcessObject):
12146
12364
  return _fast.SeededRegionGrowing_connect(self, *args)
12147
12365
 
12148
12366
  @staticmethod
12149
- def create(intensityMinimum: "float", intensityMaximum: "float", seedPoints: "std::vector< Vector3i,std::allocator< Vector3i > >") -> "std::shared_ptr< fast::SeededRegionGrowing >":
12367
+ def create(*args, **kwargs) -> "std::shared_ptr< fast::SeededRegionGrowing >":
12150
12368
  r"""
12151
12369
  Create instance
12152
12370
  :type intensityMinimum: float
@@ -12155,10 +12373,12 @@ class SeededRegionGrowing(ProcessObject):
12155
12373
  :param intensityMaximum: Maximum intensity to accept voxel as part of segmentation.
12156
12374
  :type seedPoints: std::vector< Vector3i,std::allocator< Vector3i > >
12157
12375
  :param seedPoints: List of seed points in pixel space. If 2D, z component is not used.
12376
+ :type connectivity: int
12377
+ :param connectivity: Which connectivity to use when growing
12158
12378
  :rtype: :py:class:`SeededRegionGrowing`
12159
12379
  :return: instance
12160
12380
  """
12161
- return _fast.SeededRegionGrowing_create(intensityMinimum, intensityMaximum, seedPoints)
12381
+ return _fast.SeededRegionGrowing_create(*args, **kwargs)
12162
12382
 
12163
12383
  def setIntensityRange(self, min: "float", max: "float") -> "void":
12164
12384
  return _fast.SeededRegionGrowing_setIntensityRange(self, min, max)
@@ -12179,7 +12399,7 @@ def SeededRegionGrowing_New() -> "std::shared_ptr< fast::SeededRegionGrowing >":
12179
12399
  def SeededRegionGrowing_getStaticNameOfClass() -> "std::string":
12180
12400
  return _fast.SeededRegionGrowing_getStaticNameOfClass()
12181
12401
 
12182
- def SeededRegionGrowing_create(intensityMinimum: "float", intensityMaximum: "float", seedPoints: "std::vector< Vector3i,std::allocator< Vector3i > >") -> "std::shared_ptr< fast::SeededRegionGrowing >":
12402
+ def SeededRegionGrowing_create(*args, **kwargs) -> "std::shared_ptr< fast::SeededRegionGrowing >":
12183
12403
  r"""
12184
12404
  Create instance
12185
12405
  :type intensityMinimum: float
@@ -12188,10 +12408,12 @@ def SeededRegionGrowing_create(intensityMinimum: "float", intensityMaximum: "flo
12188
12408
  :param intensityMaximum: Maximum intensity to accept voxel as part of segmentation.
12189
12409
  :type seedPoints: std::vector< Vector3i,std::allocator< Vector3i > >
12190
12410
  :param seedPoints: List of seed points in pixel space. If 2D, z component is not used.
12411
+ :type connectivity: int
12412
+ :param connectivity: Which connectivity to use when growing
12191
12413
  :rtype: :py:class:`SeededRegionGrowing`
12192
12414
  :return: instance
12193
12415
  """
12194
- return _fast.SeededRegionGrowing_create(intensityMinimum, intensityMaximum, seedPoints)
12416
+ return _fast.SeededRegionGrowing_create(*args, **kwargs)
12195
12417
 
12196
12418
  class SegmentationVolumeReconstructor(ProcessObject):
12197
12419
  r"""
@@ -0,0 +1,97 @@
1
+
2
+ __kernel void drawFilledCircles(
3
+ __global float2* centroids,
4
+ __private int size,
5
+ __write_only image2d_t output,
6
+ __global float2* radii,
7
+ __private char singleRadius,
8
+ __private float value,
9
+ __private float3 color
10
+ ) {
11
+ const int index = get_global_id(0);
12
+ float2 centroid = centroids[index];
13
+ float2 radius;
14
+ if(singleRadius == 1) {
15
+ radius = radii[0];
16
+ } else {
17
+ radius = radii[index];
18
+ }
19
+
20
+ const int dataType = get_image_channel_data_type(output);
21
+
22
+ float4 write = {value, value, value, value};
23
+ if(value == 0.0f) {
24
+ // Use color instead
25
+ write.xyz = color;
26
+ if(dataType != CLK_FLOAT) {
27
+ write = round(write*255);
28
+ }
29
+ }
30
+
31
+ for(int a = -ceil(radius.x); a <= ceil(radius.x); ++a) {
32
+ for(int b = -ceil(radius.y); b <= ceil(radius.y); ++b) {
33
+ float2 current = round(centroid + (float2)(a, b));
34
+ float2 n = current - centroid;
35
+ float inside = (n.x*n.x)/(radius.x*radius.x) + (n.y*n.y)/(radius.y*radius.y);
36
+ if(inside <= 1.0f) { // Inside ellipse
37
+ int2 pos = convert_int2(current);
38
+ if(pos.x >= 0 && pos.y >= 0 && pos.x < get_image_width(output) && pos.y < get_image_height(output)) {
39
+ if(dataType == CLK_FLOAT) {
40
+ write_imagef(output, pos, write);
41
+ } else if(dataType == CLK_UNSIGNED_INT8 || dataType == CLK_UNSIGNED_INT16 || dataType == CLK_UNSIGNED_INT32) {
42
+ write_imageui(output, pos, convert_uint4(write));
43
+ } else {
44
+ write_imagei(output, pos, convert_int4(write));
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ }
51
+
52
+ __kernel void drawCircles(
53
+ __global float2* centroids,
54
+ __private int size,
55
+ __write_only image2d_t output,
56
+ __global float2* radii,
57
+ __private char singleRadius,
58
+ __private float value,
59
+ __private float3 color
60
+ ) {
61
+ const int index = get_global_id(0);
62
+ float2 centroid = centroids[index];
63
+ float2 radius;
64
+ if(singleRadius == 1) {
65
+ radius = radii[0];
66
+ } else {
67
+ radius = radii[index];
68
+ }
69
+ const int dataType = get_image_channel_data_type(output);
70
+
71
+ float4 write = {value, value, value, value};
72
+ if(value == 0.0f) {
73
+ // Use color instead
74
+ write.xyz = color;
75
+ if(dataType != CLK_FLOAT) {
76
+ write = round(write*255);
77
+ }
78
+ }
79
+
80
+ // Calculate circumference
81
+ const int N = ceil(2*M_PI_F*max(radius.x, radius.y)); // No closed formula for ellipse circumference
82
+ for(int i = 0; i < N; ++i) {
83
+ float angle = i*2.0f*M_PI_F/N;
84
+ int x = centroid.x + round(cos(angle)*radius.x);
85
+ int y = centroid.y + round(sin(angle)*radius.y);
86
+ printf("%d %d\n", x, y);
87
+
88
+ if(dataType == CLK_FLOAT) {
89
+ write_imagef(output, (int2)(x, y), write);
90
+ } else if(dataType == CLK_UNSIGNED_INT8 || dataType == CLK_UNSIGNED_INT16 || dataType == CLK_UNSIGNED_INT32) {
91
+ write_imageui(output, (int2)(x, y), convert_uint4(write));
92
+ } else {
93
+ write_imagei(output, (int2)(x, y), convert_int4(write));
94
+ }
95
+ }
96
+
97
+ }
@@ -0,0 +1,28 @@
1
+ __constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
2
+
3
+ __kernel void invert2D(
4
+ __read_only image2d_t input,
5
+ __write_only image2d_t output,
6
+ __private float min,
7
+ __private float max
8
+ ) {
9
+ const int2 pos = {get_global_id(0), get_global_id(1)};
10
+ int dataType = get_image_channel_data_type(input);
11
+
12
+ float4 value;
13
+ if(dataType == CLK_FLOAT) {
14
+ value = read_imagef(input, sampler, pos);
15
+ } else if(dataType == CLK_UNSIGNED_INT8 || dataType == CLK_UNSIGNED_INT16 || dataType == CLK_UNSIGNED_INT32) {
16
+ value = convert_float4(read_imageui(input, sampler, pos));
17
+ } else {
18
+ value = convert_float4(read_imagei(input, sampler, pos));
19
+ }
20
+ value = (max - min) - value;
21
+ if(dataType == CLK_FLOAT) {
22
+ write_imagef(output, pos, value);
23
+ } else if(dataType == CLK_UNSIGNED_INT8 || dataType == CLK_UNSIGNED_INT16 || dataType == CLK_UNSIGNED_INT32) {
24
+ write_imageui(output, pos, convert_uint4(value));
25
+ } else {
26
+ write_imagei(output, pos, convert_int4(value));
27
+ }
28
+ }
@@ -14,7 +14,8 @@ __kernel void seededRegionGrowing(
14
14
  __global char* segmentation,
15
15
  __global char* stopGrowing,
16
16
  __private float min,
17
- __private float max
17
+ __private float max,
18
+ __private int connectivity
18
19
  ) {
19
20
  const int2 pos = {get_global_id(0), get_global_id(1)};
20
21
  const uint linearPos = pos.x + pos.y*get_global_size(0);
@@ -23,9 +24,9 @@ __kernel void seededRegionGrowing(
23
24
  int2 offset[8] = {
24
25
  {1,0},
25
26
  {0,1},
26
- {1,1},
27
27
  {-1,0},
28
28
  {0,-1},
29
+ {1,1},
29
30
  {-1,-1},
30
31
  {-1,1},
31
32
  {1,-1}
@@ -36,7 +37,7 @@ __kernel void seededRegionGrowing(
36
37
  if(intensity >= min && intensity <= max) {
37
38
  segmentation[linearPos] = 1; // add pixel to segmentation
38
39
  // Add neighbor pixels to queue
39
- for(int i = 0; i < 8; i++) {
40
+ for(int i = 0; i < connectivity; i++) {
40
41
  // Out of bounds check
41
42
  int2 neighborPos = pos + offset[i];
42
43
  if(neighborPos.x < 0 || neighborPos.y < 0 ||
@@ -16,18 +16,40 @@ __kernel void seededRegionGrowing(
16
16
  __global char* segmentation,
17
17
  __global char* stopGrowing,
18
18
  __private float min,
19
- __private float max
19
+ __private float max,
20
+ __private int connectivity
20
21
  ) {
21
22
  const int4 pos = {get_global_id(0), get_global_id(1), get_global_id(2), 0};
22
23
  const uint linearPos = pos.x + pos.y*get_global_size(0) + pos.z*get_global_size(0)*get_global_size(1);
23
24
 
24
- const int4 offsets[6] = {
25
- {0,0,1,0},
26
- {0,1,0,0},
27
- {1,0,0,0},
28
- {0,0,-1,0},
29
- {0,-1,0,0},
30
- {-1,0,0,0},
25
+ const int4 offsets[26] = {
26
+ {-1, 0, 0, 0},
27
+ {0, -1, 0, 0},
28
+ {0, 0, -1, 0},
29
+ {0, 0, 1, 0},
30
+ {0, 1, 0, 0},
31
+ {1, 0, 0, 0},
32
+
33
+ {-1, -1, -1, 0},
34
+ {-1, -1, 0, 0},
35
+ {-1, -1, 1, 0},
36
+ {-1, 0, -1, 0},
37
+ {-1, 0, 1, 0},
38
+ {-1, 1, -1, 0},
39
+ {-1, 1, 0, 0},
40
+ {-1, 1, 1, 0},
41
+ {0, -1, -1, 0},
42
+ {0, -1, 1, 0},
43
+ {0, 1, -1, 0},
44
+ {0, 1, 1, 0},
45
+ {1, -1, -1, 0},
46
+ {1, -1, 0, 0},
47
+ {1, -1, 1, 0},
48
+ {1, 0, -1, 0},
49
+ {1, 0, 1, 0},
50
+ {1, 1, -1, 0},
51
+ {1, 1, 0, 0},
52
+ {1, 1, 1, 0}
31
53
  };
32
54
 
33
55
  if(segmentation[linearPos] == 2) { // pixel is in queue
@@ -35,7 +57,7 @@ __kernel void seededRegionGrowing(
35
57
  if(intensity >= min && intensity <= max) {
36
58
  segmentation[linearPos] = 1; // add pixel to segmentation
37
59
  // Add neighbor pixels to queue
38
- for(int i = 0; i < 6; i++) {
60
+ for(int i = 0; i < connectivity; i++) {
39
61
  // Out of bounds check. TODO something more efficient
40
62
  int4 neighborPos = pos + offsets[i];
41
63
  if(neighborPos.x < 0 || neighborPos.y < 0 || neighborPos.z < 0 ||
@@ -681,10 +681,12 @@ __kernel void traverseHP(
681
681
  );
682
682
 
683
683
  const float value0 = READ_RAW_DATA(rawData, sampler, (int4)(point0.x, point0.y, point0.z, 0)).x;
684
+ const float value1 = READ_RAW_DATA(rawData, sampler, (int4)(point1.x, point1.y, point1.z, 0)).x;
684
685
  float diff = native_divide(
685
- isolevel-value0,
686
- READ_RAW_DATA(rawData, sampler, (int4)(point1.x, point1.y, point1.z, 0)).x - value0);
686
+ isolevel - value0,
687
+ value1 - value0);
687
688
 
689
+ diff = clamp(diff, 0.0f, 1.0f); // TODO Should not be needed
688
690
 
689
691
  // OpenCL on Mac is missing the mix function for some reason
690
692
  #ifdef MAC_HACK