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