studies/betriebssysteme/Betriebssysteme-Code4/Fraktal.cpp
⇒
download file
1
2
3
4
5
6
7
8
9
10 #include <windows.h>
11
12 #include <stdio.h>
13
14
15
16
17 #pragma comment(linker, "/OPT:NOWIN98")
18
19 #pragma comment(linker, "/NODEFAULTLIB:libc.lib")
20 #pragma comment(linker, "/NODEFAULTLIB:libcd.lib")
21 #pragma comment(lib, "msvcrt.lib")
22 #pragma comment(lib, "gdi32.lib")
23
24 #pragma comment(exestr, "(C)2001-2002 by Stephan Brumme")
25
26
27
28 struct TFractalParameters
{
29 COLORREF* arImage;
30 unsigned int nWidth;
31 unsigned int nHeight;
32 double dLeft;
33 double dRight;
34 double dTop;
35 double dBottom;
36 unsigned int nMaxDepth;
37 };
38
39
40
41
42 bool WriteBMP(const char* strFilename, unsigned int nWidth, unsigned int nHeight, const COLORREF arImage[])
43 {
44
45
46
47 BITMAPINFO bmpInfo;
48 bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
49 bmpInfo.bmiHeader.biWidth = nWidth;
50 bmpInfo.bmiHeader.biHeight = nHeight;
51 bmpInfo.bmiHeader.biPlanes = 1;
52 bmpInfo.bmiHeader.biBitCount = 32;
53 bmpInfo.bmiHeader.biClrUsed = 0;
54 bmpInfo.bmiHeader.biClrImportant = 0;
55 bmpInfo.bmiHeader.biCompression = BI_RGB;
56 bmpInfo.bmiHeader.biSizeImage = ((nWidth*32+31) & ~31) / 8 * nHeight;
57 bmpInfo.bmiHeader.biXPelsPerMeter =
58 bmpInfo.bmiHeader.biYPelsPerMeter = 3780;
59
60
61 BITMAPFILEHEADER bmpHeader;
62
63 bmpHeader.bfType = 0x4d42;
64
65 bmpHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + bmpInfo.bmiHeader.biSize; +
66
67 bmpHeader.bfSize = bmpHeader.bfOffBits + bmpInfo.bmiHeader.biSizeImage;
68
69 bmpHeader.bfReserved1 = 0;
70 bmpHeader.bfReserved2 = 0;
71
72
73
74 HANDLE hFile;
75 if (strFilename != NULL)
76 hFile = CreateFile(strFilename, GENERIC_WRITE, 0, NULL,
77 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
78 else
hFile = GetStdHandle(STD_OUTPUT_HANDLE);
79
80
81 if (hFile == INVALID_HANDLE_VALUE)
82 return false;
83
84
85 DWORD dwBytesWritten;
86
87 if (!WriteFile(hFile, &bmpHeader, sizeof(bmpHeader), &dwBytesWritten, NULL))
88 return false;
89
90 if (!WriteFile(hFile, &bmpInfo, sizeof(bmpInfo), &dwBytesWritten, NULL))
91 return false;
92
93
94 if (!WriteFile(hFile, arImage, bmpInfo.bmiHeader.biSizeImage, &dwBytesWritten, NULL))
95 return false;
96
97
98 CloseHandle(hFile);
99 return true;
100 }
101
102
103
104 DWORD WINAPI Calculate(void *pParameter)
105 {
106
107 TFractalParameters *param = (TFractalParameters*) pParameter;
108
109
110 COLORREF* pImageCursor = param->arImage;
111
112
113
114 for (unsigned int nRow = 0; nRow < param->nHeight; nRow++)
115 {
116 for (unsigned int nColumn = 0; nColumn < param->nWidth; nColumn++)
117 {
118
119 const double dX = nColumn/(param->nWidth -1.0) * (param->dRight - param->dLeft ) + param->dLeft;
120 const double dY = nRow /(param->nHeight-1.0) * (param->dTop - param->dBottom) + param->dBottom;
121
122
123 unsigned int nDepth = 0;
124 double wx = dX;
125 double wy = dY;
126
127
128 do
{
129 const double old_wx = wx;
130 nDepth++;
131
132 wx = wx*wx - wy*wy + dX;
133 wy = 2*old_wx * wy + dY;
134 } while (wx*wx + wy*wy <= 4 && nDepth <= param->nMaxDepth);
135
136
137 nDepth--;
138
139
140 nDepth = int((param->nMaxDepth-nDepth) * 255.0 / param->nMaxDepth);
141 *pImageCursor = RGB(nDepth, nDepth, nDepth);
142 pImageCursor++;
143 }
144 }
145
146 return 0;
147 }
148
149
150
151
152 int main(int argc, char* argv[])
153 {
154
155 unsigned int nWidth = 512;
156 unsigned int nHeight = 512;
157 double dLeft = -2.0;
158 double dRight = 0.5;
159 double dTop = 1.25;
160 double dBottom = -1.25;
161 unsigned int nMaxDepth = 25;
162 const char* strFilename = NULL;
163 unsigned int nThreads = 1;
164
165
166 if (argc == 1)
167 {
168 printf("options:\n"
169 " /f:image.bmp output file (default: standard output)\n"
170 " /m:1 no. of threads (default: 1 thread)\n"
171 " /x:512 set width (default: 512 pixel)\n"
172 " /y:512 set height (default: 512 pixel)\n"
173 " /l:-2.0 left border (default: -2.0)\n"
174 " /r:0.5 right border (default: 0.5)\n"
175 " /t:1.25 top border (default: 1.25)\n"
176 " /b:-1.25 bottom border (default: -1.25)\n"
177 " /d:25 iteration depth (default: 25, must be 0..255)\n"
178 );
179
180 return 1;
181 }
182
183
184 int nParameter = 1;
185 while (nParameter < argc)
186 {
187
188 const char* strOption = argv[nParameter];
189
190
191 if (strOption == NULL ||
192 strlen(strOption) < 4 ||
193 strOption[0] != '/' ||
194 strOption[2] != ':')
195 {
196 printf("unknown option '%s'\n", strOption);
197 return 1;
198 }
199
200
201 const char* strValue = &(strOption[3]);
202
203
204 switch(strOption[1])
205 {
206
207 case 'f':
208 case 'F': strFilename = strValue; break;
209
210
211 case 'x':
212 case 'X': nWidth = atoi(strValue); break;
213 case 'y':
214 case 'Y': nHeight = atoi(strValue); break;
215
216
217 case 'l':
218 case 'L': dLeft = atof(strValue); break;
219 case 'r':
220 case 'R': dRight = atof(strValue); break;
221 case 't':
222 case 'T': dTop = atof(strValue); break;
223 case 'b':
224 case 'B': dBottom = atof(strValue); break;
225
226
227 case 'd':
228 case 'D': nMaxDepth = atoi(strValue); break;
229
230
231 case 'm':
232 case 'M': nThreads = atoi(strValue); break;
233
234
235 default: printf("unknown option '%s'\n", strOption);
236 return 1;
237 }
238
239
240 nParameter++;
241 }
242
243
244
245 COLORREF* arImage = new COLORREF[nWidth*nHeight];
246
247
248 HANDLE* arhThread = new HANDLE[nThreads];
249 DWORD dwThreadID;
250
251
252 TFractalParameters* param = new TFractalParameters[nThreads];
253 const double dHeightDelta = (dTop - dBottom)/nThreads;
254
255
256 for (unsigned int i=0; i<nThreads; i++)
257 {
258
259 param[i].nWidth = nWidth;
260 param[i].nHeight = nHeight*(i+1)/nThreads - nHeight*i/nThreads;
261
262 param[i].arImage = arImage;
263 param[i].arImage += (nHeight-nHeight*i/nThreads-param[i].nHeight)*nWidth;
264
265 param[i].dLeft = dLeft;
266 param[i].dRight = dRight;
267 param[i].dTop = dTop-i*dHeightDelta;
268 param[i].dBottom = param[i].dTop-dHeightDelta*param[i].nHeight/(nHeight/(double)nThreads);
269
270 param[i].nMaxDepth = nMaxDepth;
271
272
273 arhThread[i] = CreateThread(NULL, 0, Calculate, &(param[i]), 0, &dwThreadID);
274 if (strFilename != NULL)
275 printf("starting thread %d (ID: %d)\n", i+1, dwThreadID);
276 }
277
278
279 WaitForMultipleObjects(nThreads, arhThread, true, INFINITE);
280
281
282 if (strFilename != NULL)
283 printf("writing to %s ... ", strFilename);
284 if (!WriteBMP(strFilename, nWidth, nHeight, arImage))
285 printf("FAILURE !!!\n");
286
287
288 delete arImage;
289 for (i=0; i<nThreads; i++)
290 CloseHandle(arhThread[i]);
291 delete arhThread;
292
293
294 return 0;
295 }
296