【问题标题】:Visualizing/saving an extremely large number of pixels with可视化/保存大量像素
【发布时间】:2017-07-12 17:14:07
【问题描述】:

我用 C++ 编写了一个计算mandelbrot-set 的程序。现在我想将其可视化(将其保存在图片中)。但是当我尝试保存64k 图片时会出现一些问题。那么保存像素图片或至少可视化的最佳方法是什么?

编辑:

当我想创建一个示例64K (61440 * 34560) 图像时,会出现错误“在0x0...停止。此错误以非常高的分辨率出现。在较低的分辨率下,程序按预期工作。

#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;
}

【问题讨论】:

标签: c++ image visual-c++ sfml mandelbrot


【解决方案1】:

您的程序在调用img.create(width, height, sf::Color::Black); 期间失败。

当您进入 sf::Image::create 函数时,您最终会在这里创建 newPixels 向量,当 width * height 在您的情况下太大时,这将失败:

////////////////////////////////////////////////////////////
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 !!

结论:SFML 无法处理大图。

【讨论】:

  • 谢谢!我想我必须找到一种不同的方式来可视化它。
  • 创建几个较小的图像并将它们拼接在一起可能是一种方法。
  • 但我仍然需要使用其他东西将它们拼接在一起,因为即使我从较小的图像开始,最终图像的大小也不会改变
  • 是的,你需要别的东西。无论如何,这不是微不足道的。也许this 有帮助。
猜你喜欢
  • 1970-01-01
  • 2013-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
  • 2012-07-02
相关资源
最近更新 更多