Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2009-07-21 17:20:35 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2009-07-21 17:20:35 +0400
commite3c6ae9b89d1d0c7bb6957f81b9fd9a89477b2d0 (patch)
tree9a50b247676dd1f3b0abe3cea40cc0773161dae3 /source/blender/imbuf
parentea0b015b0a1c73fb1899a4d9040704a7d85fda9c (diff)
2.5: Texture Filtering
Patch by Alfredo de Greef with high quality image texture filters. This adds 3 new filters: * SAT: Summed Area Tables. This is like mipmaps, but using somewhat more memory avoids some artifacts. * EWA: Ellipitical Weighted Average, anisotropic filter. * FELINE: Fast elliptical lines for anisotropic texture mapping. The one change I made to this was to try to fix an alpha/premul problem, hopefully I didn't break anything, it looks compatible with the existing filter now for me.
Diffstat (limited to 'source/blender/imbuf')
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/intern/filter.c88
2 files changed, 88 insertions, 2 deletions
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 1d8035a2358..d2f561438b9 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -319,7 +319,7 @@ void IMB_antialias(struct ImBuf * ibuf);
void IMB_filter(struct ImBuf *ibuf);
void IMB_filterN(struct ImBuf *out, struct ImBuf *in);
void IMB_filter_extend(struct ImBuf *ibuf, char *mask);
-void IMB_makemipmap(struct ImBuf *ibuf, int use_filter);
+void IMB_makemipmap(struct ImBuf *ibuf, int use_filter, int SAT);
/**
*
diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c
index 9802405fd8d..cc3315c7696 100644
--- a/source/blender/imbuf/intern/filter.c
+++ b/source/blender/imbuf/intern/filter.c
@@ -371,6 +371,7 @@ void IMB_filter_extend(struct ImBuf *ibuf, char *mask)
}
}
+#if 0
void IMB_makemipmap(ImBuf *ibuf, int use_filter)
{
ImBuf *hbuf= ibuf;
@@ -394,5 +395,90 @@ void IMB_makemipmap(ImBuf *ibuf, int use_filter)
minsize= hbuf->x<hbuf->y?hbuf->x:hbuf->y;
}
}
+#endif
-
+void IMB_makemipmap(ImBuf *ibuf, int use_filter, int SAT)
+{
+ if (SAT) {
+ // to maximize precision subtract image average, use intermediate double SAT,
+ // only convert to float at the end
+ const double dv = 1.0/255.0;
+ double avg[4] = {0, 0, 0, 0};
+ const int x4 = ibuf->x << 2;
+ int x, y, i;
+ ImBuf* sbuf = IMB_allocImBuf(ibuf->x, ibuf->y, 32, IB_rectfloat, 0);
+ double *satp, *satbuf = MEM_callocN(sizeof(double)*ibuf->x*ibuf->y*4, "tmp SAT buf");
+ const double mf = ibuf->x*ibuf->y;
+ float* fp;
+ ibuf->mipmap[0] = sbuf;
+ if (ibuf->rect_float) {
+ fp = ibuf->rect_float;
+ for (y=0; y<ibuf->y; ++y)
+ for (x=0; x<ibuf->x; ++x) {
+ avg[0] += *fp++;
+ avg[1] += *fp++;
+ avg[2] += *fp++;
+ avg[3] += *fp++;
+ }
+ }
+ else {
+ char* cp = (char*)ibuf->rect;
+ for (y=0; y<ibuf->y; ++y)
+ for (x=0; x<ibuf->x; ++x) {
+ avg[0] += *cp++ * dv;
+ avg[1] += *cp++ * dv;
+ avg[2] += *cp++ * dv;
+ avg[3] += *cp++ * dv;
+ }
+ }
+ avg[0] /= mf;
+ avg[1] /= mf;
+ avg[2] /= mf;
+ avg[3] /= mf;
+ for (y=0; y<ibuf->y; ++y)
+ for (x=0; x<ibuf->x; ++x) {
+ const unsigned int p = (x + y*ibuf->x) << 2;
+ char* cp = (char*)ibuf->rect + p;
+ fp = ibuf->rect_float + p;
+ satp = satbuf + p;
+ for (i=0; i<4; ++i, ++cp, ++fp, ++satp) {
+ double sv = (ibuf->rect_float ? (double)*fp : (double)(*cp)*dv) - avg[i];
+ if (x > 0) sv += satp[-4];
+ if (y > 0) sv += satp[-x4];
+ if (x > 0 && y > 0) sv -= satp[-x4 - 4];
+ *satp = sv;
+ }
+ }
+ fp = sbuf->rect_float;
+ satp = satbuf;
+ for (y=0; y<ibuf->y; ++y)
+ for (x=0; x<ibuf->x; ++x) {
+ *fp++ = (float)*satp++;
+ *fp++ = (float)*satp++;
+ *fp++ = (float)*satp++;
+ *fp++ = (float)*satp++;
+ }
+ MEM_freeN(satbuf);
+ fp = &sbuf->rect_float[(sbuf->x - 1 + (sbuf->y - 1)*sbuf->x) << 2];
+ fp[0] = avg[0];
+ fp[1] = avg[1];
+ fp[2] = avg[2];
+ fp[3] = avg[3];
+ }
+ else {
+ ImBuf *hbuf = ibuf;
+ int curmap = 0;
+ while (curmap < IB_MIPMAP_LEVELS) {
+ if (use_filter) {
+ ImBuf *nbuf= IMB_allocImBuf(hbuf->x, hbuf->y, 32, IB_rect, 0);
+ IMB_filterN(nbuf, hbuf);
+ ibuf->mipmap[curmap] = IMB_onehalf(nbuf);
+ IMB_freeImBuf(nbuf);
+ }
+ else ibuf->mipmap[curmap] = IMB_onehalf(hbuf);
+ hbuf = ibuf->mipmap[curmap];
+ if (hbuf->x == 1 && hbuf->y == 1) break;
+ curmap++;
+ }
+ }
+}