Blender V4.3
image_drawing.h
Go to the documentation of this file.
1// Copyright (c) 2009 libmv authors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to
5// deal in the Software without restriction, including without limitation the
6// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7// sell copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19// IN THE SOFTWARE.
20
21// Generic Image Processing Algorithm (GIPA)
22// Use an ImageModel class that must implement the following :
23//
24// ::Contains(int y, int x) <= Tell if a point is inside or not the image
25// ::operator(int y,int x) <= Modification accessor over the pixel (y,x)
26// ::Width()
27// ::Height()
28
29#ifndef LIBMV_IMAGE_IMAGE_DRAWING_H
30#define LIBMV_IMAGE_IMAGE_DRAWING_H
31
32namespace libmv {
33
36template <class Image, class Color>
37inline void safePutPixel(int yc, int xc, const Color& col, Image* pim) {
38 if (!pim) {
39 return;
40 }
41 if (pim->Contains(yc, xc)) {
42 (*pim)(yc, xc) = col;
43 }
44}
48template <class Image, class Color>
49inline void safePutPixel(int yc, int xc, const Color* col, Image* pim) {
50 if (!pim) {
51 return;
52 }
53 if (pim->Contains(yc, xc)) {
54 for (int i = 0; i < pim->Depth(); ++i) {
55 (*pim)(yc, xc, i) = *(col + i);
56 }
57 }
58}
59
60// Bresenham approach to draw ellipse.
61// http://raphaello.univ-fcomte.fr/ig/algorithme/ExemplesGLUt/BresenhamEllipse.htm
62// Add the rotation of the ellipse.
63// As the algo. use symmetry we must use 4 rotations.
64template <class Image, class Color>
65void DrawEllipse(int xc,
66 int yc,
67 int radiusA,
68 int radiusB,
69 const Color& col,
70 Image* pim,
71 double angle = 0.0) {
72 int a = radiusA;
73 int b = radiusB;
74
75 // Counter Clockwise rotation matrix.
76 double matXY[4] = {cos(angle), sin(angle), -sin(angle), cos(angle)};
77 int x, y;
78 double d1, d2;
79 x = 0;
80 y = b;
81 d1 = b * b - a * a * b + a * a / 4;
82
83 float rotX = (matXY[0] * x + matXY[1] * y);
84 float rotY = (matXY[2] * x + matXY[3] * y);
85 safePutPixel(yc + rotY, xc + rotX, col, pim);
86 rotX = (matXY[0] * x - matXY[1] * y);
87 rotY = (matXY[2] * x - matXY[3] * y);
88 safePutPixel(yc + rotY, xc + rotX, col, pim);
89 rotX = (-matXY[0] * x - matXY[1] * y);
90 rotY = (-matXY[2] * x - matXY[3] * y);
91 safePutPixel(yc + rotY, xc + rotX, col, pim);
92 rotX = (-matXY[0] * x + matXY[1] * y);
93 rotY = (-matXY[2] * x + matXY[3] * y);
94 safePutPixel(yc + rotY, xc + rotX, col, pim);
95
96 while (a * a * (y - .5) > b * b * (x + 1)) {
97 if (d1 < 0) {
98 d1 += b * b * (2 * x + 3);
99 ++x;
100 } else {
101 d1 += b * b * (2 * x + 3) + a * a * (-2 * y + 2);
102 ++x;
103 --y;
104 }
105 rotX = (matXY[0] * x + matXY[1] * y);
106 rotY = (matXY[2] * x + matXY[3] * y);
107 safePutPixel(yc + rotY, xc + rotX, col, pim);
108 rotX = (matXY[0] * x - matXY[1] * y);
109 rotY = (matXY[2] * x - matXY[3] * y);
110 safePutPixel(yc + rotY, xc + rotX, col, pim);
111 rotX = (-matXY[0] * x - matXY[1] * y);
112 rotY = (-matXY[2] * x - matXY[3] * y);
113 safePutPixel(yc + rotY, xc + rotX, col, pim);
114 rotX = (-matXY[0] * x + matXY[1] * y);
115 rotY = (-matXY[2] * x + matXY[3] * y);
116 safePutPixel(yc + rotY, xc + rotX, col, pim);
117 }
118 d2 = b * b * (x + .5) * (x + .5) + a * a * (y - 1) * (y - 1) - a * a * b * b;
119 while (y > 0) {
120 if (d2 < 0) {
121 d2 += b * b * (2 * x + 2) + a * a * (-2 * y + 3);
122 --y;
123 ++x;
124 } else {
125 d2 += a * a * (-2 * y + 3);
126 --y;
127 }
128 rotX = (matXY[0] * x + matXY[1] * y);
129 rotY = (matXY[2] * x + matXY[3] * y);
130 safePutPixel(yc + rotY, xc + rotX, col, pim);
131 rotX = (matXY[0] * x - matXY[1] * y);
132 rotY = (matXY[2] * x - matXY[3] * y);
133 safePutPixel(yc + rotY, xc + rotX, col, pim);
134 rotX = (-matXY[0] * x - matXY[1] * y);
135 rotY = (-matXY[2] * x - matXY[3] * y);
136 safePutPixel(yc + rotY, xc + rotX, col, pim);
137 rotX = (-matXY[0] * x + matXY[1] * y);
138 rotY = (-matXY[2] * x + matXY[3] * y);
139 safePutPixel(yc + rotY, xc + rotX, col, pim);
140 }
141}
142
143// Bresenham approach do not allow to draw concentric circle without holes.
144// So it's better the use the Andres method.
145// http://fr.wikipedia.org/wiki/Algorithme_de_tracé_de_cercle_d'Andres.
146template <class Image, class Color>
147void DrawCircle(int x, int y, int radius, const Color& col, Image* pim) {
148 Image& im = *pim;
149 if (im.Contains(y + radius, x + radius) ||
150 im.Contains(y + radius, x - radius) ||
151 im.Contains(y - radius, x + radius) ||
152 im.Contains(y - radius, x - radius)) {
153 int x1 = 0;
154 int y1 = radius;
155 int d = radius - 1;
156 while (y1 >= x1) {
157 // Draw the point for each octant.
158 safePutPixel(y1 + y, x1 + x, col, pim);
159 safePutPixel(x1 + y, y1 + x, col, pim);
160 safePutPixel(y1 + y, -x1 + x, col, pim);
161 safePutPixel(x1 + y, -y1 + x, col, pim);
162 safePutPixel(-y1 + y, x1 + x, col, pim);
163 safePutPixel(-x1 + y, y1 + x, col, pim);
164 safePutPixel(-y1 + y, -x1 + x, col, pim);
165 safePutPixel(-x1 + y, -y1 + x, col, pim);
166 if (d >= 2 * x1) {
167 d = d - 2 * x1 - 1;
168 x1 += 1;
169 } else {
170 if (d <= 2 * (radius - y1)) {
171 d = d + 2 * y1 - 1;
172 y1 -= 1;
173 } else {
174 d = d + 2 * (y1 - x1 - 1);
175 y1 -= 1;
176 x1 += 1;
177 }
178 }
179 }
180 }
181}
182
183// Bresenham algorithm
184template <class Image, class Color>
185void DrawLine(int xa, int ya, int xb, int yb, const Color& col, Image* pim) {
186 Image& im = *pim;
187
188 // If one point is outside the image
189 // Replace the outside point by the intersection of the line and
190 // the limit (either x=width or y=height).
191 if (!im.Contains(ya, xa) || !im.Contains(yb, xb)) {
192 int width = pim->Width();
193 int height = pim->Height();
194 const bool xdir = xa < xb, ydir = ya < yb;
195 float nx0 = xa, nx1 = xb, ny0 = ya, ny1 = yb, &xleft = xdir ? nx0 : nx1,
196 &yleft = xdir ? ny0 : ny1, &xright = xdir ? nx1 : nx0,
197 &yright = xdir ? ny1 : ny0, &xup = ydir ? nx0 : nx1,
198 &yup = ydir ? ny0 : ny1, &xdown = ydir ? nx1 : nx0,
199 &ydown = ydir ? ny1 : ny0;
200
201 if (xright < 0 || xleft >= width) {
202 return;
203 }
204 if (xleft < 0) {
205 yleft -= xleft * (yright - yleft) / (xright - xleft);
206 xleft = 0;
207 }
208 if (xright >= width) {
209 yright -= (xright - width) * (yright - yleft) / (xright - xleft);
210 xright = width - 1;
211 }
212 if (ydown < 0 || yup >= height) {
213 return;
214 }
215 if (yup < 0) {
216 xup -= yup * (xdown - xup) / (ydown - yup);
217 yup = 0;
218 }
219 if (ydown >= height) {
220 xdown -= (ydown - height) * (xdown - xup) / (ydown - yup);
221 ydown = height - 1;
222 }
223
224 xa = (int)xleft;
225 xb = (int)xright;
226 ya = (int)yleft;
227 yb = (int)yright;
228 }
229
230 int xbas, xhaut, ybas, yhaut;
231 // Check the condition ybas < yhaut.
232 if (ya <= yb) {
233 xbas = xa;
234 ybas = ya;
235 xhaut = xb;
236 yhaut = yb;
237 } else {
238 xbas = xb;
239 ybas = yb;
240 xhaut = xa;
241 yhaut = ya;
242 }
243 // Initialize slope.
244 int x, y, dx, dy, incrmX, incrmY, dp, N, S;
245 dx = xhaut - xbas;
246 dy = yhaut - ybas;
247 if (dx > 0) { // If xhaut > xbas we will increment X.
248 incrmX = 1;
249 } else {
250 incrmX = -1; // else we will decrement X.
251 dx *= -1;
252 }
253 if (dy > 0) { // Positive slope will increment X.
254 incrmY = 1;
255 } else { // Negative slope.
256 incrmY = -1;
257 }
258 if (dx >= dy) {
259 dp = 2 * dy - dx;
260 S = 2 * dy;
261 N = 2 * (dy - dx);
262 y = ybas;
263 x = xbas;
264 while (x != xhaut) {
265 safePutPixel(y, x, col, pim);
266 x += incrmX;
267 if (dp <= 0) { // Go in direction of the South Pixel.
268 dp += S;
269 } else { // Go to the North.
270 dp += N;
271 y += incrmY;
272 }
273 }
274 } else {
275 dp = 2 * dx - dy;
276 S = 2 * dx;
277 N = 2 * (dx - dy);
278 x = xbas;
279 y = ybas;
280 while (y < yhaut) {
281 safePutPixel(y, x, col, pim);
282 y += incrmY;
283 if (dp <= 0) { // Go in direction of the South Pixel.
284 dp += S;
285 } else { // Go to the North.
286 dp += N;
287 x += incrmX;
288 }
289 }
290 }
291 safePutPixel(y, x, col, pim);
292}
293
294} // namespace libmv
295
296#endif // LIBMV_IMAGE_IMAGE_DRAWING_H
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
ccl_device_inline float3 cos(float3 v)
#define N
void safePutPixel(int yc, int xc, const Color &col, Image *pim)
void DrawEllipse(int xc, int yc, int radiusA, int radiusB, const Color &col, Image *pim, double angle=0.0)
void DrawLine(int xa, int ya, int xb, int yb, const Color &col, Image *pim)
void DrawCircle(int x, int y, int radius, const Color &col, Image *pim)