Why数学图像的生成

该软件能够以给定的数学公式及算法生成各种绚烂的数学图像.软件中有两种生成图像的方法:

(1)通过一种我自定义的脚本语言生成:

软件中定义一套简单易学的脚本语言,用于描述数学表达式.使用时需要先要将数学表达式写成该脚本的形式,解析脚本代码以生成相应的图像.

(2)使用软件中内置的算法:

软件中含有近百种数学图像生成的算法,如Mandelbrot,JuliaSets之类的分形算法。

软件的开发语言是C++,开发环境是VS2008,渲染使用的是D3D9。关于数学图形图像的QQ交流群: 367752815

软件下载地址:http://files.cnblogs.com/WhyEngine/WhyMathImageViewer_1_0.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:如果该文章能收集到200个赞,我便将公布其源码.

时间: 2024-07-29 16:41:08

Why数学图像的生成的相关文章

基于torch学汪峰写歌词、聊天机器人、图像着色/生成、看图说话、生成字幕

手把手教你基于torch玩转 学汪峰写词.自动聊天机器人.图像着色.图像生成.看图说话.生成字幕 作者:骁哲.李伟.小蔡.July.说明:本教程出自七月在线开发/市场团队.及七月在线5月深度学习班学员之手,有何问题欢迎加Q群交流:472899334.时间:二零一六年十月十二日. 前言 我们教梵高作画的教程发布之后,国庆7天,上百位朋友一一陆续动手尝试,大有全民DL.全民实验之感.特别是来自DL班的小蔡同学,国庆7天连做10个开源实验,并把这10个实验的简易教程(含自动聊天机器人)发布在社区上:h

如何使用编程语言画出数学图像

有一次学校有一个科技活动,其中就有一个3d打印机,当时我还很好奇它的工作原理,现在倒是能够理解一些了.要打印3维的,就要将它分割,打印平面重叠形成3维的,同理如何打印平面呢,那就要把平面分成无数的直线,同时又如何打印直线呢,最终还是回到如何打印一个点的问题上来了.我们在本子上画图像时,似乎图像是连续的,然而事实上我们也能明白,其实它是又无数多点构成的,对于计算机中也是如此,如何打印图像呢,也是要将其分割为一定的点然后打印.那么怎么对点进行遍历,将所有点都考虑到呢?这就涉及坐标的知识了,不过计算机

中小学数学卷子自动生成 - 结对项目wjy的代码分析

[实现思路] 命令行输入用户名和密码,匹配试卷难度,每个类的账号只能生成当前难度下的试卷: 根据试卷难度生成题目,主要是随机生成操作数的个数,每个操作数的形式,两个操作符之间的操作符,最后是随机生成括号,因为设计题目的合理性,所以在写随机生成的时候需要考虑到各种可能的情况: 最后生成的试卷以“年-月-日-时-分-秒.txt”命名方式生成到以用户名命名的文件夹中. [函数结构] public static void main(String[] args) static void init() st

虚拟视点图像的生成009

psnr值在30db左右,ssim在0.85左右. 源代码: #ifndef _wrapingOf3D1 #define _wrapingOf3D1 #include<iostream> #include<opencv2\opencv.hpp> #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <math.h>

C语言中将0到1000的浮点数用强制类型转换的方式生成一幅图像

搞过计算机图像的人都知道,图像中的每一个像素通常为一个整型数,它可以分成4个无符号的char类型,以表示其RGBA四个分量.一幅图像可以看做是一个二维整型数组.这里我会生成一个float数组,其数组大小为1000000,刚好1000*1000,数组内的浮点数的数值范围在0到1000.0之间,呈等差数组排列,相邻两数的差为0.001.然后将其每一个浮点数强制转化成一个整型数或三个unsigned char型,以决定像素的RGB三个通道分量,看看其生成的图像是什么样子. 前几天写了一篇文章是在C语言

YChaos生成混沌图像

YChaos是一款通过数学公式生成混沌图像的软件,展示混沌之美,数学之美.软件中定义一套简易的脚本语言,用于描述数学表达式.使用时需要先要将数学表达式写成该脚本的形式,解析脚本代码以生成相应的图形与图像.该软件与我之前写的Why数学图像生成工具和WHY数学图形可视化工具(开源)有很大关联.它们使用的是同一套数学表达式解析代码.如果你对数学生成图形图像感兴趣,欢迎加入QQ交流群: 367752815 一.软件使用 双击"YChaos图像生成软件.exe"启动软件. 软件中有两种模式:编辑

算法之美---由计算机生成的图像

发几幅由计算机生成的图像,以展示算法之美.并提供生成图像的算法代码.代码中,一部分是由C++实现,另一部分是由一种我定义的脚本语言实现. 相关软件见:Why数学图像生成工具. (1)树 1 void CPixelIFSTree::BuildPixelsMap() 2 { 3 float m[5][7]; 4 5 //'IFS码赋值 6 m[0][0] = 0.195f; m[0][1] =-0.488f; m[0][2] = 0.344f; m[0][3] = 0.433f; m[0][4] =

正与邪---25幅由算法生成的五角星图像

      五角星,又称五芒星,是指一种有五只尖角,并以五条直线画成的星星图形.做为中国人,一定对五角星有着特殊的情感.我还记得上小学的时候,曾在课桌上刻过几个五角星以表达我的爱国之情.前几天我还写过一个算法生成五星红旗.五角星是边数最少多角形,最简单画它的方法是先画一个正五边形,把各角和其对角用直线相连,并擦去原来的五边形.也可以延长原五边形的各边直到它们相交,从而得到一个大的五角星.其最大的特点是符合黄金分割0.618. 五角星被很多国家的军队作为军官(尤其是高级军官)的军衔标志使用. 一直

OPENCV图像轮廓检测

前面在图像转换的时候学到canny算子,可以检测出图像的轮廓信息,但是,该算子检测到的轮廓信息还需要我们手动的用眼睛去识别,而实际工程应用中,我们需要得到轮廓的具体数学信息,这就涉及到今天的主题,图像轮廓检测. 一.图像轮廓检测 在opencv中,轮廓对应着一系列的点的集合,opencv提供了一个函数,用来获得这些点的集合 API:void finContours(输入图像,输出轮廓点集,输出向量,int 轮廓检索模式,int 轮廓近似方法,Point 轮廓点的可选偏移量) 注:1.输入图像,是