File:Mandelbrot Set Image 70.png
Summary
| Description |
Русский: Фрагмент множества Мандельброта, координаты центра: -0.5503321035926785, 0.62593891595488 ширина изображения 0.00000000000026
English: Fragment of the Mandelbrot set, coordinates: -0.5503321035926785, 0.62593891595488 width 0.00000000000026
Беларуская: Фрагмент мноства Мандэльброта, каардынаты цэнтра: -0.5503321035926785, 0.62593891595488 шырыня 0.00000000000026 |
| 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.
|
Category:CC-Zero
Category:Complex quadratic map
Category:Creative Commons CC0 1.0 Universal Public Domain Dedication missing SDC copyright license
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:Self-published work
Category:Self-published work missing SDC copyright license