Blender  V2.93
COM_InpaintOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18 
19 #include "MEM_guardedalloc.h"
20 
21 #include "COM_InpaintOperation.h"
22 #include "COM_OpenCLDevice.h"
23 
24 #include "BLI_math.h"
25 
26 namespace blender::compositor {
27 
28 #define ASSERT_XY_RANGE(x, y) \
29  BLI_assert(x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight())
30 
31 // Inpaint (simple convolve using average of known pixels)
33 {
36  this->flags.complex = true;
37  this->m_inputImageProgram = nullptr;
38  this->m_pixelorder = nullptr;
39  this->m_manhattan_distance = nullptr;
40  this->m_cached_buffer = nullptr;
41  this->m_cached_buffer_ready = false;
42 }
44 {
46 
47  this->m_pixelorder = nullptr;
48  this->m_manhattan_distance = nullptr;
49  this->m_cached_buffer = nullptr;
50  this->m_cached_buffer_ready = false;
51 
52  this->initMutex();
53 }
54 
55 void InpaintSimpleOperation::clamp_xy(int &x, int &y)
56 {
57  int width = this->getWidth();
58  int height = this->getHeight();
59 
60  if (x < 0) {
61  x = 0;
62  }
63  else if (x >= width) {
64  x = width - 1;
65  }
66 
67  if (y < 0) {
68  y = 0;
69  }
70  else if (y >= height) {
71  y = height - 1;
72  }
73 }
74 
75 float *InpaintSimpleOperation::get_pixel(int x, int y)
76 {
77  int width = this->getWidth();
78 
79  ASSERT_XY_RANGE(x, y);
80 
83 }
84 
85 int InpaintSimpleOperation::mdist(int x, int y)
86 {
87  int width = this->getWidth();
88 
89  ASSERT_XY_RANGE(x, y);
90 
91  return this->m_manhattan_distance[y * width + x];
92 }
93 
94 bool InpaintSimpleOperation::next_pixel(int &x, int &y, int &curr, int iters)
95 {
96  int width = this->getWidth();
97 
98  if (curr >= this->m_area_size) {
99  return false;
100  }
101 
102  int r = this->m_pixelorder[curr++];
103 
104  x = r % width;
105  y = r / width;
106 
107  if (this->mdist(x, y) > iters) {
108  return false;
109  }
110 
111  return true;
112 }
113 
114 void InpaintSimpleOperation::calc_manhattan_distance()
115 {
116  int width = this->getWidth();
117  int height = this->getHeight();
118  short *m = this->m_manhattan_distance = (short *)MEM_mallocN(sizeof(short) * width * height,
119  __func__);
120  int *offsets;
121 
122  offsets = (int *)MEM_callocN(sizeof(int) * (width + height + 1),
123  "InpaintSimpleOperation offsets");
124 
125  for (int j = 0; j < height; j++) {
126  for (int i = 0; i < width; i++) {
127  int r = 0;
128  /* no need to clamp here */
129  if (this->get_pixel(i, j)[3] < 1.0f) {
130  r = width + height;
131  if (i > 0) {
132  r = min_ii(r, m[j * width + i - 1] + 1);
133  }
134  if (j > 0) {
135  r = min_ii(r, m[(j - 1) * width + i] + 1);
136  }
137  }
138  m[j * width + i] = r;
139  }
140  }
141 
142  for (int j = height - 1; j >= 0; j--) {
143  for (int i = width - 1; i >= 0; i--) {
144  int r = m[j * width + i];
145 
146  if (i + 1 < width) {
147  r = min_ii(r, m[j * width + i + 1] + 1);
148  }
149  if (j + 1 < height) {
150  r = min_ii(r, m[(j + 1) * width + i] + 1);
151  }
152 
153  m[j * width + i] = r;
154 
155  offsets[r]++;
156  }
157  }
158 
159  offsets[0] = 0;
160 
161  for (int i = 1; i < width + height + 1; i++) {
162  offsets[i] += offsets[i - 1];
163  }
164 
165  this->m_area_size = offsets[width + height];
166  this->m_pixelorder = (int *)MEM_mallocN(sizeof(int) * this->m_area_size, __func__);
167 
168  for (int i = 0; i < width * height; i++) {
169  if (m[i] > 0) {
170  this->m_pixelorder[offsets[m[i] - 1]++] = i;
171  }
172  }
173 
174  MEM_freeN(offsets);
175 }
176 
177 void InpaintSimpleOperation::pix_step(int x, int y)
178 {
179  const int d = this->mdist(x, y);
180  float pix[3] = {0.0f, 0.0f, 0.0f};
181  float pix_divider = 0.0f;
182 
183  for (int dx = -1; dx <= 1; dx++) {
184  for (int dy = -1; dy <= 1; dy++) {
185  /* changing to both != 0 gives dithering artifacts */
186  if (dx != 0 || dy != 0) {
187  int x_ofs = x + dx;
188  int y_ofs = y + dy;
189 
190  this->clamp_xy(x_ofs, y_ofs);
191 
192  if (this->mdist(x_ofs, y_ofs) < d) {
193 
194  float weight;
195 
196  if (dx == 0 || dy == 0) {
197  weight = 1.0f;
198  }
199  else {
200  weight = M_SQRT1_2; /* 1.0f / sqrt(2) */
201  }
202 
203  madd_v3_v3fl(pix, this->get_pixel(x_ofs, y_ofs), weight);
204  pix_divider += weight;
205  }
206  }
207  }
208  }
209 
210  float *output = this->get_pixel(x, y);
211  if (pix_divider != 0.0f) {
212  mul_v3_fl(pix, 1.0f / pix_divider);
213  /* use existing pixels alpha to blend into */
214  interp_v3_v3v3(output, pix, output, output[3]);
215  output[3] = 1.0f;
216  }
217 }
218 
220 {
221  if (this->m_cached_buffer_ready) {
222  return this->m_cached_buffer;
223  }
224  lockMutex();
225  if (!this->m_cached_buffer_ready) {
227  this->m_cached_buffer = (float *)MEM_dupallocN(buf->getBuffer());
228 
229  this->calc_manhattan_distance();
230 
231  int curr = 0;
232  int x, y;
233 
234  while (this->next_pixel(x, y, curr, this->m_iterations)) {
235  this->pix_step(x, y);
236  }
237  this->m_cached_buffer_ready = true;
238  }
239 
240  unlockMutex();
241  return this->m_cached_buffer;
242 }
243 
244 void InpaintSimpleOperation::executePixel(float output[4], int x, int y, void * /*data*/)
245 {
246  this->clamp_xy(x, y);
247  copy_v4_v4(output, this->get_pixel(x, y));
248 }
249 
251 {
252  this->m_inputImageProgram = nullptr;
253  this->deinitMutex();
254  if (this->m_cached_buffer) {
255  MEM_freeN(this->m_cached_buffer);
256  this->m_cached_buffer = nullptr;
257  }
258 
259  if (this->m_pixelorder) {
260  MEM_freeN(this->m_pixelorder);
261  this->m_pixelorder = nullptr;
262  }
263 
264  if (this->m_manhattan_distance) {
266  this->m_manhattan_distance = nullptr;
267  }
268  this->m_cached_buffer_ready = false;
269 }
270 
272  ReadBufferOperation *readOperation,
273  rcti *output)
274 {
275  if (this->m_cached_buffer_ready) {
276  return false;
277  }
278 
279  rcti newInput;
280 
281  newInput.xmax = getWidth();
282  newInput.xmin = 0;
283  newInput.ymax = getHeight();
284  newInput.ymin = 0;
285 
286  return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
287 }
288 
289 } // namespace blender::compositor
MINLINE int min_ii(int a, int b)
#define M_SQRT1_2
Definition: BLI_math_base.h:50
MINLINE void copy_v4_v4(float r[4], const float a[4])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void mul_v3_fl(float r[3], float f)
#define ASSERT_XY_RANGE(x, y)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
#define output
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override
void executePixel(float output[4], int x, int y, void *data) override
a MemoryBuffer contains access to the data of a chunk
float * getBuffer()
get the data of this MemoryBuffer
virtual void * initializeTileData(rcti *)
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void addOutputSocket(DataType datatype)
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
constexpr int COM_DATA_TYPE_COLOR_CHANNELS
Definition: COM_defines.h:53
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79