Blender  V2.93
COM_AntiAliasOperation.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 "COM_AntiAliasOperation.h"
20 #include "BLI_math.h"
21 #include "BLI_utildefines.h"
22 
23 #include "MEM_guardedalloc.h"
24 
25 #include "RE_texture.h"
26 
27 namespace blender::compositor {
28 
29 /* An implementation of the Scale3X edge-extrapolation algorithm.
30  *
31  * Code from GIMP plugin, based on code from Adam D. Moss <adam@gimp.org>
32  * licensed by the MIT license.
33  */
34 static int extrapolate9(float *E0,
35  float *E1,
36  float *E2,
37  float *E3,
38  float *E4,
39  float *E5,
40  float *E6,
41  float *E7,
42  float *E8,
43  const float *A,
44  const float *B,
45  const float *C,
46  const float *D,
47  const float *E,
48  const float *F,
49  const float *G,
50  const float *H,
51  const float *I)
52 {
53 #define PEQ(X, Y) (fabsf(*X - *Y) < 1e-3f)
54 #define PCPY(DST, SRC) \
55  do { \
56  *DST = *SRC; \
57  } while (0)
58  if ((!PEQ(B, H)) && (!PEQ(D, F))) {
59  if (PEQ(D, B)) {
60  PCPY(E0, D);
61  }
62  else {
63  PCPY(E0, E);
64  }
65  if ((PEQ(D, B) && !PEQ(E, C)) || (PEQ(B, F) && !PEQ(E, A))) {
66  PCPY(E1, B);
67  }
68  else {
69  PCPY(E1, E);
70  }
71  if (PEQ(B, F)) {
72  PCPY(E2, F);
73  }
74  else {
75  PCPY(E2, E);
76  }
77  if ((PEQ(D, B) && !PEQ(E, G)) || (PEQ(D, H) && !PEQ(E, A))) {
78  PCPY(E3, D);
79  }
80  else {
81  PCPY(E3, E);
82  }
83  PCPY(E4, E);
84  if ((PEQ(B, F) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, C))) {
85  PCPY(E5, F);
86  }
87  else {
88  PCPY(E5, E);
89  }
90  if (PEQ(D, H)) {
91  PCPY(E6, D);
92  }
93  else {
94  PCPY(E6, E);
95  }
96  if ((PEQ(D, H) && !PEQ(E, I)) || (PEQ(H, F) && !PEQ(E, G))) {
97  PCPY(E7, H);
98  }
99  else {
100  PCPY(E7, E);
101  }
102  if (PEQ(H, F)) {
103  PCPY(E8, F);
104  }
105  else {
106  PCPY(E8, E);
107  }
108  return 1;
109  }
110 
111  return 0;
112 
113 #undef PEQ
114 #undef PCPY
115 }
116 
118 {
121  this->m_valueReader = nullptr;
122  this->flags.complex = true;
123 }
124 
126 {
127  this->m_valueReader = this->getInputSocketReader(0);
128 }
129 
130 void AntiAliasOperation::executePixel(float output[4], int x, int y, void *data)
131 {
132  MemoryBuffer *input_buffer = (MemoryBuffer *)data;
133  const int buffer_width = input_buffer->getWidth(), buffer_height = input_buffer->getHeight();
134  if (y < 0 || y >= buffer_height || x < 0 || x >= buffer_width) {
135  output[0] = 0.0f;
136  }
137  else {
138  const float *buffer = input_buffer->getBuffer();
139  const float *row_curr = &buffer[y * buffer_width];
140  if (x == 0 || x == buffer_width - 1 || y == 0 || y == buffer_height - 1) {
141  output[0] = row_curr[x];
142  return;
143  }
144  const float *row_prev = &buffer[(y - 1) * buffer_width],
145  *row_next = &buffer[(y + 1) * buffer_width];
146  float ninepix[9];
147  if (extrapolate9(&ninepix[0],
148  &ninepix[1],
149  &ninepix[2],
150  &ninepix[3],
151  &ninepix[4],
152  &ninepix[5],
153  &ninepix[6],
154  &ninepix[7],
155  &ninepix[8],
156  &row_prev[x - 1],
157  &row_prev[x],
158  &row_prev[x + 1],
159  &row_curr[x - 1],
160  &row_curr[x],
161  &row_curr[x + 1],
162  &row_next[x - 1],
163  &row_next[x],
164  &row_next[x + 1])) {
165  /* Some rounding magic to so make weighting correct with the
166  * original coefficients.
167  */
168  unsigned char result = ((3 * ninepix[0] + 5 * ninepix[1] + 3 * ninepix[2] + 5 * ninepix[3] +
169  6 * ninepix[4] + 5 * ninepix[5] + 3 * ninepix[6] + 5 * ninepix[7] +
170  3 * ninepix[8]) *
171  255.0f +
172  19.0f) /
173  38.0f;
174  output[0] = result / 255.0f;
175  }
176  else {
177  output[0] = row_curr[x];
178  }
179  }
180 }
181 
183 {
184  this->m_valueReader = nullptr;
185 }
186 
188  ReadBufferOperation *readOperation,
189  rcti *output)
190 {
191  rcti imageInput;
192  NodeOperation *operation = getInputOperation(0);
193  imageInput.xmax = input->xmax + 1;
194  imageInput.xmin = input->xmin - 1;
195  imageInput.ymax = input->ymax + 1;
196  imageInput.ymin = input->ymin - 1;
197  return operation->determineDependingAreaOfInterest(&imageInput, readOperation, output);
198 }
199 
201 {
202  return getInputOperation(0)->initializeTileData(rect);
203 }
204 
205 } // namespace blender::compositor
#define D
#define PEQ(X, Y)
#define PCPY(DST, SRC)
_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 C
Definition: RandGen.cpp:39
#define A
#define output
void executePixel(float output[4], int x, int y, void *data) override
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) override
SocketReader * m_valueReader
Cached reference to the reader.
a MemoryBuffer contains access to the data of a chunk
const int getHeight() const
get the height of this MemoryBuffer
const int getWidth() const
get the width of this MemoryBuffer
float * getBuffer()
get the data of this MemoryBuffer
NodeOperation contains calculation logic.
virtual void * initializeTileData(rcti *)
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
NodeOperation * getInputOperation(unsigned int inputSocketindex)
void addOutputSocket(DataType datatype)
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
virtual bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
#define B
#define F
static int extrapolate9(float *E0, float *E1, float *E2, float *E3, float *E4, float *E5, float *E6, float *E7, float *E8, const float *A, const float *B, const float *C, const float *D, const float *E, const float *F, const float *G, const float *H, const float *I)
#define I
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
#define G(x, y, z)
#define H(x, y, z)