1 /**
2  * Mandelbulber v2, a 3D fractal generator       ,=#MKNmMMKmmßMNWy,
3  *                                             ,B" ]L,,p%%%,,,§;, "K
4  * Copyright (C) 2017-20 Mandelbulber Team     §R-==%w["'~5]m%=L.=~5N
5  *                                        ,=mm=§M ]=4 yJKA"/-Nsaj  "Bw,==,,
6  * This file is part of Mandelbulber.    §R.r= jw",M  Km .mM  FW ",§=ß., ,TN
7  *                                     ,4R =%["w[N=7]J '"5=],""]]M,w,-; T=]M
8  * Mandelbulber is free software:     §R.ß~-Q/M=,=5"v"]=Qf,'§"M= =,M.§ Rz]M"Kw
9  * you can redistribute it and/or     §w "xDY.J ' -"m=====WeC=\ ""%""y=%"]"" §
10  * modify it under the terms of the    "§M=M =D=4"N #"%==A%p M§ M6  R' #"=~.4M
11  * GNU General Public License as        §W =, ][T"]C  §  § '§ e===~ U  !§[Z ]N
12  * published by the                    4M",,Jm=,"=e~  §  §  j]]""N  BmM"py=ßM
13  * Free Software Foundation,          ]§ T,M=& 'YmMMpM9MMM%=w=,,=MT]M m§;'§,
14  * either version 3 of the License,    TWw [.j"5=~N[=§%=%W,T ]R,"=="Y[LFT ]N
15  * or (at your option)                   TW=,-#"%=;[  =Q:["V""  ],,M.m == ]N
16  * any later version.                      J§"mr"] ,=,," =="""J]= M"M"]==ß"
17  *                                          §= "=C=4 §"eM "=B:m|4"]#F,§~
18  * Mandelbulber is distributed in            "9w=,,]w em%wJ '"~" ,=,,ß"
19  * the hope that it will be useful,                 . "K=  ,=RMMMßM"""
20  * but WITHOUT ANY WARRANTY;                            .'''
21  * without even the implied warranty
22  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * See the GNU General Public License for more details.
25  * You should have received a copy of the GNU General Public License
26  * along with Mandelbulber. If not, see <http://www.gnu.org/licenses/>.
27  *
28  * ###########################################################################
29  *
30  * Authors: Krzysztof Marczak (buddhi1980@gmail.com)
31  *
32  * cPostEffectHdrBlur - Renders a weighted blur which works on HDR image data
33  */
34 
35 #include "post_effect_hdr_blur.h"
36 
37 #include "cimage.hpp"
38 #include "global_data.hpp"
39 #include "progress_text.hpp"
40 #include "system_data.hpp"
41 
cPostEffectHdrBlur(std::shared_ptr<cImage> _image)42 cPostEffectHdrBlur::cPostEffectHdrBlur(std::shared_ptr<cImage> _image) : QObject(), image(_image)
43 {
44 	tempImage.resize(image->GetHeight() * image->GetWidth());
45 	radius = 0;
46 	intensity = 0;
47 }
48 
~cPostEffectHdrBlur()49 cPostEffectHdrBlur::~cPostEffectHdrBlur()
50 {
51 	// nothing to delete
52 }
53 
Render(bool * stopRequest)54 void cPostEffectHdrBlur::Render(bool *stopRequest)
55 {
56 
57 	tempImage = image->GetPostImageFloat();
58 
59 	const double blurSize = radius * (image->GetWidth() + image->GetHeight()) * 0.001;
60 	const double blurSize2 = blurSize * blurSize;
61 	const int intBlurSize = int(blurSize + 1);
62 	const double limiter = intensity;
63 
64 	QString statusText = QObject::tr("Rendering HDR Blur effect");
65 	QString progressTxt;
66 
67 	cProgressText progressText;
68 	progressText.ResetTimer();
69 	double percentDone = 0.0;
70 
71 	QElapsedTimer timerRefreshProgressBar;
72 	timerRefreshProgressBar.start();
73 
74 	for (qint64 y = 0; y < qint64(image->GetHeight()); y++)
75 	{
76 		if (*stopRequest || systemData.globalStopRequest) break;
77 
78 #pragma omp parallel for
79 		for (qint64 x = 0; x < qint64(image->GetWidth()); x++)
80 		{
81 			double weight = 0;
82 			int yStart = qMax(0LL, y - intBlurSize);
83 			int yEnd = qMin(qint64(image->GetHeight()), y + intBlurSize);
84 
85 			sRGBFloat newPixel;
86 
87 			for (int yy = yStart; yy < yEnd; yy++)
88 			{
89 				int xStart = qMax(0LL, x - intBlurSize);
90 				int xEnd = qMin(qint64(image->GetWidth()), x + intBlurSize);
91 				for (int xx = xStart; xx < xEnd; xx++)
92 				{
93 					double dx = x - xx;
94 					double dy = y - yy;
95 					double r2 = dx * dx + dy * dy;
96 					if (r2 < blurSize2)
97 					{
98 						double value = 1.0 / (r2 / (0.2 * blurSize) + limiter);
99 						// if(dx == 0 && dy == 0) value = 10.0;
100 						weight += value;
101 						sRGBFloat oldPixel = tempImage[xx + yy * image->GetWidth()];
102 						newPixel.R += oldPixel.R * value;
103 						newPixel.G += oldPixel.G * value;
104 						newPixel.B += oldPixel.B * value;
105 					}
106 				}
107 			}
108 
109 			if (weight > 0)
110 			{
111 				newPixel.R /= weight;
112 				newPixel.G /= weight;
113 				newPixel.B /= weight;
114 			}
115 			image->PutPixelPostImage(x, y, newPixel);
116 		}
117 
118 		if (timerRefreshProgressBar.elapsed() > 100)
119 		{
120 			timerRefreshProgressBar.restart();
121 
122 			percentDone = float(y) / float(image->GetHeight());
123 			progressTxt = progressText.getText(percentDone);
124 
125 			emit updateProgressAndStatus(statusText, progressTxt, percentDone);
126 			gApplication->processEvents();
127 		}
128 	}
129 
130 	emit updateProgressAndStatus(statusText, progressText.getText(1.0), 1.0);
131 }
132 
SetParameters(double _radius,double _intensity)133 void cPostEffectHdrBlur::SetParameters(double _radius, double _intensity)
134 {
135 	radius = _radius;
136 	intensity = _intensity;
137 }
138