From e3c6ae9b89d1d0c7bb6957f81b9fd9a89477b2d0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 21 Jul 2009 13:20:35 +0000 Subject: 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. --- source/blender/imbuf/intern/filter.c | 88 +++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) (limited to 'source/blender/imbuf/intern') 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->xy?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; yy; ++y) + for (x=0; xx; ++x) { + avg[0] += *fp++; + avg[1] += *fp++; + avg[2] += *fp++; + avg[3] += *fp++; + } + } + else { + char* cp = (char*)ibuf->rect; + for (y=0; yy; ++y) + for (x=0; xx; ++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; yy; ++y) + for (x=0; xx; ++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; yy; ++y) + for (x=0; xx; ++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++; + } + } +} -- cgit v1.2.3