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)
InfoField
#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

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:
Creative Commons CC-Zero 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#Mandelbrot%20Set%20Image%2070.png Category:Creative Commons CC0 1.0 Universal Public Domain Dedication missing SDC copyright licenseCategory:Self-published workCategory:Self-published work missing SDC copyright license
Category:Near-copies of the Mandelbrot set within itself Category:Fractal art Category:Fractals created by User: Aokoroko Category:Files by User:Aokoroko Category:Misiurewicz point Category:Complex quadratic map Category:Mandelbrot sets (detail) Category:Images with Pascal source code Category:Free Pascal
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