2
* $Id: zblur.c,v 1.5 2005/06/04 16:22:50 lukep Exp $
4
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version. The Blender
10
* Foundation also sells licenses for use in proprietary software under
11
* the Blender License. See http://www.blender.org/BL/ for information
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software Foundation,
21
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
* ***** END GPL/BL DUAL LICENSE BLOCK *****
27
* This file is largely based on the focal blur plugin by onk, 8.99
36
#include "MEM_guardedalloc.h"
38
#include "DNA_camera_types.h"
39
#include "DNA_scene_types.h"
41
#include "BKE_global.h"
42
#include "BKE_utildefines.h"
44
#include "RE_callbacks.h"
47
#include "pixelblending.h"
54
/* -------------------------------------------------
57
typedef enum { I_GRAY, I_FLOAT, I_FLOAT4 } IMGTYPE;
66
typedef struct { /* blur mask struct */
72
typedef Mask* Maskarray;
74
/* don't change these */
75
#define NMASKS_SHIFT 2
79
static Image *alloc_img(int x, int y, IMGTYPE type)
89
typesize = sizeof(float);
92
typesize = 4 * sizeof(float);
100
ret = (Image *) MEM_mallocN(sizeof(Image) + size*typesize, "zblur_img");
105
ret->el_size = typesize;
107
ret->data = (char *) (ret + 1);
109
memset(ret->data, 0, size);
115
static int free_img(Image *img)
121
/* 32 bits (int) rect to float buf */
122
static void recti2imgf(unsigned int *src, Image *dest, int x, int y)
128
if(dest->type != I_FLOAT4) return;
131
to = (float *) dest->data;
133
if (R.r.mode & R_FIELDS) { /* double each scanline */
134
for (iy=0; iy<y; iy++) {
135
for (ix=0; ix<x; ix++) {
136
*to++ = ((float)from[0])/255.0;
137
*to++ = ((float)from[1])/255.0;
138
*to++ = ((float)from[2])/255.0;
139
*to++ = ((float)from[3])/255.0;
143
memcpy(to, to-4*sizeof(float)*x, 4*sizeof(float)*x);
152
*to++ = ((float)from[0])/255.0;
153
*to++ = ((float)from[1])/255.0;
154
*to++ = ((float)from[2])/255.0;
155
*to++ = ((float)from[3])/255.0;
161
/* float rect to float buf */
162
static void rectf2imgf(float *src, Image *dest, int x, int y)
168
if(dest->type != I_FLOAT4) return;
171
to = (float *) dest->data;
173
if (R.r.mode & R_FIELDS) { /* double each scanline */
174
for (iy=0; iy<y; iy++) {
176
memcpy(to, from, 4*sizeof(float)*x);
178
memcpy(to, from, 4*sizeof(float)*x);
188
memcpy(to, from, 4*sizeof(float)*x);
195
/* floatbuf back to 32 bits rect */
196
static void imgf2recti(Image *src, unsigned int *dest)
202
if(src->type != I_FLOAT4) return;
204
from = (float *) src->data;
207
if (R.r.mode & R_FIELDS) {
208
for (iy=0; iy<src->y; iy++) {
209
for (ix=0; ix<src->x; ix++) {
210
*to++ = (char)(from[0]*255.0);
211
*to++ = (char)(from[1]*255.0);
212
*to++ = (char)(from[2]*255.0);
213
*to++ = (char)(from[3]*255.0);
223
*to++ = (char)(from[0]*255.0);
224
*to++ = (char)(from[1]*255.0);
225
*to++ = (char)(from[2]*255.0);
226
*to++ = (char)(from[3]*255.0);
232
/* floatbuf back to float rect */
233
static void imgf2rectf(Image *src, float *dest)
239
if(src->type != I_FLOAT4) return;
241
from = (float *) src->data;
244
if (R.r.mode & R_FIELDS) {
245
for (iy=0; iy<src->y; iy++) {
247
memcpy(to, from, 4*sizeof(float)*src->x);
256
memcpy(to, from, 4*sizeof(float)*i);
261
static void imgf_gamma(Image *src, float gamma)
266
if(gamma==1.0) return;
268
i = 4 * src->x * src->y;
269
to= (float *) src->data;
271
*to = (float)pow(*to, gamma);
277
/* create new image with alpha & color zero where mask is zero */
278
static Image *imgf_apply_mask(Image *src, Image *zmask)
285
dest = alloc_img(src->x, src->y, I_FLOAT4);
288
from= (float *) src->data;
289
to= (float *) dest->data;
290
zptr= (char *)zmask->data;
300
to[0]= to[1]= to[2]= to[3]= 0.0f;
310
static void imgf_alpha_over(Image *dest, Image *src)
316
from= (float *) src->data;
317
to= (float *) dest->data;
320
addAlphaOverFloat(to, from);
328
/* --------------------------------------------------------------------- */
331
static Mask *alloc_mask(int size)
336
memsize = (sizeof(Mask) + (2 * size +1) * (2 * size +1) * sizeof(float));
338
m = (Mask*) MEM_mallocN(memsize, "zblur_mask");
340
m->val = (float *) (m + 1);
345
static void free_mask(Mask *m)
349
memsize = 2 * m->size + 1;
350
memsize *= memsize * sizeof(float);
351
memsize += sizeof(Mask);
356
/* normalize mask to 1 */
358
static void norm_mask(Mask *m)
365
size = (2 * m->size +1)*(2 * m->size +1);
374
/* filters a grayvalue image with a gaussian IIR filter with blur radius "rad"
375
* For large blurs, it's more efficient to call the routine several times
376
* instead of using big blur radii.
377
* The original image is changed */
380
static void gauss_blur(Image *img, float rad)
383
register float sum, val;
392
r = (1.5 * rad + 1.5);
396
if ((img->x <= n) || (img->y <= n)) {
400
gausstab = (float *) MEM_mallocN(n * sizeof(float), "zblur_gauss");
407
for (x = -r; x <= r; x++) {
409
val = exp(-4*(float ) (x*x)/ (float) (r*r));
420
new = alloc_img(img->x, img->y, I_GRAY);
429
for (y = 0; y < img->y; y++) {
430
src = (char *)img->data + (y * img->x);
431
dest = (char *)new->data + (y * img->x);
433
for (x = r; x > 0 ; x--) {
438
for (i = 0; i < m; i++) {
441
gval += val * (*src++);
443
*dest++ = gval / sum;
447
for (x = 0; x <= (img->x - n); x++) {
451
for (i = 0; i < n; i++) {
453
gval += val * (*src++);
459
for (x = 1; x <= r ; x++) {
464
for (i = 0; i < m; i++) {
467
gval += val * (*src++);
469
*dest++ = gval / sum;
477
bigstep = (n - 1) * step;
478
for (x = 0; x < step ; x++) {
480
dest = img->data + x;
482
for (y = r; y > 0; y--) {
487
for (i = 0; i < m; i++) {
490
gval += val * src[0];
493
dest[0] = gval / sum;
497
for (y = 0; y <= (img->y - n); y++) {
500
for (i = 0; i < n; i++) {
502
gval += val * src[0];
509
for (y = 1; y <= r ; y++) {
514
for (i = 0; i < m; i++) {
517
gval += val * src[0];
520
dest[0] = gval / sum;
522
src -= (m - 1) * step;
529
static float zigma(float x, float sigma, float sigma4)
531
//return 1.0/(1.0+pow(x, sigma));
535
return 1.0/exp(x*x) - sigma4;
541
static Mask *gauss_mask(float rad, float sigma)
544
float sum, val, *v, fac, radsq= rad*rad;
549
r = (1.0 * rad + 1.0);
554
sigma4= 1.0/exp(sigma*sigma*sigma*sigma);
556
for (iy = -r; iy <= r; iy++) {
557
for (ix = -r; ix <= r; ix++) {
559
fac= ((float)(ix*ix + iy*iy))/(radsq);
560
val = zigma(fac, sigma, sigma4);
562
// val = exp(-(float) (ix*ix + iy*iy)/(rad * rad));
574
/* generates #num masks with the maximal blur radius 'rad'
576
static Maskarray *init_masks(int num, float rad, float sigma)
580
Maskarray *maskarray;
582
maskarray = (Maskarray*) MEM_mallocN(num * sizeof (Maskarray), "zblur_masks");
585
for (i = 0; i < num; i++) {
586
maskarray[i] = gauss_mask(r, sigma);
593
/* ********************* Do the blur ******************************** */
595
static Image *zblur(Image *src, Image *zbuf, float radius, float sigma)
601
float *mval; /* mask value pointer */
602
float rval, gval, bval, aval;
615
if(src->type != I_FLOAT4) return NULL;
617
dest = alloc_img(src->x, src->y, I_FLOAT4);
620
mar = init_masks(NMASKS, radius, sigma);
622
for (y = 0; y < src->y ; y++) {
623
for (x = 0; x < src->x; x++) {
624
dptr = (float *) (dest->data + ((y * src->x + x) * src->el_size));
625
zptr = zbuf->data + (y * src->x + x);
627
sptr = (float *) (src->data + ((y *src->x + x )* src->el_size));
629
m = mar[zval >> NMASKS_SHIFT];
633
if(size==0 || zval==0) {
644
sx = (x < size) ? x : size;
645
sy = (y < size) ? y : size;
646
ex = (ex <= size) ? ex - 1: size;
647
ey = (ey <= size) ? ey - 1: size;
649
sptr -= sy *src->x * 4;
651
mrow = (size << 1) + 1;
652
mval = m->val + (size - sy) * mrow + size;
654
norm = rval = gval = bval = aval= 0.0;
656
for (my = -sy; my <= ey; my++) {
657
for (mx = -sx; mx <= ex; mx++) {
660
fac = mval[mx] * (float) zptr[mx] /255.0 ;
663
rval += fac * sptr[tmp];
664
gval += fac * sptr[tmp + 1];
665
bval += fac * sptr[tmp + 2];
666
aval += fac * sptr[tmp + 3];
674
dptr[0] = rval / norm;
675
dptr[1] = gval / norm;
676
dptr[2] = bval / norm;
677
dptr[3] = aval / norm;
679
if(!(y % 4) && RE_local_test_break()) break;
682
for (i= 0; i < NMASKS; i++) {
692
/* this splits the z-buffer into 2 gray-images (background, foreground)
693
* which are used for the weighted blur */
695
static void zsplit(int *zptr, Image *fg, Image *bg, int zfocus, int zmax, int zmin, int x, int y)
700
float fgnorm, bgnorm;
704
bgnorm = 255.0 / ((float) zmax - (float) zfocus);
705
fgnorm = 255.0 / ((float) zfocus - (float) zmin);
707
if (R.r.mode & R_FIELDS) {
708
for (iy=0; iy<y; iy++) {
709
for (ix=0; ix<x; ix++) {
710
fdist = (float) (*zptr++);
711
if (fdist < zmin) fdist = zmin;
716
*p = (char) (-fdist * fgnorm);
720
*q = (char) (fdist * bgnorm);
733
fdist = (float) (*zptr++);
734
if (fdist < zmin) fdist = zmin;
739
*p = (char) (-fdist * fgnorm);
743
*q = (char) (fdist * bgnorm);
753
Image *orig, *zfront, *work, *zback;
758
if (R.rectz == NULL) return;
763
zblurr= (R.r.zblur*R.r.size)/100;
765
if (R.r.mode & R_FIELDS) {
770
zmin= INT_MAX*( 2.0*R.r.zmin - 1.0); // R.r.zmin ranges 0 - 1
771
zfocus = INT_MAX*( 2.0*R.r.focus - 1.0);
773
if(zmin>zfocus) zmin= zfocus;
775
zfront = alloc_img(x, y, I_GRAY);
776
zback = alloc_img(x, y, I_GRAY);
777
orig = alloc_img(x, y, I_FLOAT4);
779
if(R.rectftot) rectf2imgf(R.rectftot, orig, x, y);
780
else recti2imgf(R.rectot, orig, x, y);
782
imgf_gamma(orig, R.r.zgamma); // pregamma correct if required
785
/* split up z buffer into 2 gray images */
786
zsplit(R.rectz, zfront, zback, zfocus, INT_MAX, zmin, x, y);
788
// glDrawBuffer(GL_FRONT);
789
// glRasterPos2i(0, 0);
790
// glDrawPixels(x, y, GL_RED, GL_UNSIGNED_BYTE, zback->data);
792
// glDrawBuffer(GL_BACK);
794
gauss_blur(zback, 1.0);
795
gauss_blur(zfront, zblurr);
798
work = zblur(orig, zback, zblurr, R.r.zsigma);
801
/* blur front part */
802
orig = zblur(work, zfront, zblurr, R.r.zsigma);
804
imgf_gamma(orig, 1.0/R.r.zgamma); // pregamma correct if required
806
if(R.rectftot) imgf2rectf(orig, R.rectftot);
807
else imgf2recti(orig, R.rectot);
814
/* make new display rect */
815
if(R.rectftot) RE_floatbuffer_to_output();