Why数学图像生成工具
该软件能够以给定的数学公式及算法生成各种绚烂的数学图像.软件中有两种生成图像的方法:
(1)通过一种我自定义的脚本语言生成:
软件中定义一套简单易学的脚本语言,用于描述数学表达式.使用时需要先要将数学表达式写成该脚本的形式,解析脚本代码以生成相应的图像.
(2)使用软件中内置的算法:
软件中含有近百种数学图像生成的算法,如Mandelbrot,JuliaSets之类的分形算法。
软件的开发语言是C++,开发环境是VS2008,渲染使用的是D3D9。关于数学图形图像的QQ交流群: 367752815
软件下载地址:
1.0版本 https://files.cnblogs.com/WhyEngine/WhyMathImageViewer_1_0.zip
1.1版本 https://files.cnblogs.com/WhyEngine/WhyMathImage_1_1.zip
[一]基本功能
首先介绍下该软件的基本功能,这是一款与图像有关的软件,所以图像加载显示功能是必需的,软件支持的图像格式有:png,jpg,dds,bmp,tga,ppm。用户可以将文件直接拖入窗体内以打开图像,也可以通过菜单项或快捷方式Ctrl+F选择文件加载。下图为软件界面:
在窗体的两边有UI界面,用户可以按快捷键U来开关UI界面。
(1.1)图像颜色通道
先看下左则的UI,打开图像后,可以通过UI选择RGBA的各个通道以显示图像,或通过快捷键R,G,B,A,I来选择通道模式:
R通道图像:
G通道图像:
B通道图像:
反色图像:
(1.2)图像滤波方式
有两种图像滤波方式:(1)线性采样(2)点采样。通过下图可以看出二者的区别:
(1.3)图像大小设置:
鼠标滚轮用于控制图像的缩放。图像缩放时,是以鼠标所指的位置当做中心进行缩放的。
鼠标右键拖动可以控制图像的位置。
如下图为缩小并拖动后的图像:
还有两个按钮,其快捷键为F,O。分别表示使图像最合适的大小显示,和使图像以原始大小显示。
最后键盘F11用于控制界面的全屏切换。
[二]通过脚本生成图像
之前我写过一套数学图形可视化的工具,可以将数学表达式以图形的形式显示出来.这两套软件使用的脚本解析方式是一样的,即两个软件使用相同的脚本解析模块.关于详细语法介绍请看:数学图形可视化工具的脚本语法.我已经将该脚本解析模块的代码开源.这里脚本的后缀名为txt,主要是方便用记事本打开.目前我写了几十个脚本,放置在"Why数学图像生成工具_1_0\Scripts"目录下.脚本文件的加载方式与图像加载一样,即可以通过菜单项选择文件打开,又可以直接将文件拖入程序窗体内自动加载.
(2.1)函数名
下面是我的脚本语言中的所有函数名:
(1)单目运算函数,形如a = log(b)
"positive", // 取正,基本上没什么用,相当于(+a)
"negative", // 取负
"abs", // 求绝对值
"floor", // 整数位
"ceil", // 整数位+1
"sign", // 返回-1.0或1.0
"sgn", // 返回-1.0或0.0或1.0
"is_zero", // 返回0.0或1.0
"rand", // 返回一个随机的浮点数
"rand_int", // 返回一个随机整数
"round", // 四舍五入
"reciprocal", // 倒数"sqrt", // 开根号
"exp", //
"log", // 求对数
"ln", // log == ln
"log10",
"lg", // log10 = lg
"log2","sin", // 正弦函数
"cos", // 余弦函数
"asin", // 反正弦函数
"acos", // 反余弦函数
"arcsin", // 反正弦函数
"arccos", // 反余弦函数"tan", // 正切函数
"cot", // 余切函数
"ctg", // 余切函数
"atan", // 反正切函数
"acot", // 反余切函数
"actg", // 反余切函数
"arctan", // 反正切函数
"arccot", // 反余切函数
"arcctg", // 反余切函数"sec", // 正割函数
"csc", // 余割函数
"asec", // 反正割函数
"acsc", // 反余割函数
"arcsec", // 反正割函数
"arccsc", // 反余割函数"sinh", // 双曲正弦函数
"cosh", // 双曲余弦函数
"tanh", // 双曲正切函数
"coth", // 双曲余切函数"sh", // 双曲正弦函数
"ch", // 双曲余弦函数
"th", // 双曲正切函数
"cth", // 双曲余切函数"sech", // 双曲正割(等同于sch)
"sch", // 双曲正割
"csch", // 双曲余割(等同于xh)
"xh", // 双曲余割"factorial", // 阶乘
"erf", // 误差函数
"float_to_color", // 将浮点数转化为0-255的颜色数(2)双目运算函数,形如a = add(b, c)
"add", 相加
"sub", 相减
"multiply", 相乘
"divide", 相除"max", // 返回两数较大的一个
"min", // 返回两数较小的一个
"mod", // 求余
"pow", // 求幂
"log_ax", // 对数
"pow_sign", // 用于对负数的求幂,相当于pow(abs(a), b)"correction_gamma",// gamma校正函数
"correction_pow", // pow校正函数
"correction_sin", // sin校正函数"atan2", // 正切
"rand2", // 返回两数之间的一个随机浮点数
"rand_int2", // 返回两数之间的一个随机整数"and_bool" // 与,返回0或1.0
"or_bool", // 或,返回0或1.0
"xor_bool" // 异或,返回0或1.0
"and_byte" // 与,返回0到255.0的一个数
"or_byte", // 或,返回0到255.0的一个数
"xor_byte" // 异或,返回0到255.0的一个数
"and_word" // 与,返回0到65535.0的一个数
"or_word", // 或,返回0到65535.0的一个数
"xor_word" // 异或,返回0到65535.0的一个数"greater", // 返回0或1.0
"greater_equal", // 返回0或1.0
"less", // 返回0或1.0
"less_equal", // 返回0或1.0
"equal", // 返回0或1.0(3)三目运算符函数 形如lerp(a, b, r)
"lerp", // 线性插值
"clamp", // 限定数值的范围
"limit", // 限定数值的范围,与clamp一样
"in_range", // 数值是否范围内,返回0或1.0
"gray", // 颜色的灰度化
"add3", // 相加
"min3", // 三个之中取最小
"max3", // 三个之中取最大
"average3", // 三数平均值
"if", // 如果第一个数不为0则取第二个数,否则取第三个数
"if_else", // 与if等价(4)函数四目运算符 形如average4(a, b, c, d)
"add4", // 相加
"min4", // 四个之中取最小
"max4", // 四个之中取最大
"average4", // 四数平均值(5)函数数组运算符(输入实数数组,输出一个浮点数,如求最大值,最小值,数组加和等)
"array_add", // 相加
"array_min", // 数组之中取最小
"array_max", // 数组之中取最大
"array_ave", // 数组平均值(6)函数数组运算符(输入实数数组,输出也是实数数组,如求数组左移,数组右移,前向累加等)
"array_move_right",// 数组右移
"array_move_left", // 数组左移
"array_cumulate", // 数组累加
"array_difference",// 数组差,b[n] = a[n + params] - a[n](7)函数数组运算符(输入两个浮点数,输出实数数组)
"array_lerp", // 将数组中的数值变为等差数列
"array_rand", // 将数组中的数值变为随机浮点数
"array_rand_int", // 将数组中的数值变为随机整数
"array_set_all_values",// 将数组设置为统一值(8)函数数组运算符(输入实数数组和一个浮点数,输出一个浮点数)
"array_get_value" // 获取数组的某一个值
(2.2)脚本编辑
按下键盘F5或通过菜单选项可以打开脚本编辑对话框:
这个对话框与数学图形可视化的工具的基本上完全一样.
有一点需要注意的是:脚本中的数据都是以浮点数进行处理的.最后脚本中的r,g,b,a分别表示图像中的红色,绿色,蓝色,透明度这四个通道.并且其数值应该是0到1.0之间.而不像常规图像处理中用整数表示的0到255之间.当脚本中的数值为1.0时,相当于常规图像中的255.
(2.3)图像实例
先给大家举个脚本生成图像的简单例子:
# 确定图像大小为512*512 pixels = W:512 H:512 # 创建数组u为X轴方向 u = from 0 to (2*PI) W # 创建数组v为Y轴方向 v = from (-PI*0.5) to (PI*0.5) H x = cos(v)*sin(u) y = sin(v) z = cos(v)*cos(u) # rgb分别表示图像中对应像素的红色,绿色,蓝色通道 r = (x+1.0)/2 g = (y+1.0)/2 b = (z+1.0)/2
其生成的图像如下:
其实这个脚本代码与数学图形可视化的工具是可以通用的,看下它的3D图形:
再举个复杂点的图像例子:
pixels = W:1024 H:1024 x = from 0 to 1023 W y = from 0 to 1023 H r = and_byte((x+y), y) g = and_byte((255 + x - y), x) b = and_byte((255 - x - y), y) b = and_byte(b, x) r = r/255 g = g/255 b = b/255
然后是一幅让人眼花的图像,但生成它的数学公式很简单.
pixels = W:1024 H:1024 x = from 0 to (16*PI) W y = from 0 to (16*PI) H r = sin(x+y) g = sin(x-y) b = sin(x*y) r = r*0.5 + 0.5 g = g*0.5 + 0.5 b = b*0.5 + 0.5
下面是两幅使用sin和tan函数而生成的图像
[三]数学图像生成算法
不得不承认我的脚本功能还不够强大,只能实现些比较基础的图像,像循环迭代这样的算法目前还没办法实现.为了弥补这一不足,我将一些数学图像生成算法内置到该软件中.
(3.1)Tweetable Mathematical Art
网上有很多通过算法生成数学图像,尤其是与分形学相关的方面.我收集了近百种数学图像生成的算法,都写入该软件中.其中大部份算法来自:http://codegolf.stackexchange.com/questions/35569/tweetable-mathematical-art.它是Kyle McCormick 在 StackExchange 上发起了一个叫做 Tweetable Mathematical Art 的比赛,参赛者需要用三条代码来生成一张图片。具体地说,参赛者需要用 C++ 语言编写 RD 、 GR 、 BL 三个函数,每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数(0 ≤ i, j ≤ 1023),然后需要返回一个 0 到 255 之间的整数,表示位于 (i, j) 的像素点的颜色值。参赛者编写的代码会被插进下面这段程序当中,最终会生成一个大小为 1024×1024 的图片。
// NOTE: compile with g++ filename.cpp -std=c++11 #include <iostream> #include <cmath> #include <cstdlib> #define DIM 1024 #define DM1 (DIM-1) #define _sq(x) ((x)*(x)) // square #define _cb(x) abs((x)*(x)*(x)) // absolute value of cube #define _cr(x) (unsigned char)(pow((x),1.0/3.0)) // cube root unsigned char GR(int,int); unsigned char BL(int,int); unsigned char RD(int i,int j){ // YOUR CODE HERE } unsigned char GR(int i,int j){ // YOUR CODE HERE } unsigned char BL(int i,int j){ // YOUR CODE HERE } void pixel_write(int,int); FILE *fp; int main(){ fp = fopen("MathPic.ppm","wb"); fprintf(fp, "P6\n%d %d\n255\n", DIM, DIM); for(int j=0;j<DIM;j++) for(int i=0;i<DIM;i++) pixel_write(i,j); fclose(fp); return 0; } void pixel_write(int i, int j){ static unsigned char color[3]; color[0] = RD(i,j)&255; color[1] = GR(i,j)&255; color[2] = BL(i,j)&255; fwrite(color, 1, 3, fp); }
这代码写得很棒,给我一种重剑无锋,大道至简的感觉.参赛者只要将自己的代码写入这三个函数即可生成一幅图像文件:
unsigned char RD(int i,int j){ // YOUR CODE HERE } unsigned char GR(int i,int j){ // YOUR CODE HERE } unsigned char BL(int i,int j){ // YOUR CODE HERE }
由于它要求每个函数都不能超过140个字符,所以很多参赛者在其代码中大量使用宏来过份地简化,因而其可读性差了点.而我花了几天时间基本上将其所有代码翻写了一遍.
(3.2)图像内置算法基类
我的代码中为每一种图像生成算法创建一个类对象,所有算法类继承自同一个基类:
#ifndef _IPixelEquation_H_ #define _IPixelEquation_H_ // -------------------------------------------------------------------------------------- #include <cmath> #include <cstdlib> #include <cstring> #include <cfloat> // -------------------------------------------------------------------------------------- #define PI 3.14159265f #define EPSILON 0.000001f #define PARAMS_COUNT 4 #define RADIAN_VS_DEGREE 57.2957795130824f // 180 / PI #define DEGREE_VS_RADIAN 0.01745329251994f // PI / 180 // 通过R,G,B生成一整数表示颜色 #define MAKE_RGB(r,g,b) ( (b) | ((g) << 8) | ((r) << 16) | 0xff000000 ) // 通过R,G,B,A生成一整数表示颜色 #define MAKE_ARGB(a,r,g,b) ( (b) | ((g) << 8) | ((r) << 16) | ((a) << 24) ) #define FLOAT_1_TO_BYTE(x) ( (x) < 0.0f ? 0 : (((x) > 1.0f) ? 255 : (unsigned int)((x) * 255)) ) #define FLOAT_255_TO_BYTE(x) ( (x) < 0.0f ? 0 : (((x) > 255.0f) ? 255 : (unsigned int)(x)) ) #define BYTE_TO_FLOAT_1(x) ( (x) * 0.00392156862745f ) // x / 255 #define _sq(x) ((x)*(x)) // square #define _cb(x) fabsf((x)*(x)*(x)) // absolute value of cube #define _cr(x) powf((x),1.0f/3.0f) // cube root // -------------------------------------------------------------------------------------- class IPixelEquation { public: IPixelEquation() { m_width = 1024; m_height = 1024; memset(m_params, 0, sizeof(m_params)); } unsigned int GetWidth() const { return m_width; } unsigned int GetHeight() const { return m_height; } // 设置参数值 virtual void SetParamValue(unsigned int index, float v) { if (index < PARAMS_COUNT) { m_params[index] = v; } } // 获取参数值 float GetParamValue(unsigned int index) const { if (index < PARAMS_COUNT) { return m_params[index]; } else { return 0.0f; } } // 返回参数表示的意义 virtual const char* GetParamName(unsigned int index) const { return 0; } // 参数的取值范围属性 virtual void GetParamProperties(unsigned int index, float& _min, float& _max, float& _step) { _min = -1.0f; _max = 1.0f; _step = 0.001f; } // 恢复默认参数 virtual void ResetDefaultParams() {} // 返回数学图像名 virtual const char* GetName() const = 0; // 计算图像像素颜色 virtual unsigned int CalculatePixel(unsigned int x, unsigned int y) = 0; protected: unsigned int m_width; unsigned int m_height; float m_params[PARAMS_COUNT]; // 参数设置 };
每一个算法类中需要实现各自的unsigned int CalculatePixel(unsigned int x, unsigned int y)函数,以计算图像像素颜色.下面代码中每一行就表示一个数学图像算法类,我目前共写了81个:
1 #include "PixelEquation\PixelZero.h" 2 #include "PixelEquation\PixelRGB.h" 3 #include "PixelEquation\PixelNewtonFractal.h" 4 #include "PixelEquation\PixelColorPoint.h" 5 #include "PixelEquation\PixelOilPainting.h" 6 #include "PixelEquation\PixelMandelbrotMartin.h" 7 #include "PixelEquation\PixelMandelbrotKasten.h" 8 #include "PixelEquation\PixelMandelbrotLehman.h" 9 #include "PixelEquation\PixelLaserLight.h" 10 #include "PixelEquation\PixelLatticeCloth.h" 11 #include "PixelEquation\PixelIceFrost.h" 12 #include "PixelEquation\PixelFeigenbaumLogistic.h" 13 #include "PixelEquation\PixelCrossTarget.h" 14 #include "PixelEquation\PixelAndAddOr.h" 15 #include "PixelEquation\PixelReflectedWaves.h" 16 #include "PixelEquation\PixelColorful.h" 17 #include "PixelEquation\PixelDiabolical.h" 18 #include "PixelEquation\PixelConstructionPapers.h" 19 #include "PixelEquation\PixelCrossOnHill.h" 20 #include "PixelEquation\PixelActionPainting.h" 21 #include "PixelEquation\PixelStarryNight.h" 22 #include "PixelEquation\PixelHilbertColor.h" 23 #include "PixelEquation\PixelSharpEdges.h" 24 #include "PixelEquation\PixelRaycasterSphere.h" 25 #include "PixelEquation\PixelPalette.h" 26 #include "PixelEquation\PixelBeHappy.h" 27 #include "PixelEquation\PixelCellularAutomata.h" 28 #include "PixelEquation\PixelSchwefel.h" 29 #include "PixelEquation\PixelSierpinskiCarpets1.h" 30 #include "PixelEquation\PixelSierpinskiCarpets2.h" 31 #include "PixelEquation\PixelSierpinskiCarpets3.h" 32 #include "PixelEquation\PixelSierpinskiTriangle.h" 33 #include "PixelEquation\PixelWavyChessboard.h" 34 #include "PixelEquation\PixelBelousovZhabotinsky.h" 35 #include "PixelEquation\PixelStripes.h" 36 #include "PixelEquation\PixelSineStripes.h" 37 #include "PixelEquation\PixelNonlinearStripes.h" 38 #include "PixelEquation\PixelWaveStripes.h" 39 #include "PixelEquation\PixelBlurStripes.h" 40 #include "PixelEquation\PixelZebraStripes.h" 41 #include "PixelEquation\PixelMistakeStripes.h" 42 #include "PixelEquation\PixelStackOverflow.h" 43 #include "PixelEquation\PixelPlaidTrip.h" 44 #include "PixelEquation\PixelCameron1.h" 45 #include "PixelEquation\PixelCameron2.h" 46 #include "PixelEquation\PixelTablecloths.h" 47 #include "PixelEquation\PixelSwirlyPointy1.h" 48 #include "PixelEquation\PixelSwirlyPointy2.h" 49 #include "PixelEquation\PixelJuliaSets1.h" 50 #include "PixelEquation\PixelJuliaSets2.h" 51 #include "PixelEquation\PixelFaubiguy.h" 52 #include "PixelEquation\PixelSierpinskiPentagon.h" 53 #include "PixelEquation\PixelBuddhabrot.h" 54 #include "PixelEquation\PixelSheetMusic.h" 55 #include "PixelEquation\PixelVoronoiDiagrams.h" 56 #include "PixelEquation\PixelLyapunovFractal1.h" 57 #include "PixelEquation\PixelLyapunovFractal2.h" 58 #include "PixelEquation\PixelUnicorns.h" 59 #include "PixelEquation\PixelColouredVinyl.h" 60 #include "PixelEquation\PixelVinyl.h" 61 #include "PixelEquation\PixelSpiral.h" 62 #include "PixelEquation\PixelJoukowsky.h" 63 #include "PixelEquation\PixelXOR.h" 64 #include "PixelEquation\PixelSierpinskiSplash.h" 65 #include "PixelEquation\PixelGroovy.h" 66 #include "PixelEquation\PixelCool.h" 67 #include "PixelEquation\PixelGameScreen.h" 68 #include "PixelEquation\PixelUmberFerrule.h" 69 #include "PixelEquation\PixelPlanetaryPainter.h" 70 #include "PixelEquation\PixelPowAnd.h" 71 #include "PixelEquation\PixelHilbertRed.h" 72 #include "PixelEquation\PixelRaycasterSprite.h" 73 #include "PixelEquation\PixelPowFTW.h" 74 #include "PixelEquation\PixelBinaryFlash.h" 75 #include "PixelEquation\PixelTriangularLimbo.h" 76 #include "PixelEquation\PixelAmericanFlag.h" 77 #include "PixelEquation\PixelPurple.h" 78 #include "PixelEquation\PixelChristmasStars.h" 79 #include "PixelEquation\PixelSpotlight.h" 80 #include "PixelEquation\PixelMagnifierBall.h" 81 #include "PixelEquation\PixelWhat.h"
(3.3)图像内置算法举例
在窗体右侧的UI界面中,有一个选择列表,可以选择内置的算法以生成图像.
如果你在自定义类的CalculatePixel函数中什么也不做,将会生成一个全黑色的图像.
class CPixelZero : public IPixelEquation { public: const char* GetName() const { return "Black"; } unsigned int CalculatePixel(unsigned int x, unsigned int y) { return 0; } };
如下为生成一个彩色三角形集的图像算法:
class CPixelColorful : public IPixelEquation { public: const char* GetName() const { return "Colorful Triangle"; } unsigned int CalculatePixel(unsigned int i, unsigned int j) { unsigned int r = (i+j)/4%256; unsigned int g = (i+2*j)/4%256; unsigned int b = (2*i+j)/4%256; return MAKE_RGB(r,g,b); } };
下面是一个比较艺术的图像:
1 /* 2 unsigned char RD(int i,int j){ 3 #define r(n)(rand()%n) 4 static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):RD((i+r(2))%1024,(j+r(2))%1024):c[i][j]; 5 } 6 7 unsigned char GR(int i,int j){ 8 static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):GR((i+r(2))%1024,(j+r(2))%1024):c[i][j]; 9 } 10 11 unsigned char BL(int i,int j){ 12 static char c[1024][1024];return!c[i][j]?c[i][j]=!r(999)?r(256):BL((i+r(2))%1024,(j+r(2))%1024):c[i][j]; 13 } 14 } 15 */ 16 17 // -------------------------------------------------------------------------------------- 18 19 #define r(n)(rand()%n) 20 21 unsigned int CPixelOilPainting::CalculateRed(unsigned int i, unsigned int j) 22 { 23 static char c[1024][1024]; 24 return !c[i][j]?c[i][j]=!r(999)?r(256):CalculateRed((i+r(2))%1024,(j+r(2))%1024):c[i][j]; 25 } 26 27 unsigned int CPixelOilPainting::CalculateGreen(unsigned int i, unsigned int j) 28 { 29 static char c[1024][1024]; 30 return !c[i][j]?c[i][j]=!r(999)?r(256):CalculateGreen((i+r(2))%1024,(j+r(2))%1024):c[i][j]; 31 } 32 33 unsigned int CPixelOilPainting::CalculateBlue(unsigned int i, unsigned int j) 34 { 35 static char c[1024][1024]; 36 return !c[i][j]?c[i][j]=!r(999)?r(256):CalculateBlue((i+r(2))%1024,(j+r(2))%1024):c[i][j]; 37 } 38 39 unsigned int CPixelOilPainting::CalculatePixel(unsigned int x, unsigned int y) 40 { 41 unsigned int r = CalculateRed(x, y); 42 unsigned int g = CalculateGreen(x, y); 43 unsigned int b = CalculateBlue(x, y); 44 r &= 0xff; 45 g &= 0xff; 46 b &= 0xff; 47 return MAKE_RGB(r,g,b); 48 }
再发一个复杂点的JuliaSets分形图:
1 // -------------------------------------------------------------------------------------- 2 3 #include "PixelJuliaSets1.h" 4 5 // -------------------------------------------------------------------------------------- 6 7 /* 8 unsigned short red_fn(int i, int j){ 9 #define D(x) (x-DIM/2.)/(DIM/2.) 10 float x=D(i),y=D(j),X,Y,n=0;while(n++<200&&(X=x*x)+(Y=y*y)<4){x=X-Y+.36237;y=2*x*y+.32;}return log(n)*256;} 11 12 unsigned short green_fn(int i, int j){ 13 float x=D(i),y=D(j),X,Y,n=0;while(n++<200&&(x*x+y*y)<4){X=x;Y=y;x=X*X-Y*Y+-.7;y=2*X*Y+.27015;}return log(n)*128;} 14 15 unsigned short blue_fn(int i, int j){ 16 float x=D(i),y=D(j),X,Y,n=0;while(n++<600&&(x*x+y*y)<4){X=x;Y=y;x=X*X-Y*Y+.36237;y=2*X*Y+.32;}return log(n)*128;} 17 */ 18 19 // -------------------------------------------------------------------------------------- 20 21 #define DIM 1024 22 #define D(x) (x-512.0f)/512.0f 23 24 float CPixelJuliaSets1::CalculateRed(float i, float j) 25 { 26 float x=D(i),y=D(j); 27 float X=x*x; 28 float Y=y*y; 29 int n=0; 30 while(n<200 && (X+Y<4)) 31 { 32 x=X-Y+0.36237f; 33 y=2*x*y+0.32f; 34 35 X=x*x; 36 Y=y*y; 37 38 n++; 39 } 40 41 return logf((float)n)*256.0f; 42 } 43 44 float CPixelJuliaSets1::CalculateGreen(float i, float j) 45 { 46 float x=D(i),y=D(j); 47 float X; 48 float Y; 49 int n=0; 50 while(n<200 && (x*x+y*y)<4) 51 { 52 X=x; 53 Y=y; 54 55 x=X*X-Y*Y-0.7f; 56 y=2*X*Y+0.27015f; 57 58 n++; 59 } 60 61 return logf((float)n)*128.0f; 62 } 63 64 float CPixelJuliaSets1::CalculateBlue(float i, float j) 65 { 66 float x=D(i),y=D(j); 67 float X; 68 float Y; 69 int n=0; 70 while(n<600&&(x*x+y*y)<4) 71 { 72 X=x; 73 Y=y; 74 75 x=X*X-Y*Y+0.36237f; 76 y=2*X*Y+0.32f; 77 78 n++; 79 } 80 81 return logf((float)n)*128.0f; 82 } 83 84 unsigned int CPixelJuliaSets1::CalculatePixel(unsigned int x, unsigned int y) 85 { 86 float i = (float)x; 87 float j = (float)y; 88 89 unsigned int r = (unsigned int)CalculateRed(i, j); 90 unsigned int g = (unsigned int)CalculateGreen(i, j); 91 unsigned int b = (unsigned int)CalculateBlue(i, j); 92 93 r &= 0xff; 94 g &= 0xff; 95 b &= 0xff; 96 97 return MAKE_RGB(r,g,b); 98 }
有些图像生成算法时间复杂度很高,会很耗时,有的图像需要十几分钟才能生成.用的时候要有心理准备.
PS:如果该文章能集齐100个赞,我便公布源码.