File:Mandelbrot Set Image 76.png
Summary
| Description |
Русский: Фрагмент множества Мандельброта, координаты центра: -0.5503493176297569, 0.6259309572825709 ширина изображения 0.00000000000031
English: Fragment of the Mandelbrot set, coordinates: -0.5503493176297569, 0.6259309572825709 width 0.00000000000031
Беларуская: Фрагмент мноства Мандэльброта, каардынаты цэнтра: -0.5503493176297569, 0.6259309572825709 шырыня 0.00000000000031 |
| Date | |
| Source | Own work |
| Author | Aokoroko |
| Other versions |
|
| Source code (C++ with OpenMP, 80-bit, SSAA 8x8) | #ifdef _WIN32
#include <windows.h>
#endif
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstdint>
#include <atomic>
#include <omp.h>
using namespace std;
const double PI = 3.14159265358979323846;
// BMP file structures for manual header generation
#pragma pack(push, 1)
struct BMPHeader {
uint16_t type{0x4D42}; // 'BM'
uint32_t size{0};
uint16_t reserved1{0};
uint16_t reserved2{0};
uint32_t offBits{54};
uint32_t structSize{40};
int32_t width{0};
int32_t height{0};
uint16_t planes{1};
uint16_t bitCount{24}; // RGB 24-bit
uint32_t compression{0};
uint32_t sizeImage{0};
int32_t xpelsPerMeter{2834};
int32_t ypelsPerMeter{2834};
uint32_t clrUsed{0};
uint32_t clrImportant{0};
};
#pragma pack(pop)
int main() {
#ifdef _WIN32
// Set console title and icon for Windows environments
SetConsoleTitleW(L"Mandelbrot Renderer - 64 Samples Per Pixel");
#endif
long double absc, ordi, size_val;
int choice;
std::cout << "Select coordinate point (1-7): ";
if (!(std::cin >> choice)) choice = 1;
// Predefined coordinates for various Mandelbrot features
switch (choice) {
case 1: absc = -1.39966699645936; ordi = 0.0005429083913; size_val = 0.000000000000026; break;
case 2: absc = -0.691488093510181825; ordi = 0.465680729473216972; size_val = 0.0000000000000016; break;
case 3: absc = -1.26392609056234794; ordi = -0.17578764215262827; size_val = 0.000000000000023; break;
case 4: absc = -0.88380294401099034; ordi = -0.23531813998049201; size_val = 0.0000000000000019; break;
case 5: absc = 0.38923838852618047304; ordi = -0.37956875637751280668; size_val = 0.0000000000000085; break;
case 6: absc = -0.5503493176297569; ordi = 0.6259309572825709; size_val = 0.00000000000031; break;
case 7: {
ifstream ff("Mandelbrot.txt");
if (!ff.is_open()) { cerr << "Error: Mandelbrot.txt not found!" << endl; return 1; }
ff >> absc >> ordi >> size_val;
ff.close();
break;
}
default: std::cout << "Error: Invalid selection!" << std::endl; return 1;
}
const int horiz = 1920; // Output width
const int vert = 1920; // Output height
const int rowSize = (horiz * 3 + 3) & ~3; // 4-byte alignment for BMP rows
BMPHeader h;
h.width = horiz;
h.height = vert;
h.sizeImage = rowSize * vert;
h.size = h.sizeImage + 54;
// Generate color palette (sinusoidal gradient)
uint8_t pal[256][3];
for (int a = 0; a < 255; ++a) {
pal[a][0] = (uint8_t)round(127 + 127 * cos(2 * PI * a / 255.0));
pal[a][1] = (uint8_t)round(127 + 127 * sin(2 * PI * a / 255.0));
pal[a][2] = (uint8_t)round(127 + 127 * sin(2 * PI * a / 255.0));
}
pal[255][0] = 255; pal[255][1] = 255; pal[255][2] = 255; // Inner set color (white)
// Calculate step size for sub-pixel sampling (8x8 = 64 samples per pixel)
long double step = size_val / (horiz << 3);
long double absc2 = absc - step * ((horiz << 3) - 1) / 2.0;
long double ordi2 = ordi - step * ((vert << 3) - 1) / 2.0;
vector<uint8_t> allData(h.sizeImage, 0);
atomic<int> linesLeft{vert};
cout << "Rendering started using " << omp_get_max_threads() << " threads..." << endl;
#pragma omp parallel for schedule(dynamic)
for (int b = 0; b < vert; ++b) {
int nn = b << 3;
for (int a = 0; a < horiz; ++a) {
int mm = a << 3;
long z_sum[3] = {0, 0, 0};
// Supersampling loop (8x8 grid per pixel)
for (int j = 0; j < 8; ++j) {
long double n_coord = ordi2 + (nn + j) * step;
for (int i = 0; i < 8; ++i) {
long double m_coord = absc2 + (mm + i) * step;
long double c_re = m_coord, d_im = n_coord;
int t = 50000; // Max iterations
long double cc, dd;
// Main Mandelbrot escape-time loop
do {
cc = c_re * c_re;
dd = d_im * d_im;
d_im = 2 * c_re * d_im + n_coord;
c_re = cc - dd + m_coord;
t--;
} while (t > 0 && (cc + dd <= 10000.0)); // Escape radius squared = 10000
int colorIdx = (t == 0) ? 255 : (t % 255);
z_sum[0] += pal[colorIdx][0];
z_sum[1] += pal[colorIdx][1];
z_sum[2] += pal[colorIdx][2];
}
}
// Average the 64 samples and write to pixel buffer
int pixelPos = b * rowSize + a * 3;
allData[pixelPos + 0] = (uint8_t)(z_sum[0] >> 6); // sum / 64
allData[pixelPos + 1] = (uint8_t)(z_sum[1] >> 6);
allData[pixelPos + 2] = (uint8_t)(z_sum[2] >> 6);
}
// Simple progress indicator
if (--linesLeft % 10 == 0) {
#pragma omp critical
{ cout << "Lines remaining: " << linesLeft << " \r" << flush; }
}
}
// Write binary BMP data to file
ofstream f("Mandelbrot.bmp", ios::binary);
if (f.is_open()) {
f.write(reinterpret_cast<char*>(&h), 54);
f.write(reinterpret_cast<char*>(allData.data()), allData.size());
f.close();
cout << "\nFinished! Mandelbrot.bmp saved." << endl;
}
return 0;
}
|
Technical details
- Method: High-Fidelity C++ Implementation (80-bit long double precision).
- Anti-aliasing: 64x SSAA (8x8 supersampling).
- Iterations: 50,000 max.
- Software: C++ (compiled with g++), GNU C++ Compiler.
Source code
- Rosetta Code: https://rosettacode.org/wiki/Mandelbrot_set#High-Fidelity_C++_Implementation_(80-bit,_64x_SSAA,_OpenMP)
- github: https://github.com/Divetoxx/Mandelbrot
The freely distributable C++ compiler is called g++. In the source code, replace absc, ordi, and size_val with the coordinates and width specified in Description.
#include <iostream>
#include <fstream>
#include <vector>
#include <cmath>
#include <cstdint>
#include <atomic>
#include <omp.h>
using namespace std;
const double PI = 3.14159265358979323846;
#pragma pack(push, 1)
struct BMPHeader {
uint16_t type{0x4D42};
uint32_t size{0};
uint16_t reserved1{0};
uint16_t reserved2{0};
uint32_t offBits{54};
uint32_t structSize{40};
int32_t width{0};
int32_t height{0};
uint16_t planes{1};
uint16_t bitCount{24};
uint32_t compression{0};
uint32_t sizeImage{0};
int32_t xpelsPerMeter{2834};
int32_t ypelsPerMeter{2834};
uint32_t clrUsed{0};
uint32_t clrImportant{0};
};
#pragma pack(pop)
int main() {
long double absc, ordi, size_val;
absc = -0.9177640112013507; ordi = -0.2787829020420787; size_val = 0.00000000000003;
const int horiz = 1920;
const int vert = 1920;
const int rowSize = (horiz * 3 + 3) & ~3;
BMPHeader h;
h.width = horiz;
h.height = vert;
h.sizeImage = rowSize * vert;
h.size = h.sizeImage + 54;
uint8_t pal[256][3];
for (int a = 0; a < 255; ++a) {
pal[a][0] = (uint8_t)round(127 + 127 * cos(2 * PI * a / 255.0));
pal[a][1] = (uint8_t)round(127 + 127 * sin(2 * PI * a / 255.0));
pal[a][2] = (uint8_t)round(127 + 127 * sin(2 * PI * a / 255.0));
}
pal[255][0] = 255; pal[255][1] = 255; pal[255][2] = 255;
long double step = size_val / (horiz << 3);
long double absc2 = absc - step * ((horiz << 3) - 1) / 2.0;
long double ordi2 = ordi - step * ((vert << 3) - 1) / 2.0;
vector<uint8_t> allData(h.sizeImage, 0);
atomic<int> linesLeft{vert};
cout << "Starting calculation on " << omp_get_max_threads() << " threads..." << endl;
#pragma omp parallel for schedule(dynamic)
for (int b = 0; b < vert; ++b) {
int nn = b << 3;
for (int a = 0; a < horiz; ++a) {
int mm = a << 3;
long z_sum[3] = {0, 0, 0};
for (int j = 0; j < 8; ++j) {
long double n_coord = ordi2 + (nn + j) * step;
for (int i = 0; i < 8; ++i) {
long double m_coord = absc2 + (mm + i) * step;
long double c_re = m_coord, d_im = n_coord;
int t = 50000;
long double cc, dd;
do {
cc = c_re * c_re;
dd = d_im * d_im;
d_im = 2 * c_re * d_im + n_coord;
c_re = cc - dd + m_coord;
t--;
} while (t > 0 && (cc + dd <= 10000.0));
int colorIdx = (t == 0) ? 255 : (t % 255);
z_sum[0] += pal[colorIdx][0];
z_sum[1] += pal[colorIdx][1];
z_sum[2] += pal[colorIdx][2];
}
}
int pixelPos = b * rowSize + a * 3;
allData[pixelPos + 0] = (uint8_t)(z_sum[0] >> 6);
allData[pixelPos + 1] = (uint8_t)(z_sum[1] >> 6);
allData[pixelPos + 2] = (uint8_t)(z_sum[2] >> 6);
}
int current = --linesLeft;
if (current % 10 == 0 || current < 10) {
#pragma omp critical
{
cout << "Lines remaining: " << current << " \r" << flush;
}
}
}
ofstream f("Mandelbrot.bmp", ios::binary);
if (f.is_open()) {
f.write(reinterpret_cast<char*>(&h), 54);
f.write(reinterpret_cast<char*>(allData.data()), allData.size());
f.close();
cout << "\nFinished! Mandelbrot.bmp saved." << endl;
}
return 0;
}
Licensing
I, the copyright holder of this work, hereby publish it under the following license:
| This file is made available under the Creative Commons CC0 1.0 Universal Public Domain Dedication. | |
| The person who associated a work with this deed has dedicated the work to the public domain by waiving all of their rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.
|
This image has been assessed using the Quality image guidelines and is considered a Quality image.
|
Category:CC-Zero
Category:Complex quadratic map
Category:Files by User:Aokoroko
Category:Fractal art
Category:Fractals created by User: Aokoroko
Category:Free Pascal
Category:Images with Pascal source code
Category:Mandelbrot sets (detail)
Category:Misiurewicz point
Category:Near-copies of the Mandelbrot set within itself
Category:Quality images
Category:Quality images missing SDC Commons quality assessment
Category:Quality images missing SDC depicts
Category:Self-published work