Blender V4.3
filter.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cmath>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_math_base.h"
14#include "BLI_utildefines.h"
15
16#include "IMB_filter.hh"
17#include "IMB_imbuf.hh"
18#include "IMB_imbuf_types.hh"
19
20#include "imbuf.hh"
21
22static void filtcolum(uchar *point, int y, int skip)
23{
24 uint c1, c2, c3, error;
25 uchar *point2;
26
27 if (y > 1) {
28 c1 = c2 = *point;
29 point2 = point;
30 error = 2;
31 for (y--; y > 0; y--) {
32 point2 += skip;
33 c3 = *point2;
34 c1 += (c2 << 1) + c3 + error;
35 error = c1 & 3;
36 *point = c1 >> 2;
37 point = point2;
38 c1 = c2;
39 c2 = c3;
40 }
41 *point = (c1 + (c2 << 1) + c2 + error) >> 2;
42 }
43}
44
45static void filtcolumf(float *point, int y, int skip)
46{
47 float c1, c2, c3, *point2;
48
49 if (y > 1) {
50 c1 = c2 = *point;
51 point2 = point;
52 for (y--; y > 0; y--) {
53 point2 += skip;
54 c3 = *point2;
55 c1 += (c2 * 2) + c3;
56 *point = 0.25f * c1;
57 point = point2;
58 c1 = c2;
59 c2 = c3;
60 }
61 *point = 0.25f * (c1 + (c2 * 2) + c2);
62 }
63}
64
65void IMB_filtery(ImBuf *ibuf)
66{
67 uchar *point = ibuf->byte_buffer.data;
68 float *pointf = ibuf->float_buffer.data;
69
70 int x = ibuf->x;
71 int y = ibuf->y;
72 int skip = x << 2;
73
74 for (; x > 0; x--) {
75 if (point) {
76 if (ibuf->planes > 24) {
77 filtcolum(point, y, skip);
78 }
79 point++;
80 filtcolum(point, y, skip);
81 point++;
82 filtcolum(point, y, skip);
83 point++;
84 filtcolum(point, y, skip);
85 point++;
86 }
87 if (pointf) {
88 if (ibuf->planes > 24) {
89 filtcolumf(pointf, y, skip);
90 }
91 pointf++;
92 filtcolumf(pointf, y, skip);
93 pointf++;
94 filtcolumf(pointf, y, skip);
95 pointf++;
96 filtcolumf(pointf, y, skip);
97 pointf++;
98 }
99 }
100}
101
102static void imb_filterN(ImBuf *out, ImBuf *in)
103{
104 BLI_assert(out->channels == in->channels);
105 BLI_assert(out->x == in->x && out->y == in->y);
106
107 const int channels = in->channels;
108 const int rowlen = in->x;
109
110 if (in->byte_buffer.data && out->byte_buffer.data) {
111 for (int y = 0; y < in->y; y++) {
112 /* setup rows */
113 const char *row2 = (const char *)in->byte_buffer.data + y * channels * rowlen;
114 const char *row1 = (y == 0) ? row2 : row2 - channels * rowlen;
115 const char *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen;
116
117 char *cp = (char *)out->byte_buffer.data + y * channels * rowlen;
118
119 for (int x = 0; x < rowlen; x++) {
120 const char *r11, *r13, *r21, *r23, *r31, *r33;
121
122 if (x == 0) {
123 r11 = row1;
124 r21 = row2;
125 r31 = row3;
126 }
127 else {
128 r11 = row1 - channels;
129 r21 = row2 - channels;
130 r31 = row3 - channels;
131 }
132
133 if (x == rowlen - 1) {
134 r13 = row1;
135 r23 = row2;
136 r33 = row3;
137 }
138 else {
139 r13 = row1 + channels;
140 r23 = row2 + channels;
141 r33 = row3 + channels;
142 }
143
144 cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] +
145 2 * row3[0] + r33[0]) >>
146 4;
147 cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] +
148 2 * row3[1] + r33[1]) >>
149 4;
150 cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] +
151 2 * row3[2] + r33[2]) >>
152 4;
153 cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] +
154 2 * row3[3] + r33[3]) >>
155 4;
156 cp += channels;
157 row1 += channels;
158 row2 += channels;
159 row3 += channels;
160 }
161 }
162 }
163
164 if (in->float_buffer.data && out->float_buffer.data) {
165 for (int y = 0; y < in->y; y++) {
166 /* setup rows */
167 const float *row2 = (const float *)in->float_buffer.data + y * channels * rowlen;
168 const float *row1 = (y == 0) ? row2 : row2 - channels * rowlen;
169 const float *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen;
170
171 float *cp = (float *)out->float_buffer.data + y * channels * rowlen;
172
173 for (int x = 0; x < rowlen; x++) {
174 const float *r11, *r13, *r21, *r23, *r31, *r33;
175
176 if (x == 0) {
177 r11 = row1;
178 r21 = row2;
179 r31 = row3;
180 }
181 else {
182 r11 = row1 - channels;
183 r21 = row2 - channels;
184 r31 = row3 - channels;
185 }
186
187 if (x == rowlen - 1) {
188 r13 = row1;
189 r23 = row2;
190 r33 = row3;
191 }
192 else {
193 r13 = row1 + channels;
194 r23 = row2 + channels;
195 r33 = row3 + channels;
196 }
197
198 cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] +
199 2 * row3[0] + r33[0]) *
200 (1.0f / 16.0f);
201 cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] +
202 2 * row3[1] + r33[1]) *
203 (1.0f / 16.0f);
204 cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] +
205 2 * row3[2] + r33[2]) *
206 (1.0f / 16.0f);
207 cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] +
208 2 * row3[3] + r33[3]) *
209 (1.0f / 16.0f);
210 cp += channels;
211 row1 += channels;
212 row2 += channels;
213 row3 += channels;
214 }
215 }
216 }
217}
218
219void IMB_mask_filter_extend(char *mask, int width, int height)
220{
221 const char *row1, *row2, *row3;
222 int rowlen, x, y;
223 char *temprect;
224
225 rowlen = width;
226
227 /* make a copy, to prevent flooding */
228 temprect = static_cast<char *>(MEM_dupallocN(mask));
229
230 for (y = 1; y <= height; y++) {
231 /* setup rows */
232 row1 = (char *)(temprect + (y - 2) * rowlen);
233 row2 = row1 + rowlen;
234 row3 = row2 + rowlen;
235 if (y == 1) {
236 row1 = row2;
237 }
238 else if (y == height) {
239 row3 = row2;
240 }
241
242 for (x = 0; x < rowlen; x++) {
243 if (mask[((y - 1) * rowlen) + x] == 0) {
244 if (*row1 || *row2 || *row3 || *(row1 + 1) || *(row3 + 1)) {
245 mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN;
246 }
247 else if ((x != rowlen - 1) && (*(row1 + 2) || *(row2 + 2) || *(row3 + 2))) {
248 mask[((y - 1) * rowlen) + x] = FILTER_MASK_MARGIN;
249 }
250 }
251
252 if (x != 0) {
253 row1++;
254 row2++;
255 row3++;
256 }
257 }
258 }
259
260 MEM_freeN(temprect);
261}
262
263void IMB_mask_clear(ImBuf *ibuf, const char *mask, int val)
264{
265 int x, y;
266 if (ibuf->float_buffer.data) {
267 for (x = 0; x < ibuf->x; x++) {
268 for (y = 0; y < ibuf->y; y++) {
269 if (mask[ibuf->x * y + x] == val) {
270 float *col = ibuf->float_buffer.data + 4 * (ibuf->x * y + x);
271 col[0] = col[1] = col[2] = col[3] = 0.0f;
272 }
273 }
274 }
275 }
276 else {
277 /* char buffer */
278 for (x = 0; x < ibuf->x; x++) {
279 for (y = 0; y < ibuf->y; y++) {
280 if (mask[ibuf->x * y + x] == val) {
281 char *col = (char *)(ibuf->byte_buffer.data + 4 * ibuf->x * y + x);
282 col[0] = col[1] = col[2] = col[3] = 0;
283 }
284 }
285 }
286 }
287}
288
289static int filter_make_index(const int x, const int y, const int w, const int h)
290{
291 if (x < 0 || x >= w || y < 0 || y >= h) {
292 return -1; /* return bad index */
293 }
294
295 return y * w + x;
296}
297
299 const void *buffer, const char *mask, const int index, const int depth, const bool is_float)
300{
301 int res = 0;
302
303 if (index >= 0) {
304 const int alpha_index = depth * index + (depth - 1);
305
306 if (mask != nullptr) {
307 res = mask[index] != 0 ? 1 : 0;
308 }
309 else if ((is_float && ((const float *)buffer)[alpha_index] != 0.0f) ||
310 (!is_float && ((const uchar *)buffer)[alpha_index] != 0))
311 {
312 res = 1;
313 }
314 }
315
316 return res;
317}
318
319void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter)
320{
321 const int width = ibuf->x;
322 const int height = ibuf->y;
323 const int depth = 4; /* always 4 channels */
324 const int chsize = ibuf->float_buffer.data ? sizeof(float) : sizeof(uchar);
325 const size_t bsize = size_t(width) * height * depth * chsize;
326 const bool is_float = (ibuf->float_buffer.data != nullptr);
327 void *dstbuf = MEM_dupallocN(ibuf->float_buffer.data ? (void *)ibuf->float_buffer.data :
328 (void *)ibuf->byte_buffer.data);
329 char *dstmask = mask == nullptr ? nullptr : (char *)MEM_dupallocN(mask);
330 void *srcbuf = ibuf->float_buffer.data ? (void *)ibuf->float_buffer.data :
331 (void *)ibuf->byte_buffer.data;
332 char *srcmask = mask;
333 int cannot_early_out = 1, r, n, k, i, j, c;
334 float weight[25];
335
336 /* build a weights buffer */
337 n = 1;
338
339#if 0
340 k = 0;
341 for (i = -n; i <= n; i++) {
342 for (j = -n; j <= n; j++) {
343 weight[k++] = sqrt(float(i) * i + j * j);
344 }
345 }
346#endif
347
348 weight[0] = 1;
349 weight[1] = 2;
350 weight[2] = 1;
351 weight[3] = 2;
352 weight[4] = 0;
353 weight[5] = 2;
354 weight[6] = 1;
355 weight[7] = 2;
356 weight[8] = 1;
357
358 /* run passes */
359 for (r = 0; cannot_early_out == 1 && r < filter; r++) {
360 int x, y;
361 cannot_early_out = 0;
362
363 for (y = 0; y < height; y++) {
364 for (x = 0; x < width; x++) {
365 const int index = filter_make_index(x, y, width, height);
366
367 /* only update unassigned pixels */
368 if (!check_pixel_assigned(srcbuf, srcmask, index, depth, is_float)) {
369 float tmp[4];
370 float wsum = 0;
371 float acc[4] = {0, 0, 0, 0};
372 k = 0;
373
375 srcbuf, srcmask, filter_make_index(x - 1, y, width, height), depth, is_float) ||
377 srcbuf, srcmask, filter_make_index(x + 1, y, width, height), depth, is_float) ||
379 srcbuf, srcmask, filter_make_index(x, y - 1, width, height), depth, is_float) ||
381 srcbuf, srcmask, filter_make_index(x, y + 1, width, height), depth, is_float))
382 {
383 for (i = -n; i <= n; i++) {
384 for (j = -n; j <= n; j++) {
385 if (i != 0 || j != 0) {
386 const int tmpindex = filter_make_index(x + i, y + j, width, height);
387
388 if (check_pixel_assigned(srcbuf, srcmask, tmpindex, depth, is_float)) {
389 if (is_float) {
390 for (c = 0; c < depth; c++) {
391 tmp[c] = ((const float *)srcbuf)[depth * tmpindex + c];
392 }
393 }
394 else {
395 for (c = 0; c < depth; c++) {
396 tmp[c] = float(((const uchar *)srcbuf)[depth * tmpindex + c]);
397 }
398 }
399
400 wsum += weight[k];
401
402 for (c = 0; c < depth; c++) {
403 acc[c] += weight[k] * tmp[c];
404 }
405 }
406 }
407 k++;
408 }
409 }
410
411 if (wsum != 0) {
412 for (c = 0; c < depth; c++) {
413 acc[c] /= wsum;
414 }
415
416 if (is_float) {
417 for (c = 0; c < depth; c++) {
418 ((float *)dstbuf)[depth * index + c] = acc[c];
419 }
420 }
421 else {
422 for (c = 0; c < depth; c++) {
423 ((uchar *)dstbuf)[depth * index + c] = acc[c] > 255 ?
424 255 :
425 (acc[c] < 0 ? 0 :
426 uchar(roundf(acc[c])));
427 }
428 }
429
430 if (dstmask != nullptr) {
431 dstmask[index] = FILTER_MASK_MARGIN; /* assigned */
432 }
433 cannot_early_out = 1;
434 }
435 }
436 }
437 }
438 }
439
440 /* keep the original buffer up to date. */
441 memcpy(srcbuf, dstbuf, bsize);
442 if (dstmask != nullptr) {
443 memcpy(srcmask, dstmask, size_t(width) * height);
444 }
445 }
446
447 /* free memory */
448 MEM_freeN(dstbuf);
449 if (dstmask != nullptr) {
450 MEM_freeN(dstmask);
451 }
452}
453
454void IMB_remakemipmap(ImBuf *ibuf, int use_filter)
455{
456 ImBuf *hbuf = ibuf;
457 int curmap = 0;
458
459 ibuf->miptot = 1;
460
461 while (curmap < IMB_MIPMAP_LEVELS) {
462
463 if (ibuf->mipmap[curmap]) {
464
465 if (use_filter) {
466 ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags);
467 imb_filterN(nbuf, hbuf);
468 imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf);
469 IMB_freeImBuf(nbuf);
470 }
471 else {
472 imb_onehalf_no_alloc(ibuf->mipmap[curmap], hbuf);
473 }
474 }
475
476 ibuf->miptot = curmap + 2;
477 hbuf = ibuf->mipmap[curmap];
478 if (hbuf) {
479 hbuf->miplevel = curmap + 1;
480 }
481
482 if (!hbuf || (hbuf->x <= 2 && hbuf->y <= 2)) {
483 break;
484 }
485
486 curmap++;
487 }
488}
489
490void IMB_makemipmap(ImBuf *ibuf, int use_filter)
491{
492 ImBuf *hbuf = ibuf;
493 int curmap = 0;
494
496
497 /* no mipmap for non RGBA images */
498 if (ibuf->float_buffer.data && ibuf->channels < 4) {
499 return;
500 }
501
502 ibuf->miptot = 1;
503
504 while (curmap < IMB_MIPMAP_LEVELS) {
505 if (use_filter) {
506 ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags);
507 imb_filterN(nbuf, hbuf);
508 ibuf->mipmap[curmap] = IMB_onehalf(nbuf);
509 IMB_freeImBuf(nbuf);
510 }
511 else {
512 ibuf->mipmap[curmap] = IMB_onehalf(hbuf);
513 }
514
515 ibuf->miptot = curmap + 2;
516 hbuf = ibuf->mipmap[curmap];
517 hbuf->miplevel = curmap + 1;
518
519 if (hbuf->x < 2 && hbuf->y < 2) {
520 break;
521 }
522
523 curmap++;
524 }
525}
526
527ImBuf *IMB_getmipmap(ImBuf *ibuf, int level)
528{
529 CLAMP(level, 0, ibuf->miptot - 1);
530 return (level == 0) ? ibuf : ibuf->mipmap[level - 1];
531}
532
533void IMB_premultiply_rect(uint8_t *rect, char planes, int w, int h)
534{
535 uint8_t *cp;
536 int x, y, val;
537
538 if (planes == 24) { /* put alpha at 255 */
539 cp = rect;
540
541 for (y = 0; y < h; y++) {
542 for (x = 0; x < w; x++, cp += 4) {
543 cp[3] = 255;
544 }
545 }
546 }
547 else {
548 cp = rect;
549
550 for (y = 0; y < h; y++) {
551 for (x = 0; x < w; x++, cp += 4) {
552 val = cp[3];
553 cp[0] = (cp[0] * val) >> 8;
554 cp[1] = (cp[1] * val) >> 8;
555 cp[2] = (cp[2] * val) >> 8;
556 }
557 }
558 }
559}
560
561void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h)
562{
563 float val, *cp;
564 int x, y;
565
566 if (channels == 4) {
567 cp = rect_float;
568 for (y = 0; y < h; y++) {
569 for (x = 0; x < w; x++, cp += 4) {
570 val = cp[3];
571 cp[0] = cp[0] * val;
572 cp[1] = cp[1] * val;
573 cp[2] = cp[2] * val;
574 }
575 }
576 }
577}
578
580{
581 if (ibuf == nullptr) {
582 return;
583 }
584
585 if (ibuf->byte_buffer.data) {
586 IMB_premultiply_rect(ibuf->byte_buffer.data, ibuf->planes, ibuf->x, ibuf->y);
587 }
588
589 if (ibuf->float_buffer.data) {
590 IMB_premultiply_rect_float(ibuf->float_buffer.data, ibuf->channels, ibuf->x, ibuf->y);
591 }
592}
593
594void IMB_unpremultiply_rect(uint8_t *rect, char planes, int w, int h)
595{
596 uchar *cp;
597 int x, y;
598 float val;
599
600 if (planes == 24) { /* put alpha at 255 */
601 cp = rect;
602
603 for (y = 0; y < h; y++) {
604 for (x = 0; x < w; x++, cp += 4) {
605 cp[3] = 255;
606 }
607 }
608 }
609 else {
610 cp = rect;
611
612 for (y = 0; y < h; y++) {
613 for (x = 0; x < w; x++, cp += 4) {
614 val = cp[3] != 0 ? 1.0f / float(cp[3]) : 1.0f;
615 cp[0] = unit_float_to_uchar_clamp(cp[0] * val);
616 cp[1] = unit_float_to_uchar_clamp(cp[1] * val);
617 cp[2] = unit_float_to_uchar_clamp(cp[2] * val);
618 }
619 }
620 }
621}
622
623void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h)
624{
625 float val, *fp;
626 int x, y;
627
628 if (channels == 4) {
629 fp = rect_float;
630 for (y = 0; y < h; y++) {
631 for (x = 0; x < w; x++, fp += 4) {
632 val = fp[3] != 0.0f ? 1.0f / fp[3] : 1.0f;
633 fp[0] = fp[0] * val;
634 fp[1] = fp[1] * val;
635 fp[2] = fp[2] * val;
636 }
637 }
638 }
639}
640
642{
643 if (ibuf == nullptr) {
644 return;
645 }
646
647 if (ibuf->byte_buffer.data) {
648 IMB_unpremultiply_rect(ibuf->byte_buffer.data, ibuf->planes, ibuf->x, ibuf->y);
649 }
650
651 if (ibuf->float_buffer.data) {
652 IMB_unpremultiply_rect_float(ibuf->float_buffer.data, ibuf->channels, ibuf->x, ibuf->y);
653 }
654}
#define BLI_assert(a)
Definition BLI_assert.h:50
sqrt(x)+1/max(0
unsigned char uchar
unsigned int uint
#define CLAMP(a, b, c)
Function declarations for filter.cc.
void imb_onehalf_no_alloc(ImBuf *ibuf2, ImBuf *ibuf1)
Definition scaling.cc:236
ImBuf * IMB_onehalf(ImBuf *ibuf1)
Definition scaling.cc:314
void imb_freemipmapImBuf(ImBuf *ibuf)
#define FILTER_MASK_MARGIN
Definition IMB_imbuf.hh:377
Contains defines and structs used throughout the imbuf module.
#define IMB_MIPMAP_LEVELS
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
draw_view in_light_buf[] float
void IMB_premultiply_alpha(ImBuf *ibuf)
Definition filter.cc:579
void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h)
Definition filter.cc:623
void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h)
Definition filter.cc:561
void IMB_mask_filter_extend(char *mask, int width, int height)
Definition filter.cc:219
void IMB_makemipmap(ImBuf *ibuf, int use_filter)
Definition filter.cc:490
static void imb_filterN(ImBuf *out, ImBuf *in)
Definition filter.cc:102
void IMB_remakemipmap(ImBuf *ibuf, int use_filter)
Definition filter.cc:454
void IMB_unpremultiply_alpha(ImBuf *ibuf)
Definition filter.cc:641
static void filtcolumf(float *point, int y, int skip)
Definition filter.cc:45
void IMB_mask_clear(ImBuf *ibuf, const char *mask, int val)
Definition filter.cc:263
static void filtcolum(uchar *point, int y, int skip)
Definition filter.cc:22
void IMB_filtery(ImBuf *ibuf)
Definition filter.cc:65
void IMB_unpremultiply_rect(uint8_t *rect, char planes, int w, int h)
Definition filter.cc:594
void IMB_premultiply_rect(uint8_t *rect, char planes, int w, int h)
Definition filter.cc:533
void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter)
Definition filter.cc:319
ImBuf * IMB_getmipmap(ImBuf *ibuf, int level)
Definition filter.cc:527
static int filter_make_index(const int x, const int y, const int w, const int h)
Definition filter.cc:289
static int check_pixel_assigned(const void *buffer, const char *mask, const int index, const int depth, const bool is_float)
Definition filter.cc:298
uint col
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
void IMB_freeImBuf(ImBuf *)
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
#define unit_float_to_uchar_clamp(val)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static void error(const char *str)
unsigned char uint8_t
Definition stdint.h:78
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
unsigned char planes
ImBuf * mipmap[IMB_MIPMAP_LEVELS]