-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMandelbrot.cs
More file actions
114 lines (91 loc) · 4.09 KB
/
Copy pathMandelbrot.cs
File metadata and controls
114 lines (91 loc) · 4.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace CS_GRAPHICS
{
public class Mandelbrot
{
// 1. Get image dimensions
private int _imageWidth = 1024;
private int _imageHeight = 768;
// 2. Define our "world" boundaries (complex plane)
private double _viewportMinX = -2.0;
private double _viewportMaxX = 1.0;
private double _viewportMinY = -1.2;
private double _viewportMaxY = 1.2;
public int MaxIterations { get; set; } = 128;
private Bitmap? _buffer = null;
public Bitmap? Buffer
{
get { return _buffer; }
}
public void Render()
{
if (_buffer != null)
{
_buffer.Dispose();
}
_buffer = new Bitmap(_imageWidth, _imageHeight);
// Lock the Bitmap's memory
Rectangle rect = new Rectangle(0, 0, _imageWidth, _imageHeight);
BitmapData bmpData = _buffer.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
// Calculate how many bytes we need to store the whole image
int bytes = Math.Abs(bmpData.Stride) * _imageHeight;
// Create temp byte array to hold our color data
byte[] rgbValues = new byte[bytes];
Parallel.For(0, _imageHeight, y =>
{
// Pre-calculation: Find the start of the row in the flat array
int rowOffset = (int)y * bmpData.Stride;
for (int x = 0; x < _imageWidth; x++)
{
// 4. Convert pixel (x, y) to a complex number (a + bi)
// Map from image to complex plane
double a = _viewportMinX + (x * (_viewportMaxX - _viewportMinX) / _imageWidth);
double b = _viewportMinY + (y * (_viewportMaxY - _viewportMinY) / _imageHeight);
// Z = Z^2 + c, c = (a + bi)
double zx = 0;
double zy = 0;
int iterations = 0;
while (iterations < MaxIterations && (zx * zx + zy * zy < 4.0))
{
// Compute the next Z
// this is the result of Z^2 + (a + bi)
// (zx + zyi)^2 ...
double nextZx = (zx * zx - zy * zy) + a;
double nextZy = (2 * zx * zy) + b;
zx = nextZx;
zy = nextZy;
iterations++;
}
// Calculate the pixel index
// Each pixel has bytes.
// [index] = Blue, [index + 1] = Green, [Index + 2] = Red, [Index + 3] = Alpha
int index = rowOffset + (x * 4);
if (iterations == MaxIterations)
{
rgbValues[index] = 0; // B
rgbValues[index + 1] = 0; // G
rgbValues[index + 2] = 0; // R
rgbValues[index + 3] = 255; // A
}
else
{
// simple grayscale color
byte colorVal = (byte)(255 * (double)iterations / MaxIterations);
rgbValues[index] = colorVal; // B
rgbValues[index + 1] = colorVal; // G
rgbValues[index + 2] = colorVal; // R
rgbValues[index + 3] = 255; // A
}
}
});
// "teleport' the entire byte array into the Bitmap's memory address
// Scan0 is the memory address of the first pixel
// Instead of moving one pixel at a time, we move the entire image data
// in a very fast operation
Marshal.Copy(rgbValues, 0, bmpData.Scan0, bytes);
_buffer.UnlockBits(bmpData);
//pictureBox.Image = _buffer;
}
}
}