Vuo  2.3.2
VuoImageDilate.c
Go to the documentation of this file.
1 
10 #include "node.h"
11 #include "VuoImageRenderer.h"
12 #include "VuoImageDilate.h"
13 
15 #ifdef VUO_COMPILER
17  "title" : "VuoImageDilate",
18  "dependencies" : [
19  "VuoImageRenderer",
20  "VuoReal",
21  ]
22 });
23 #endif
25 
29 typedef struct
30 {
31  VuoShader shader[2][4]; // [func][shape]
33 
37 void VuoImageDilate_free(void *blur)
38 {
40  for (int func = 0; func <= 1; ++func)
41  for (int shape = VuoBlurShape_Box; shape <= VuoBlurShape_Disc; ++shape)
42  VuoRelease(bi->shader[func][shape]);
43 }
44 
49 {
52 
53  static const char *fragmentShader = VUO_STRINGIFY(
54  \n#include "VuoGlslAlpha.glsl"
55  \n#include "VuoGlslBrightness.glsl"
56 
57  // Inputs
58  uniform sampler2D texture;
59  uniform vec2 viewportSize;
60  uniform float halfWidth;
61  varying vec2 fragmentTextureCoordinate;
62 
63  \n#if FUNC == 0\n
64  \n#define func max\n
65  \n#define a 0\n
66  \n#else\n
67  \n#define func min\n
68  \n#define a 1\n
69  \n#endif\n
70 
71  float straightstep(float edge0, float edge1, float x)
72  {
73  return clamp((x - edge0) / (edge1 - edge0), 0., 1.);
74  }
75 
76  void main()
77  {
78  vec4 c = vec4(a);
79 
80  float delta = fwidth(fragmentTextureCoordinate.x) * viewportSize.x/2.;
81 
82  \n#if SHAPE == 2\n // Box
83 
84  int steps = int(halfWidth) + 1;
85 
86  for (int y = -steps; y <= steps; ++y)
87  for (int x = -steps; x <= steps; ++x)
88  {
89  float f = straightstep(halfWidth + delta, halfWidth - delta, abs(float(x)))
90  * straightstep(halfWidth + delta, halfWidth - delta, abs(float(y)));
91  c = mix(c, func(c, VuoGlsl_sample(texture, fragmentTextureCoordinate + vec2(float(x)/viewportSize.x, float(y)/viewportSize.y))), f);
92  }
93 
94  \n#else\n // Disc
95 
96  for (int y = 0; y <= halfWidth + 1; ++y)
97  for (int x = 0; x <= halfWidth + 1; ++x)
98  {
99  float dist = length(vec2(x,y));
100  float f = straightstep(halfWidth + delta, halfWidth - delta, dist);
101  float sx = float(x)/viewportSize.x;
102  float sy = float(y)/viewportSize.y;
103 
104  // Fourfold symmetry
105  c = mix(c, func(c, VuoGlsl_sample(texture, fragmentTextureCoordinate + vec2( sx, sy))), f);
106  c = mix(c, func(c, VuoGlsl_sample(texture, fragmentTextureCoordinate + vec2(-sx, sy))), f);
107  c = mix(c, func(c, VuoGlsl_sample(texture, fragmentTextureCoordinate + vec2( sx, -sy))), f);
108  c = mix(c, func(c, VuoGlsl_sample(texture, fragmentTextureCoordinate + vec2(-sx, -sy))), f);
109  }
110 
111  \n#endif\n
112 
113  gl_FragColor = c;
114  }
115  );
116 
117  for (int func = 0; func <= 1; ++func)
118  for (int shape = VuoBlurShape_Box; shape <= VuoBlurShape_Disc; ++shape)
119  {
120  char *sourceWithPrefix = VuoText_format("#version 120\n#define FUNC %d\n#define SHAPE %d\n\n%s", func, shape, fragmentShader);
121  bi->shader[func][shape] = VuoShader_make("Morphology Shader");
122  VuoShader_addSource(bi->shader[func][shape], VuoMesh_IndividualTriangles, NULL, NULL, sourceWithPrefix);
123  VuoRetain(bi->shader[func][shape]);
124  }
125 
126  return (VuoImageDilate)bi;
127 }
128 
133 {
134  if (!image)
135  return NULL;
136 
137  radius *= image->scaleFactor;
138 
139  if (VuoReal_areEqual(radius, 0))
140  return image;
141 
143 
144  int func = radius >= 0 ? 0 : 1;
145  int shape2 = MAX(MIN(shape, VuoBlurShape_Disc), VuoBlurShape_Box);
146 
147  VuoShader_setUniform_VuoImage(bi->shader[func][shape2], "texture", image);
148  VuoShader_setUniform_VuoReal(bi->shader[func][shape2], "halfWidth", fabs(radius) + .5);
149 
150  VuoImage dilatedImage = VuoImageRenderer_render(bi->shader[func][shape2], image->pixelsWide, image->pixelsHigh, VuoImage_getColorDepth(image));
151 
152  if (rescind)
153  {
154  VuoImage d = dilatedImage;
155  VuoLocal(d);
156 
157  int otherFunc = 1-func;
158  VuoShader_setUniform_VuoImage(bi->shader[otherFunc][shape2], "texture", d);
159  VuoShader_setUniform_VuoReal(bi->shader[otherFunc][shape2], "halfWidth", fabs(radius) + .5);
160 
161  dilatedImage = VuoImageRenderer_render(bi->shader[otherFunc][shape2], image->pixelsWide, image->pixelsHigh, VuoImage_getColorDepth(image));
162  }
163 
164  return dilatedImage;
165 }