Blender V5.0
texture_image.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
8
9#include <algorithm>
10#include <cfloat>
11#include <cmath>
12#include <cstring>
13#include <fcntl.h>
14#ifndef WIN32
15# include <unistd.h>
16#else
17# include <io.h>
18#endif
19
20#include "IMB_imbuf.hh"
21#include "IMB_imbuf_types.hh"
22
23#include "DNA_image_types.h"
24#include "DNA_texture_types.h"
25
26#include "BLI_math_interp.hh"
27#include "BLI_math_vector.h"
28#include "BLI_rect.h"
29#include "BLI_threads.h"
30#include "BLI_utildefines.h"
31
32#include "BKE_image.hh"
33
34#include "RE_texture.h"
35
36#include "texture_common.h"
37
38static void boxsample(ImBuf *ibuf,
39 float minx,
40 float miny,
41 float maxx,
42 float maxy,
43 TexResult *texres,
44 const short imaprepeat,
45 const short imapextend);
46
47/* *********** IMAGEWRAPPING ****************** */
48
49/* x and y have to be checked for image size */
50static void ibuf_get_color(float col[4], ImBuf *ibuf, int x, int y)
51{
52 const int64_t ofs = int64_t(y) * ibuf->x + x;
53
54 if (ibuf->float_buffer.data) {
55 if (ibuf->channels == 4) {
56 const float *fp = ibuf->float_buffer.data + 4 * ofs;
57 copy_v4_v4(col, fp);
58 }
59 else if (ibuf->channels == 3) {
60 const float *fp = ibuf->float_buffer.data + 3 * ofs;
61 copy_v3_v3(col, fp);
62 col[3] = 1.0f;
63 }
64 else {
65 const float *fp = ibuf->float_buffer.data + ofs;
66 col[0] = col[1] = col[2] = col[3] = *fp;
67 }
68 }
69 else {
70 const uchar *rect = ibuf->byte_buffer.data + 4 * ofs;
71
72 col[0] = float(rect[0]) * (1.0f / 255.0f);
73 col[1] = float(rect[1]) * (1.0f / 255.0f);
74 col[2] = float(rect[2]) * (1.0f / 255.0f);
75 col[3] = float(rect[3]) * (1.0f / 255.0f);
76
77 /* Bytes are internally straight, however render pipeline seems to expect pre-multiplied. */
78 col[0] *= col[3];
79 col[1] *= col[3];
80 col[2] *= col[3];
81 }
82}
83
84int imagewrap(Tex *tex,
85 Image *ima,
86 const float texvec[3],
87 TexResult *texres,
88 ImagePool *pool,
89 const bool skip_load_image)
90{
91 float fx, fy;
92 int x, y, retval;
93 int xi, yi; /* original values */
94
95 texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f;
96
97 retval = TEX_RGB;
98
99 /* quick tests */
100 if (ima == nullptr) {
101 return retval;
102 }
103
104 /* hack for icon render */
105 if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
106 return retval;
107 }
108
109 ImageUser *iuser = &tex->iuser;
110 ImageUser local_iuser;
111 if (ima->source == IMA_SRC_TILED) {
112 /* tex->iuser might be shared by threads, so create a local copy. */
113 local_iuser = tex->iuser;
114 iuser = &local_iuser;
115
116 float new_uv[2];
117 iuser->tile = BKE_image_get_tile_from_pos(ima, texvec, new_uv, nullptr);
118 fx = new_uv[0];
119 fy = new_uv[1];
120 }
121 else {
122 fx = texvec[0];
123 fy = texvec[1];
124 }
125
126 ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, iuser, pool);
127
129
130 if (ibuf == nullptr || (ibuf->byte_buffer.data == nullptr && ibuf->float_buffer.data == nullptr))
131 {
132 BKE_image_pool_release_ibuf(ima, ibuf, pool);
133 return retval;
134 }
135
136 /* setup mapping */
137 if (tex->imaflag & TEX_IMAROT) {
138 std::swap(fx, fy);
139 }
140
141 if (tex->extend == TEX_CHECKER) {
142 int xs, ys;
143
144 xs = int(floor(fx));
145 ys = int(floor(fy));
146 fx -= xs;
147 fy -= ys;
148
149 if ((tex->flag & TEX_CHECKER_ODD) == 0) {
150 if ((xs + ys) & 1) {
151 /* pass */
152 }
153 else {
154 if (ima) {
155 BKE_image_pool_release_ibuf(ima, ibuf, pool);
156 }
157 return retval;
158 }
159 }
160 if ((tex->flag & TEX_CHECKER_EVEN) == 0) {
161 if ((xs + ys) & 1) {
162 if (ima) {
163 BKE_image_pool_release_ibuf(ima, ibuf, pool);
164 }
165 return retval;
166 }
167 }
168 /* scale around center, (0.5, 0.5) */
169 if (tex->checkerdist < 1.0f) {
170 fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
171 fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
172 }
173 }
174
175 x = xi = int(floorf(fx * ibuf->x));
176 y = yi = int(floorf(fy * ibuf->y));
177
178 if (tex->extend == TEX_CLIPCUBE) {
179 if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || texvec[2] < -1.0f || texvec[2] > 1.0f) {
180 if (ima) {
181 BKE_image_pool_release_ibuf(ima, ibuf, pool);
182 }
183 return retval;
184 }
185 }
186 else if (ELEM(tex->extend, TEX_CLIP, TEX_CHECKER)) {
187 if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y) {
188 if (ima) {
189 BKE_image_pool_release_ibuf(ima, ibuf, pool);
190 }
191 return retval;
192 }
193 }
194 else {
195 if (tex->extend == TEX_EXTEND) {
196 if (x >= ibuf->x) {
197 x = ibuf->x - 1;
198 }
199 else if (x < 0) {
200 x = 0;
201 }
202 }
203 else {
204 x = x % ibuf->x;
205 if (x < 0) {
206 x += ibuf->x;
207 }
208 }
209 if (tex->extend == TEX_EXTEND) {
210 if (y >= ibuf->y) {
211 y = ibuf->y - 1;
212 }
213 else if (y < 0) {
214 y = 0;
215 }
216 }
217 else {
218 y = y % ibuf->y;
219 if (y < 0) {
220 y += ibuf->y;
221 }
222 }
223 }
224
225 /* Keep this before interpolation #29761. */
226 if (ima) {
227 if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
228 if ((tex->imaflag & TEX_CALCALPHA) == 0) {
229 texres->talpha = true;
230 }
231 }
232 }
233
234 /* interpolate */
235 if (tex->imaflag & TEX_INTERPOL) {
236 float filterx, filtery;
237 filterx = (0.5f * tex->filtersize) / ibuf->x;
238 filtery = (0.5f * tex->filtersize) / ibuf->y;
239
240 /* Important that this value is wrapped #27782.
241 * this applies the modifications made by the checks above,
242 * back to the floating point values */
243 fx -= float(xi - x) / float(ibuf->x);
244 fy -= float(yi - y) / float(ibuf->y);
245
246 boxsample(ibuf,
247 fx - filterx,
248 fy - filtery,
249 fx + filterx,
250 fy + filtery,
251 texres,
252 (tex->extend == TEX_REPEAT),
253 (tex->extend == TEX_EXTEND));
254 }
255 else { /* no filtering */
256 ibuf_get_color(texres->trgba, ibuf, x, y);
257 }
258
259 if (texres->talpha) {
260 texres->tin = texres->trgba[3];
261 }
262 else if (tex->imaflag & TEX_CALCALPHA) {
263 texres->trgba[3] = texres->tin = max_fff(texres->trgba[0], texres->trgba[1], texres->trgba[2]);
264 }
265 else {
266 texres->trgba[3] = texres->tin = 1.0;
267 }
268
269 if (tex->flag & TEX_NEGALPHA) {
270 texres->trgba[3] = 1.0f - texres->trgba[3];
271 }
272
273 /* De-pre-multiply, this is being pre-multiplied in #shade_input_do_shade()
274 * do not de-pre-multiply for generated alpha, it is already in straight. */
275 if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
276 fx = 1.0f / texres->trgba[3];
277 texres->trgba[0] *= fx;
278 texres->trgba[1] *= fx;
279 texres->trgba[2] *= fx;
280 }
281
282 if (ima) {
283 BKE_image_pool_release_ibuf(ima, ibuf, pool);
284 }
285
287
288 return retval;
289}
290
291static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
292{
293 rctf *rf, *newrct;
294 short a;
295
296 a = *count;
297 rf = stack;
298 for (; a > 0; a--) {
299 if (rf->xmin < x1) {
300 if (rf->xmax < x1) {
301 rf->xmin += (x2 - x1);
302 rf->xmax += (x2 - x1);
303 }
304 else {
305 rf->xmax = std::min(rf->xmax, x2);
306 newrct = stack + *count;
307 (*count)++;
308
309 newrct->xmax = x2;
310 newrct->xmin = rf->xmin + (x2 - x1);
311 newrct->ymin = rf->ymin;
312 newrct->ymax = rf->ymax;
313
314 if (newrct->xmin == newrct->xmax) {
315 (*count)--;
316 }
317
318 rf->xmin = x1;
319 }
320 }
321 else if (rf->xmax > x2) {
322 if (rf->xmin > x2) {
323 rf->xmin -= (x2 - x1);
324 rf->xmax -= (x2 - x1);
325 }
326 else {
327 rf->xmin = std::max(rf->xmin, x1);
328 newrct = stack + *count;
329 (*count)++;
330
331 newrct->xmin = x1;
332 newrct->xmax = rf->xmax - (x2 - x1);
333 newrct->ymin = rf->ymin;
334 newrct->ymax = rf->ymax;
335
336 if (newrct->xmin == newrct->xmax) {
337 (*count)--;
338 }
339
340 rf->xmax = x2;
341 }
342 }
343 rf++;
344 }
345}
346
347static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
348{
349 rctf *rf, *newrct;
350 short a;
351
352 a = *count;
353 rf = stack;
354 for (; a > 0; a--) {
355 if (rf->ymin < y1) {
356 if (rf->ymax < y1) {
357 rf->ymin += (y2 - y1);
358 rf->ymax += (y2 - y1);
359 }
360 else {
361 rf->ymax = std::min(rf->ymax, y2);
362 newrct = stack + *count;
363 (*count)++;
364
365 newrct->ymax = y2;
366 newrct->ymin = rf->ymin + (y2 - y1);
367 newrct->xmin = rf->xmin;
368 newrct->xmax = rf->xmax;
369
370 if (newrct->ymin == newrct->ymax) {
371 (*count)--;
372 }
373
374 rf->ymin = y1;
375 }
376 }
377 else if (rf->ymax > y2) {
378 if (rf->ymin > y2) {
379 rf->ymin -= (y2 - y1);
380 rf->ymax -= (y2 - y1);
381 }
382 else {
383 rf->ymin = std::max(rf->ymin, y1);
384 newrct = stack + *count;
385 (*count)++;
386
387 newrct->ymin = y1;
388 newrct->ymax = rf->ymax - (y2 - y1);
389 newrct->xmin = rf->xmin;
390 newrct->xmax = rf->xmax;
391
392 if (newrct->ymin == newrct->ymax) {
393 (*count)--;
394 }
395
396 rf->ymax = y2;
397 }
398 }
399 rf++;
400 }
401}
402
403static float square_rctf(const rctf *rf)
404{
405 float x, y;
406
407 x = BLI_rctf_size_x(rf);
408 y = BLI_rctf_size_y(rf);
409 return x * y;
410}
411
412static float clipx_rctf(rctf *rf, float x1, float x2)
413{
414 float size;
415
416 size = BLI_rctf_size_x(rf);
417
418 rf->xmin = std::max(rf->xmin, x1);
419 rf->xmax = std::min(rf->xmax, x2);
420 if (rf->xmin > rf->xmax) {
421 rf->xmin = rf->xmax;
422 return 0.0;
423 }
424 if (size != 0.0f) {
425 return BLI_rctf_size_x(rf) / size;
426 }
427 return 1.0;
428}
429
430static float clipy_rctf(rctf *rf, float y1, float y2)
431{
432 float size;
433
434 size = BLI_rctf_size_y(rf);
435
436 rf->ymin = std::max(rf->ymin, y1);
437 rf->ymax = std::min(rf->ymax, y2);
438
439 if (rf->ymin > rf->ymax) {
440 rf->ymin = rf->ymax;
441 return 0.0;
442 }
443 if (size != 0.0f) {
444 return BLI_rctf_size_y(rf) / size;
445 }
446 return 1.0;
447}
448
449static void boxsampleclip(ImBuf *ibuf, const rctf *rf, TexResult *texres)
450{
451 /* Sample box, is clipped already, and minx etc. have been set at ibuf size.
452 * Enlarge with anti-aliased edges of the pixels. */
453
454 float muly, mulx, div, col[4];
455 int x, y, startx, endx, starty, endy;
456
457 startx = int(floor(rf->xmin));
458 endx = int(floor(rf->xmax));
459 starty = int(floor(rf->ymin));
460 endy = int(floor(rf->ymax));
461
462 startx = std::max(startx, 0);
463 starty = std::max(starty, 0);
464 if (endx >= ibuf->x) {
465 endx = ibuf->x - 1;
466 }
467 if (endy >= ibuf->y) {
468 endy = ibuf->y - 1;
469 }
470
471 if (starty == endy && startx == endx) {
472 ibuf_get_color(texres->trgba, ibuf, startx, starty);
473 }
474 else {
475 div = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = texres->trgba[3] = 0.0;
476 for (y = starty; y <= endy; y++) {
477
478 muly = 1.0;
479
480 if (starty == endy) {
481 /* pass */
482 }
483 else {
484 if (y == starty) {
485 muly = 1.0f - (rf->ymin - y);
486 }
487 if (y == endy) {
488 muly = (rf->ymax - y);
489 }
490 }
491
492 if (startx == endx) {
493 mulx = muly;
494
495 ibuf_get_color(col, ibuf, startx, y);
496 madd_v4_v4fl(texres->trgba, col, mulx);
497 div += mulx;
498 }
499 else {
500 for (x = startx; x <= endx; x++) {
501 mulx = muly;
502 if (x == startx) {
503 mulx *= 1.0f - (rf->xmin - x);
504 }
505 if (x == endx) {
506 mulx *= (rf->xmax - x);
507 }
508
509 ibuf_get_color(col, ibuf, x, y);
510 /* TODO(jbakker): No need to do manual optimization. Branching is slower than multiplying
511 * with 1. */
512 if (mulx == 1.0f) {
513 add_v4_v4(texres->trgba, col);
514 div += 1.0f;
515 }
516 else {
517 madd_v4_v4fl(texres->trgba, col, mulx);
518 div += mulx;
519 }
520 }
521 }
522 }
523
524 if (div != 0.0f) {
525 div = 1.0f / div;
526 mul_v4_fl(texres->trgba, div);
527 }
528 else {
529 zero_v4(texres->trgba);
530 }
531 }
532}
533
534static void boxsample(ImBuf *ibuf,
535 float minx,
536 float miny,
537 float maxx,
538 float maxy,
539 TexResult *texres,
540 const short imaprepeat,
541 const short imapextend)
542{
543 /* Sample box, performs clip. minx etc are in range 0.0 - 1.0 .
544 * Enlarge with anti-aliased edges of pixels.
545 * If variable 'imaprepeat' has been set, the
546 * clipped-away parts are sampled as well.
547 */
548 /* NOTE: actually minx etc isn't in the proper range...
549 * this due to filter size and offset vectors for bump. */
550 /* NOTE: talpha must be initialized. */
551 /* NOTE: even when 'imaprepeat' is set, this can only repeat once in any direction.
552 * the point which min/max is derived from is assumed to be wrapped. */
553 TexResult texr;
554 rctf *rf, stack[8];
555 float opp, tot, alphaclip = 1.0;
556 short count = 1;
557
558 rf = stack;
559 rf->xmin = minx * (ibuf->x);
560 rf->xmax = maxx * (ibuf->x);
561 rf->ymin = miny * (ibuf->y);
562 rf->ymax = maxy * (ibuf->y);
563
564 texr.talpha = texres->talpha; /* is read by boxsample_clip */
565
566 if (imapextend) {
567 CLAMP(rf->xmin, 0.0f, ibuf->x - 1);
568 CLAMP(rf->xmax, 0.0f, ibuf->x - 1);
569 }
570 else if (imaprepeat) {
571 clipx_rctf_swap(stack, &count, 0.0, float(ibuf->x));
572 }
573 else {
574 alphaclip = clipx_rctf(rf, 0.0, float(ibuf->x));
575
576 if (alphaclip <= 0.0f) {
577 texres->trgba[0] = texres->trgba[2] = texres->trgba[1] = texres->trgba[3] = 0.0;
578 return;
579 }
580 }
581
582 if (imapextend) {
583 CLAMP(rf->ymin, 0.0f, ibuf->y - 1);
584 CLAMP(rf->ymax, 0.0f, ibuf->y - 1);
585 }
586 else if (imaprepeat) {
587 clipy_rctf_swap(stack, &count, 0.0, float(ibuf->y));
588 }
589 else {
590 alphaclip *= clipy_rctf(rf, 0.0, float(ibuf->y));
591
592 if (alphaclip <= 0.0f) {
593 texres->trgba[0] = texres->trgba[2] = texres->trgba[1] = texres->trgba[3] = 0.0;
594 return;
595 }
596 }
597
598 if (count > 1) {
599 tot = texres->trgba[0] = texres->trgba[2] = texres->trgba[1] = texres->trgba[3] = 0.0;
600 while (count--) {
601 boxsampleclip(ibuf, rf, &texr);
602
603 opp = square_rctf(rf);
604 tot += opp;
605
606 texres->trgba[0] += opp * texr.trgba[0];
607 texres->trgba[1] += opp * texr.trgba[1];
608 texres->trgba[2] += opp * texr.trgba[2];
609 if (texres->talpha) {
610 texres->trgba[3] += opp * texr.trgba[3];
611 }
612 rf++;
613 }
614 if (tot != 0.0f) {
615 texres->trgba[0] /= tot;
616 texres->trgba[1] /= tot;
617 texres->trgba[2] /= tot;
618 if (texres->talpha) {
619 texres->trgba[3] /= tot;
620 }
621 }
622 }
623 else {
624 boxsampleclip(ibuf, rf, texres);
625 }
626
627 if (texres->talpha == 0) {
628 texres->trgba[3] = 1.0;
629 }
630
631 if (alphaclip != 1.0f) {
632 /* Pre-multiply it all. */
633 texres->trgba[0] *= alphaclip;
634 texres->trgba[1] *= alphaclip;
635 texres->trgba[2] *= alphaclip;
636 texres->trgba[3] *= alphaclip;
637 }
638}
639
640/* -------------------------------------------------------------------- */
641/* from here, some functions only used for the new filtering */
642
643/* anisotropic filters, data struct used instead of long line of (possibly unused) func args */
644struct AFData {
645 float dxt[2], dyt[2];
647};
648
649/* this only used here to make it easier to pass extend flags as single int */
651
656static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)
657{
658 int clip = 0;
659 switch (extflag) {
660 case TXC_XMIR: /* y rep */
661 x %= 2 * ibuf->x;
662 x += x < 0 ? 2 * ibuf->x : 0;
663 x = x >= ibuf->x ? 2 * ibuf->x - x - 1 : x;
664 y %= ibuf->y;
665 y += y < 0 ? ibuf->y : 0;
666 break;
667 case TXC_YMIR: /* x rep */
668 x %= ibuf->x;
669 x += x < 0 ? ibuf->x : 0;
670 y %= 2 * ibuf->y;
671 y += y < 0 ? 2 * ibuf->y : 0;
672 y = y >= ibuf->y ? 2 * ibuf->y - y - 1 : y;
673 break;
674 case TXC_EXTD:
675 x = (x < 0) ? 0 : ((x >= ibuf->x) ? (ibuf->x - 1) : x);
676 y = (y < 0) ? 0 : ((y >= ibuf->y) ? (ibuf->y - 1) : y);
677 break;
678 case TXC_REPT:
679 x %= ibuf->x;
680 x += (x < 0) ? ibuf->x : 0;
681 y %= ibuf->y;
682 y += (y < 0) ? ibuf->y : 0;
683 break;
684 default: { /* as extend, if clipped, set alpha to 0.0 */
685 x = std::max(x, 0); /* TXF alpha: clip = 1; } */
686 if (x >= ibuf->x) {
687 x = ibuf->x - 1;
688 } /* TXF alpha: clip = 1; } */
689 y = std::max(y, 0); /* TXF alpha: clip = 1; } */
690 if (y >= ibuf->y) {
691 y = ibuf->y - 1;
692 } /* TXF alpha: clip = 1; } */
693 }
694 }
695
696 if (ibuf->float_buffer.data) {
697 const float *fp = ibuf->float_buffer.data + (x + int64_t(y) * ibuf->x) * ibuf->channels;
698 if (ibuf->channels == 1) {
699 col[0] = col[1] = col[2] = col[3] = *fp;
700 }
701 else {
702 col[0] = fp[0];
703 col[1] = fp[1];
704 col[2] = fp[2];
705 col[3] = clip ? 0.0f : (ibuf->channels == 4 ? fp[3] : 1.0f);
706 }
707 }
708 else {
709 const uchar *rect = ibuf->byte_buffer.data + 4 * (x + int64_t(y) * ibuf->x);
710 float inv_alpha_fac = (1.0f / 255.0f) * rect[3] * (1.0f / 255.0f);
711 col[0] = rect[0] * inv_alpha_fac;
712 col[1] = rect[1] * inv_alpha_fac;
713 col[2] = rect[2] * inv_alpha_fac;
714 col[3] = clip ? 0.0f : rect[3] * (1.0f / 255.0f);
715 }
716 return clip;
717}
718
721 const AFData *AFD;
722};
723
724static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
725{
726 ReadEWAData *data = (ReadEWAData *)userdata;
727 ibuf_get_color_clip(result, data->ibuf, x, y, data->AFD->extflag);
728}
729
730static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, const AFData *AFD)
731{
733 const float uv[2] = {fx, fy};
734 data.ibuf = ibuf;
735 data.AFD = AFD;
736 BLI_ewa_filter(ibuf->x,
737 ibuf->y,
738 AFD->intpol != 0,
739 texr->talpha,
740 uv,
741 AFD->dxt,
742 AFD->dyt,
744 &data,
745 texr->trgba);
746}
747
748#undef EWA_MAXIDX
749
751 Image *ima, float fx, float fy, float dx, float dy, float result[4], ImagePool *pool)
752{
753 TexResult texres;
754 ImBuf *ibuf = BKE_image_pool_acquire_ibuf(ima, nullptr, pool);
755
756 if (UNLIKELY(ibuf == nullptr)) {
758 return;
759 }
760
761 texres.talpha = true; /* boxsample expects to be initialized */
762 boxsample(ibuf, fx, fy, fx + dx, fy + dy, &texres, 0, 1);
763 copy_v4_v4(result, texres.trgba);
764
766
767 BKE_image_pool_release_ibuf(ima, ibuf, pool);
768}
769
770void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
771{
772 TexResult texres = {0};
773 AFData AFD;
774
775 AFD.dxt[0] = dx;
776 AFD.dxt[1] = dx;
777 AFD.dyt[0] = dy;
778 AFD.dyt[1] = dy;
779 // copy_v2_v2(AFD.dxt, dx);
780 // copy_v2_v2(AFD.dyt, dy);
781
782 AFD.intpol = 1;
783 AFD.extflag = TXC_EXTD;
784
785 ewa_eval(&texres, ibuf, fx, fy, &AFD);
786
787 copy_v4_v4(result, texres.trgba);
788}
int BKE_image_get_tile_from_pos(Image *ima, const float uv[2], float r_uv[2], float r_ofs[2])
ImBuf * BKE_image_pool_acquire_ibuf(Image *ima, ImageUser *iuser, ImagePool *pool)
void BKE_image_pool_release_ibuf(Image *ima, ImBuf *ibuf, ImagePool *pool)
bool BKE_image_has_loaded_ibuf(Image *image)
MINLINE float max_fff(float a, float b, float c)
void BLI_ewa_filter(int width, int height, bool intpol, bool use_alpha, const float uv[2], const float du[2], const float dv[2], ewa_filter_read_pixel_cb read_pixel_cb, void *userdata, float result[4])
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v4(float r[4])
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f)
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:202
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:206
unsigned char uchar
#define CLAMP(a, b, c)
#define UNLIKELY(x)
#define ELEM(...)
@ IMA_SRC_TILED
@ IMA_USED_FOR_RENDER
@ IMA_ALPHA_IGNORE
@ TEX_RGB
@ TEX_CLIP
@ TEX_EXTEND
@ TEX_CHECKER
@ TEX_REPEAT
@ TEX_CLIPCUBE
@ TEX_USEALPHA
@ TEX_CALCALPHA
@ TEX_INTERPOL
@ TEX_IMAROT
@ TEX_CHECKER_EVEN
@ TEX_NEGALPHA
@ TEX_CHECKER_ODD
BMesh const char void * data
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
nullptr float
uint col
#define floor
int count
#define floorf
float dyt[2]
float dxt[2]
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
short source
char alpha_mode
const AFData * AFD
float tin
Definition RE_texture.h:59
float trgba[4]
Definition RE_texture.h:60
short imaflag
float checkerdist
struct ImageUser iuser
short extend
float filtersize
float xmax
float xmin
float ymax
float ymin
#define BRICONTRGB
void image_sample(Image *ima, float fx, float fy, float dx, float dy, float result[4], ImagePool *pool)
void ibuf_sample(ImBuf *ibuf, float fx, float fy, float dx, float dy, float result[4])
@ TXC_YMIR
@ TXC_XMIR
@ TXC_REPT
@ TXC_EXTD
static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, const AFData *AFD)
static float clipy_rctf(rctf *rf, float y1, float y2)
static float square_rctf(const rctf *rf)
int imagewrap(Tex *tex, Image *ima, const float texvec[3], TexResult *texres, ImagePool *pool, const bool skip_load_image)
static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, const short imaprepeat, const short imapextend)
static float clipx_rctf(rctf *rf, float x1, float x2)
static void boxsampleclip(ImBuf *ibuf, const rctf *rf, TexResult *texres)
static void ibuf_get_color(float col[4], ImBuf *ibuf, int x, int y)
static void ewa_read_pixel_cb(void *userdata, int x, int y, float result[4])
static void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2)
static void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2)
static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extflag)