0

I made a program in C++ which calculates the mandelbrot-set. Now I want to visualize it (save it in a picture). But when I try to save a 64k picture some problems come up. So what is the best way to save a picture of the pixels or at least to visual it?

Edit:

When I want to create a for Example 64K (61440 * 34560) image there will be the error "Access violation while writing at the position 0x0..." (originally on German and translated) and the program stops. This error appears with very high resolution. On lower resolutions the program works as it is supposed to.

#include <SFML\Graphics.hpp>
#include <stdlib.h>
#include <complex>
#include <cmath>
#include <thread>

//4K :   3840 *  2160
//8K :   7680 *  4320
//16K:  15360 *  8640
//32K:  30720 * 17280
//64K:  61440 * 34560
//128K:122880 * 69120


const unsigned long width  = 61440; //should be dividable by ratioX & numberOfThreads!
const unsigned long height = 34560; //should be dividable by ratioY & numberOfThreads!

const unsigned int maxIterations = 500;

const unsigned int numberOfThreads = 6;

const int maxWidth = width / 3;
const int maxHeight = height / 2;
const int minWidth = -maxWidth * 2;
const int minHeight = -maxHeight;

const double ratioX = 3.0 / width;
const double ratioY = 2.0 / height;

sf::Image img = sf::Image();


int getsGreaterThan2(std::complex<double> z, int noIterations) {
    double result;
    std::complex<double> zTmp = z;
    std::complex<double> c = z;
    for (int i = 1; i != noIterations; i++) {
        zTmp = std::pow(z, 2) + c;
        if (zTmp == z) {
            return 0;
        }
        z = std::pow(z, 2) + c;
        result = std::sqrt(std::pow(z.real(), 2) + std::pow(z.imag(), 2));
        if (result > 2) {
            return i;
        }
    }
    return 0;
}


void fillPixelArrayThreadFunc(int noThreads, int threadNr) { //threadNr ... starts from 0

    double imgNumber;
    double realNumber;

    double tmp;

    long startWidth = ((double)width) / noThreads * threadNr + minWidth;
    long endWidth = startWidth + width / noThreads;

    for (long x = startWidth; x < endWidth; x++) {
        imgNumber = x * ratioX;
        for (long y = minHeight; y < maxHeight; y++) {
            realNumber = y * ratioY;
            long xArray = x - minWidth;
            long yArray = y - minHeight;
            tmp = getsGreaterThan2(std::complex<double>(imgNumber, realNumber), maxIterations);
            if (tmp == 0) {
                img.setPixel(xArray, yArray, sf::Color(0, 0, 0, 255));
            }
            else {
                img.setPixel(xArray, yArray, sf::Color(tmp / maxIterations * 128, tmp / maxIterations * 128, tmp / maxIterations * 255, 255));
            }
        }
    }
}

int main() {
    img.create(width, height, sf::Color::Black);

    std::thread *threads = new std::thread[numberOfThreads];
    for (int i = 0; i < numberOfThreads; i++) {
        threads[i] = std::thread(std::bind(fillPixelArrayThreadFunc, numberOfThreads, i));
    }
    for (int i = 0; i < numberOfThreads; i++) {
        threads[i].join();
    }

    img.saveToFile("filename.png");
    return 1;
}
Barry Michael Doyle
  • 9,333
  • 30
  • 83
  • 143
SgtDomo
  • 1
  • 1
  • Welcome to stackoverflow.com. Please take some time to read [the help pages](http://stackoverflow.com/help), especially the sections named ["What topics can I ask about here?"](http://stackoverflow.com/help/on-topic) and ["What types of questions should I avoid asking?"](http://stackoverflow.com/help/dont-ask). Also please [take the tour](http://stackoverflow.com/tour) and [read about how to ask good questions](http://stackoverflow.com/help/how-to-ask). Lastly please learn how to create a [Minimal, Complete, and Verifiable Example](http://stackoverflow.com/help/mcve). – Some programmer dude Feb 22 '17 at 15:17
  • 5
    _when I try to save a 64k picture some problems come up_... And what exactly are these problems? You cannot expect anyone to give a valid answer with such a vague description. – Jabberwocky Feb 22 '17 at 15:19
  • What picture format are you saving as: JPEG? TIFF? PNG? GIF? BMP? WMF? Are there any size limitations for the format you are using? – Thomas Matthews Feb 22 '17 at 15:27
  • I am sorry for the bad explaination. It was rather meant as a general question of how to save it properly (which file-format/methods). But I will upload my code shortly. – SgtDomo Feb 22 '17 at 15:52
  • **Q:** _how to save it properly (which file-format/methods)_? **A:** by writing the correct code for the file-format (jpeg, bmp, or whatever) you want. Sorry, but your question Is really too general, it's somewhat like asking: _How do I write a text processor?_. – Jabberwocky Feb 22 '17 at 15:57
  • 1
    Did you run it with a debugger ? – Jabberwocky Feb 22 '17 at 16:13
  • TIFF has an extension for extremely large images, and you want to be using that. – Malcolm McLean Feb 22 '17 at 16:13
  • @MichaelWalz I used the debugger of Visual Studio 2015 – SgtDomo Feb 22 '17 at 16:24
  • And __where__ did it crash ? – Jabberwocky Feb 22 '17 at 16:36
  • @MichaelWalz It crashed at "img.setPixel(xArray, yArray, sf::Color(tmp / maxIterations * 128, tmp / maxIterations * 128, tmp / maxIterations * 255, 255));" (Line 75 in fillPixelArrayThreadFunc) – SgtDomo Feb 22 '17 at 16:38
  • @SgtDomo this looks like a problem in `img.setPixel` which is not your code. So it's certainly a bug or a limitation in SFML. Maybe you should compile your program as 64 bit program. – Jabberwocky Feb 22 '17 at 16:56
  • @MichaelWalz as far as I know I already compile it as a 64bit program – SgtDomo Feb 22 '17 at 17:03
  • @SgtDomo I'm compiling it as 32 bit and your program boils down allocating 4198498343 bytes which cannot be handled. BTW: have a look in the Visual Studio Output window: I'm getting this message: `Exception thrown at 0x75BFC41F in testco.exe: Microsoft C++ exception: std::bad_alloc at memory location 0x0069F65C.`. – Jabberwocky Feb 22 '17 at 17:11
  • @MichaelWalz I think I'm getting the same message (how I already said, it's unfortunately on german). But I'm running it as debug with x64 which is 64bit, right? – SgtDomo Feb 22 '17 at 17:14
  • @SgtDomo, yes it's 64 bit. Try to step through the SFML code, but it's certainly some limitation. With 122'880 * 69'120 pixels (= 8'493'465'600) and 3 bytes per pixel you need to allocate 25'480'396'800 bytes ~24 Gb for the image and that's probably more than your system can handle. Just try `malloc(24000000000)` and look if that works. – Jabberwocky Feb 22 '17 at 17:22

1 Answers1

0

Your program fails during the call img.create(width, height, sf::Color::Black);.

When you step into the sf::Image::create function you end up here where the newPixels vector is created, this simply fails when width * height is too big as in your case:

////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Color& color)
{
    if (width && height)
    {
        // Create a new pixel buffer first for exception safety's sake
        std::vector<Uint8> newPixels(width * height * 4);
                                     ^61440* ^34560 = 8'493'465'600 bytes !!

Conclusion: SFML cannot handle huge images.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Thank you! I guess I have to find a different way to visualize it. – SgtDomo Feb 22 '17 at 17:51
  • Creating several smaller images and stitching them together might be a way to go. – Jabberwocky Feb 22 '17 at 17:54
  • but I would still have to use something else to stitch them together, because even if I begin with smaller images, the size of the end-image won't change – SgtDomo Feb 22 '17 at 17:56
  • Yes you need something else. Anyway this is not trivial. Maybe [this](https://sites.google.com/site/openimageio/home) helps. – Jabberwocky Feb 22 '17 at 18:14