使用Rust和并发实现一个高性能的彩色分形图案渲染

分形与 Mandelbrot

Mandelbrot 集 (Mandelbrot Set) 是复数平面上一个点的集合,以数学家 Benoît Mandelbrot 的名字命名。它是最著名的分形之一。一个复数 c 是否属于 Mandelbrot 集,取决于一个简单的迭代过程:
z n + 1 = z n 2 + c z_{n+1}=z_{n}^2+c zn+1=zn2+c

如果这个序列 z0​,z1​,z2​,… 的大小(模)保持在一定范围内(具体来说,不超过 2),那么我们就说复数 c 属于 Mandelbrot 集。如果序列的大小趋向于无穷大,那么 c 就不属于这个集合。

当我们为复数平面上的每个点 c 运行这个迭代过程,并根据它“逃逸”到无穷大的速度(或者它是否保持有界)给它上色时,我们就会得到 Mandelbrot 集那标志性的、无限复杂的图像。

那些“逃逸”得慢的点或者不逃逸的点,通常被涂成黑色,而那些“逃逸”得快的点,则根据它们的逃逸速度被赋予不同的颜色,从而形成了图像中绚丽多彩的部分。

项目准备

创建一个 Rust 项目:

cargo new mandelbrot

程序需要以下依赖:

[dependencies]
clap = { version = "4.x", features = ["derive"] }
image = "0.25.1"
num = "0.4.3"

计算 Mandelbrot 迭代

计算相对而言是比较简单的,我们需要引入 Rust 的一个数值类型库 num,从而支持复数类型。

如果对复数不熟悉,也没关系,就把实部想象成笛卡尔坐标系的 x 轴(横向),虚部想象成 y 轴(只不过以 i 为单位)。

use num::Complex;fn escape_time(c: Complex<f64>, limit: usize) -> Option<usize> {let mut z = Complex { re: 0.0, im: 0.0 };for i in 0..limit {if z.norm_sqr() > 4.0 {return Some(i);}z = z * z + c;}None
}

程序上非常简单,就是持续迭代计算 z * z + c,如果 limit 次迭代里它没有越界,我们就认为它属于 Mandelbrot 集合。如果超过了,就返回迭代的次数(即逃逸时间);如果在达到上限之前都没有超过,就返回 None,表示我们认为这个点可能属于 Mandelbrot 集。

像素到点的映射

我们需要一种方法来将图像中的每个像素(如 (25, 175))映射到复数平面上的一个点(如 -0.5 - 0.75i)。

fn pixel_to_point(bounds: (usize, usize),    // 图像尺寸 (宽, 高)pixel: (usize, usize),     // 像素坐标 (列, 行)upper_left: Complex<f64>,  // 左上角对应的复数lower_right: Complex<f64>, // 右下角对应的复数
) -> Complex<f64> {let (width, height) = (lower_right.re - upper_left.re, // 复数平面的宽度upper_left.im - lower_right.im, // 复数平面的高度);Complex {re: upper_left.re + pixel.0 as f64 * width / bounds.0 as f64,im: upper_left.im - pixel.1 as f64 * height / bounds.1 as f64,}
}

由于数学上的坐标系和计算机通常的屏幕坐标系的 y 轴方向是相反。计算机图像通常左上角是 (0, 0),y 轴向下增长,复平面通常 y 轴(虚部)向上增长。因此,在计算虚部 im 时,我们是从 upper_left.im 减去

渲染图片

要绘制 Mandelbrot 集,只需要将 escape_time 用在复平面上的点,根据逃逸时间赋以不同的灰度值。

fn render(pixels: &mut [u8],bounds: (usize, usize),upper_left: Complex<f64>,lower_right: Complex<f64>,
) {assert!(pixels.len() == bounds.0 * bounds.1);for row in 0..bounds.1 {for column in 0..bounds.0 {let point = pixel_to_point(bounds, (column, row), upper_left, lower_right);pixels[row * bounds.0 + column] = match escape_time(point, 255) {None => 0, // 属于 Mandelbrot 集,设为黑色 (0)Some(count) => 255 - count as u8, // 不属于,颜色与逃逸时间相关}}}
}

如果没有逃逸,则是黑色 0,否则就根据逃逸时间赋值 255 - count

到这里,我们就完成了核心的程序。下面的部分属于渲染和保存。

写入图片

use std::fs::File;
use image::{ExtendedColorType, ImageEncoder

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/85058.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序的软件测试用例编写指南及示例--性能测试用例

以下是针对微信小程序的性能测试用例补充,结合代码逻辑和实际使用场景,从加载性能、渲染性能、资源占用、交互流畅度等维度设计测试点,并标注对应的优化方向: 一、加载性能测试用例 测试项测试工具/方法测试步骤预期结果优化方向冷启动加载耗时微信开发者工具「性能」面板…

行为型:观察者模式

目录 1、核心思想 2、实现方式 2.1 模式结构 2.2 实现案例 3、优缺点分析 4、适用场景 5、注意事项 1、核心思想 目的&#xff1a;针对被观察对象与观察者对象之间一对多的依赖关系建立起一种行为自动触发机制&#xff0c;当被观察对象状态发生变化时主动对外发起广播&…

t009-线上代驾管理系统

项目演示地址 摘 要 使用旧方法对线上代驾管理系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在线上代驾管理系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题…

LVS-NAT 负载均衡群集

目录 简介 一、LVS 与群集技术基础 1.1 群集技术概述 1.2 负载均衡群集的分层结构 1.3 负载均衡工作模式 二、LVS 虚拟服务器核心组件与配置 2.1 LVS 内核模块与管理工具 2.2 负载调度算法解析 2.3 ipvsadm 管理工具实战 三、NFS 共享存储服务配置 3.1 NFS 服务基础…

LLaMaFactory - 支持的模型和模板 常用命令

一、 环境准备 激活LLaMaFactory环境&#xff0c;进入LLaMaFactory目录 cd LLaMA-Factoryconda activate llamafactory 下载模型 #模型下载 from modelscope import snapshot_download model_dir snapshot_download(Qwen/Qwen2.5-0.5B-Instruct) 二、启动一个 Qwen3-0.6B…

EDW2025|数据治理的神话破除——从误区到现实

在当今数据驱动的世界中&#xff0c;数据治理已成为企业成功的关键因素。然而&#xff0c;许多组织在实施数据治理时&#xff0c;常常被一些常见的误区所困扰。本文将逐一破除这些误区&#xff0c;揭示数据治理的真实面貌。 误区一&#xff1a;你需要一个大的预算&#xff01;…

AIGC与影视制作:技术革命、产业重构与未来图景

文章目录 一、AIGC技术全景&#xff1a;从算法突破到产业赋能1. **技术底座&#xff1a;多模态大模型的进化路径**2. **核心算法&#xff1a;从生成对抗网络到扩散模型的迭代** 二、AIGC在影视制作全流程中的深度应用1. **剧本创作&#xff1a;从“灵感枯竭”到“创意井喷”**2…

ReactJS 中的 JSX工作原理

文章目录 前言✅ 1. JSX 是什么&#xff1f;&#x1f527; 2. 编译后的样子&#xff08;核心机制&#xff09;&#x1f9f1; 3. React.createElement 做了什么&#xff1f;&#x1f9e0; 4. JSX 与组件的关系&#x1f504; 5. JSX 到真实 DOM 的过程&#x1f4d8; 6. JSX 与 Fr…

Spring Advisor增强规则实现原理介绍

Spring Advisor增强规则实现原理介绍 一、什么是 Advisor&#xff1f;1. Advisor 的定义与本质接口定义&#xff1a; 2. Advisor 的核心作用统一封装切点与通知构建拦截器链的基础实现增强逻辑的灵活组合 二. Sprin当中的实现逻辑1 Advisor 接口定义2 PointcutAdvisor 接口定义…

小程序32-简易双向数据绑定

在WXML中&#xff0c;普通属性的绑定是单向的&#xff0c;例如:<input value"{{value}}" /> 如果希望用户输入数据的同时改变data中的数据&#xff0c;可以借助简易双向绑定机制。在对应属性之前添加model:前缀即可: 例如<input model:value"{{value}…

Nginx网站服务:从入门到LNMP架构实战

&#x1f3e1;作者主页&#xff1a;点击&#xff01; Nginx-从零开始的服务器之旅专栏&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年5月30日14点22分 前言 说起Web服务器&#xff0c…

【maker-pdf 文档文字识别(包含ocr),安装使用完整教程】

安装环境 conda create -n maker-pdf python3.12 conda activate marker-pdf pip install modelscope pip install marker-pdf -U下载模型 from modelscope import snapshot_downloadmodel_root "models" snapshot_download("Lixiang/marker-pdf", loca…

C# 类和继承(所有类都派生自object类)

所有类都派生自object类 除了特殊的类object&#xff0c;所有的类都是派生类&#xff0c;即使它们没有基类规格说明。类object是唯 一的非派生类&#xff0c;因为它是继承层次结构的基础。 没有基类规格说明的类隐式地直接派生自类object。不加基类规格说明只是指定object为 基…

尚硅谷redis7 90-92 redis集群分片之集群扩容

90 redis集群分片之集群扩容 三主三从不够用了&#xff0c;进行扩容变为4主4从 问题&#xff1a;1.新建两个redis实例&#xff0c;怎么加入原有集群&#xff1f;2.原有的槽位分3段&#xff0c;又加进来一个槽位怎么算&#xff1f; 新建6387、6388两个服务实例配置文件新建后启…

尚硅谷-尚庭公寓部署文档

文章目录 整合版部署文档部署架构图1. 项目目录结构增加注释的 Dockerfile 配置(1) 后端服务1 Dockerfile (backend/service1/Dockerfile)(2) 后端服务2 Dockerfile (backend/service2/Dockerfile) Dockerfile 配置说明重要注意事项3. Nginx 配置(1) 主配置文件 (nginx/nginx.c…

Android Studio 介绍

如何关闭或彻底删除一个工程 基于Android Studio的android入门——如何关闭或彻底删除一个工程 搜索内容 Android Studio高效指南&#xff1a;快速查找技巧大揭秘 build命令&#xff1a;gradle app:assembleDebug 命令解析 1. 命令结构与作用 核心功能&#xff1a;该命令…

JAVA与C语言之间的差异(一)

一、代码习惯以及主函数 JAVA中{在使用的时候不要换行 public static void main(String[] args) {int[] array {1, 2, 3};for(int i 0; i < array.length; i){System.out.println(array[i] " ");}} 其次&#xff0c;以main函数为主函数&#xff1a; public …

华为OD机试真题——开放日活动/取出尽量少的球(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》 华为OD机试真题《开放…

我的3种AI写作节奏搭配模型,适合不同类型写作者

—不用内耗地高效写完一篇内容&#xff0c;原来可以这样搭配AI ✍️ 开场&#xff1a;为什么要“搭配节奏”写作&#xff1f; 很多人以为用AI写作&#xff0c;就是丢一句提示词&#xff0c;然后“等它写完”。 但你有没有遇到这些情况&#xff1a; AI写得很快&#xff0c;学境…

【知识点】第1章:程序设计基本方法

文章目录 知识点整理计算机的概念程序设计语言Python 语言概述Python 语言开发环境配置程序的基本编写方法 练习题简答题判断题 知识点整理 计算机的概念 计算机的定义&#xff1a;计算机是根据指令操作数据的设备。 计算机的两个基本特性&#xff1a; 功能性&#xff1a;计…