线程 Mandelbrot 程序 C++
Threaded Mandelbrot program C++
作为序言:我目前是一名一年级学生,被允许进入某个二年级 类。因此,我目前正在争论一种我还没有真正有时间学习的语言(C++)(第一年主要学习 C#),所以这段代码可能不太漂亮。
我们的任务是双重的。首先,我们需要编写一个程序,以 PPM 格式输出 Mandelbrot 图像。为此,我遵循了 Youtube 教程 here。
作业的第二部分是使程序多线程化。本质上,该程序应该使用 4 个线程,每个线程绘制图像的四分之一。
为此,我修改了视频教程中的代码,并将 main 转换为方法。现在,我正在尝试正确制作图像的第一部分。我认为这样做的方法是调整
for (int y = 0; y < imageHeight; y++) //Rows!
{
for (int x = 0; x < imageWidth; x++) //Columns! (pixels in every row)
{
到
for (int y = 0; y < halfHeight; y++) //Rows!
{
for (int x = 0; x < halfWidth; x++) //Columns! (pixels in every row)
{
然而,程序并没有像我怀疑的那样绘制左上四分之一,而是沿着整个宽度绘制,在达到图像宽度的中间标记后重复自身,并且只沿着四分之一的高度绘制
(see image)
因为我喜欢从错误中吸取教训,所以我很想知道这里到底出了什么问题。
感谢您帮助编程新手:)
下面是完整的程序代码。
#include "stdafx.h"
#include <fstream>
#include <iostream>
int imageWidth = 512, imageHeight = 512, maxN = 255, halfWidth = 256, halfHeight = 256;
double minR = -1.5, maxR = 0.7, minI = -1.0, maxI = 1.0;
std::ofstream f_out("output_image.ppm");
int findMandelbrot(double cr, double ci, int max_iterations)
{
int i = 0;
double zr = 0.0, zi = 0.0;
while (i < max_iterations && zr * zr + zi * zi < 4.0)
{
double temp = zr * zr - zi * zi + cr;
zi = 2.0 * zr * zi + ci;
zr = temp;
i++;
}
return i;
}
double mapToReal(int x, int imageWidth, double minR, double maxR)
{
double range = maxR - minR;
return x * (range / imageWidth) + minR;
}
double mapToImaginary(int y, int imageHeight, double minI, double maxI)
{
double range = maxI - minI;
return y * (range / imageHeight) + minI;
}
void threadedMandelbrot()
{
for (int y = 0; y < halfHeight; y++) //Rows!
{
for (int x = 0; x < halfWidth; x++) //Columns! (pixels in every row)
{
//... Find the real and imaginary values of c, corresponding
// to that x,y pixel in the image
double cr = mapToReal(x, imageWidth, minR, maxR);
double ci = mapToImaginary(y, imageHeight, minI, maxI);
//... Find the number of iterations in the Mandelbrot formula
// using said c.
int n = findMandelbrot(cr, ci, maxN);
//... Map the resulting number to an RGB value.
int r = (n % 256);
int g = (n % 256);
int b = (n % 256);
//... Output it to the image
f_out << r << " " << g << " " << b << " ";
}
f_out << std::endl;
}
}
int main()
{
//Initializes file
f_out << "P3" << std::endl;
f_out << imageWidth << " " << imageHeight << std::endl;
f_out << "256" << std::endl;
//For every pixel...
threadedMandelbrot();
f_out.close();
std::cout << "Helemaal klaar!" << std::endl;
return 0;
}
您只计算图像的四分之一,因此您必须将其尺寸设置为 halfHeight
、halfWidth
或用零填充文件。当图像查看器读取文件时,它会在一行像素中显示两行,直到到达文件末尾,即图片高度的四分之一处。
要解决此问题,您只需计算图像的其他四分之三,但我建议您将计算函数与文件写入函数分开:执行线程计算,将结果放入数组中(std::array
或 std::vector
), 查找正确的颜色然后写入文件。
作为序言:我目前是一名一年级学生,被允许进入某个二年级 类。因此,我目前正在争论一种我还没有真正有时间学习的语言(C++)(第一年主要学习 C#),所以这段代码可能不太漂亮。
我们的任务是双重的。首先,我们需要编写一个程序,以 PPM 格式输出 Mandelbrot 图像。为此,我遵循了 Youtube 教程 here。
作业的第二部分是使程序多线程化。本质上,该程序应该使用 4 个线程,每个线程绘制图像的四分之一。
为此,我修改了视频教程中的代码,并将 main 转换为方法。现在,我正在尝试正确制作图像的第一部分。我认为这样做的方法是调整
for (int y = 0; y < imageHeight; y++) //Rows!
{
for (int x = 0; x < imageWidth; x++) //Columns! (pixels in every row)
{
到
for (int y = 0; y < halfHeight; y++) //Rows!
{
for (int x = 0; x < halfWidth; x++) //Columns! (pixels in every row)
{
然而,程序并没有像我怀疑的那样绘制左上四分之一,而是沿着整个宽度绘制,在达到图像宽度的中间标记后重复自身,并且只沿着四分之一的高度绘制 (see image)
因为我喜欢从错误中吸取教训,所以我很想知道这里到底出了什么问题。
感谢您帮助编程新手:)
下面是完整的程序代码。
#include "stdafx.h"
#include <fstream>
#include <iostream>
int imageWidth = 512, imageHeight = 512, maxN = 255, halfWidth = 256, halfHeight = 256;
double minR = -1.5, maxR = 0.7, minI = -1.0, maxI = 1.0;
std::ofstream f_out("output_image.ppm");
int findMandelbrot(double cr, double ci, int max_iterations)
{
int i = 0;
double zr = 0.0, zi = 0.0;
while (i < max_iterations && zr * zr + zi * zi < 4.0)
{
double temp = zr * zr - zi * zi + cr;
zi = 2.0 * zr * zi + ci;
zr = temp;
i++;
}
return i;
}
double mapToReal(int x, int imageWidth, double minR, double maxR)
{
double range = maxR - minR;
return x * (range / imageWidth) + minR;
}
double mapToImaginary(int y, int imageHeight, double minI, double maxI)
{
double range = maxI - minI;
return y * (range / imageHeight) + minI;
}
void threadedMandelbrot()
{
for (int y = 0; y < halfHeight; y++) //Rows!
{
for (int x = 0; x < halfWidth; x++) //Columns! (pixels in every row)
{
//... Find the real and imaginary values of c, corresponding
// to that x,y pixel in the image
double cr = mapToReal(x, imageWidth, minR, maxR);
double ci = mapToImaginary(y, imageHeight, minI, maxI);
//... Find the number of iterations in the Mandelbrot formula
// using said c.
int n = findMandelbrot(cr, ci, maxN);
//... Map the resulting number to an RGB value.
int r = (n % 256);
int g = (n % 256);
int b = (n % 256);
//... Output it to the image
f_out << r << " " << g << " " << b << " ";
}
f_out << std::endl;
}
}
int main()
{
//Initializes file
f_out << "P3" << std::endl;
f_out << imageWidth << " " << imageHeight << std::endl;
f_out << "256" << std::endl;
//For every pixel...
threadedMandelbrot();
f_out.close();
std::cout << "Helemaal klaar!" << std::endl;
return 0;
}
您只计算图像的四分之一,因此您必须将其尺寸设置为 halfHeight
、halfWidth
或用零填充文件。当图像查看器读取文件时,它会在一行像素中显示两行,直到到达文件末尾,即图片高度的四分之一处。
要解决此问题,您只需计算图像的其他四分之三,但我建议您将计算函数与文件写入函数分开:执行线程计算,将结果放入数组中(std::array
或 std::vector
), 查找正确的颜色然后写入文件。