0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如果让程序自动来填写每一个像素点,最后会是一副什么画呢?

Android编程精选 来源:小林coding 作者:烧茄子 2022-04-13 14:59 次阅读

Hi,大家好。

我们知道,在计算机中要显示颜色,一般都是用R、G、B三个0-255范围内的整数来描述。

89413620-ba77-11ec-aa7f-dac502259ad0.png

这一点,即便你不是从事前端、客户端这些与界面交互相关的开发工作,也应该知道。

也就是说,你现在在屏幕上看到的任何一个像素点的颜色,都可以用RGB三个整数值来表示。

那就有一个有趣的问题:如果让程序自动来填写每一个像素点,最后会是一副什么画呢?

最近我在知乎就看到了这么一个有趣的话题,看完真的让人称奇,独乐乐不如众乐乐,分享给大家。

事情是这么一回事:

国外有个大佬在StackExchange上发起了一个叫做 Tweetable Mathematical Art 的比赛。

参赛者需要用C++编写代表三原色的RD、GR、BL三个函数,每个函数都不能超过 140 个字符。每个函数都会接到 i 和 j 两个整型参数(0 ≤ i, j ≤ 1023),然后需要返回一个 0 到 255 之间的整数,表示位于 (i, j) 的像素点的颜色值。

举个例子,如果 RD(0, 0) 和 GR(0, 0) 返回的都是 0 ,但 BL(0, 0) 返回的是 255 ,那么图像的最左上角那个像素就是蓝色。

参赛者编写的代码会被插进下面这段程序当中(我做了一些细微的改动),最终会生成一个大小为 1024×1024 的图片。

//NOTE:compilewithg++filename.cpp-std=c++11
#include
#include
#include
#defineDIM1024
#defineDM1(DIM-1)
#define_sq(x)((x)*(x))//square
#define_cb(x)abs((x)*(x)*(x))//absolutevalueofcube
#define_cr(x)(unsignedchar)(pow((x),1.0/3.0))//cuberoot

unsignedcharGR(int,int);
unsignedcharBL(int,int);

unsignedcharRD(inti,intj){
//YOURCODEHERE
}
unsignedcharGR(inti,intj){
//YOURCODEHERE
}
unsignedcharBL(inti,intj){
//YOURCODEHERE
}

voidpixel_write(int,int);
FILE*fp;
intmain(){
fp=fopen("MathPic.ppm","wb");
fprintf(fp,"P6
%d%d
255
",DIM,DIM);
for(intj=0;jfor(inti=0;ireturn0;
}
voidpixel_write(inti,intj){
staticunsignedcharcolor[3];
color[0]=RD(i,j)&255;
color[1]=GR(i,j)&255;
color[2]=BL(i,j)&255;
fwrite(color,1,3,fp);
}

我选了一些自己比较喜欢的作品,放在下面和大家分享。首先是一个来自 Martin Büttner 的作品:

8950cdba-ba77-11ec-aa7f-dac502259ad0.jpg

它的代码如下:

unsignedcharRD(inti,intj){
return(char)(_sq(cos(atan2(j-512,i-512)/2))*255);
}

unsignedcharGR(inti,intj){
return(char)(_sq(cos(atan2(j-512,i-512)/2-2*acos(-1)/3))*255);
}

unsignedcharBL(inti,intj){
return(char)(_sq(cos(atan2(j-512,i-512)/2+2*acos(-1)/3))*255);
}

同样是来自 Martin Büttner 的作品:

895d3dde-ba77-11ec-aa7f-dac502259ad0.jpg

这是目前暂时排名第一的作品。它的代码如下:

unsignedcharRD(inti,intj){
#definer(n)(rand()%n)
staticcharc[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];
}

unsignedcharGR(inti,intj){
staticcharc[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];
}

unsignedcharBL(inti,intj){
staticcharc[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];
}

下面这张图片仍然出自 Martin Büttner 之手:

896ae57e-ba77-11ec-aa7f-dac502259ad0.jpg

难以想象, Mandelbrot 分形图形居然可以只用这么一点代码画出:

unsignedcharRD(inti,intj){
floatx=0,y=0;intk;for(k=0;k++<256;){floata=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}
returnlog(k)*47;
}

unsignedcharGR(inti,intj){
floatx=0,y=0;intk;for(k=0;k++<256;){floata=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}
returnlog(k)*47;
}

unsignedcharBL(inti,intj){
floatx=0,y=0;intk;for(k=0;k++<256;){floata=x*x-y*y+(i-768.0)/512;y=2*x*y+(j-512.0)/512;x=a;if(x*x+y*y>4)break;}
return128-log(k)*23;
}

Manuel Kasten 也制作了一个 Mandelbrot 集的图片,与刚才不同的是,该图描绘的是 Mandelbrot 集在某处局部放大后的结果:

897933f4-ba77-11ec-aa7f-dac502259ad0.jpg

它的代码如下:

unsignedcharRD(inti,intj){
doublea=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880)
{b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;}
return255*pow((n-80)/800,3.);
}

unsignedcharGR(inti,intj){
doublea=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880)
{b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;}
return255*pow((n-80)/800,.7);
}

unsignedcharBL(inti,intj){
doublea=0,b=0,c,d,n=0;
while((c=a*a)+(d=b*b)<4&&n++<880)
{b=2*a*b+j*8e-9-.645411;a=c-d+i*8e-9+.356888;}
return255*pow((n-80)/800,.5);
}

这是 Manuel Kasten 的另一作品:

89866c22-ba77-11ec-aa7f-dac502259ad0.jpg

生成这张图片的代码很有意思:函数依靠 static 变量来控制绘画的进程,完全没有用到 i 和 j 这两个参数!

unsignedcharRD(inti,intj){
staticdoublek;k+=rand()/1./RAND_MAX;intl=k;l%=512;returnl>255?511-l:l;
}

unsignedcharGR(inti,intj){
staticdoublek;k+=rand()/1./RAND_MAX;intl=k;l%=512;returnl>255?511-l:l;
}

unsignedcharBL(inti,intj){
staticdoublek;k+=rand()/1./RAND_MAX;intl=k;l%=512;returnl>255?511-l:l;
}

这是来自 githubphagocyte 的作品:

8993b03a-ba77-11ec-aa7f-dac502259ad0.jpg

它的代码如下:

unsignedcharRD(inti,intj){
floats=3./(j+99);
floaty=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return(int((i+DIM)*s+y)%2+int((DIM*2-i)*s+y)%2)*127;
}

unsignedcharGR(inti,intj){
floats=3./(j+99);
floaty=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return(int(5*((i+DIM)*s+y))%2+int(5*((DIM*2-i)*s+y))%2)*127;
}

unsignedcharBL(inti,intj){
floats=3./(j+99);
floaty=(j+sin((i*i+_sq(j-700)*5)/100./DIM)*35)*s;
return(int(29*((i+DIM)*s+y))%2+int(29*((DIM*2-i)*s+y))%2)*127;
}

这是来自 githubphagocyte 的另一个作品:

89a4472e-ba77-11ec-aa7f-dac502259ad0.jpg

这是一张使用 diffusion-limited aggregation 模型得到的图片,程序运行起来要耗费不少时间。代码很有意思:巧妙地利用宏定义,打破了函数与函数之间的界限,三段代码的字数限制便能合在一起使用了。

unsignedcharRD(inti,intj){
#defineDDIM
#defineMm[(x+D+(d==0)-(d==2))%D][(y+D+(d==1)-(d==3))%D]
#defineRrand()%D
#defineBm[x][y]
return(i+j)?256-(BL(i,j))/2:0;
}

unsignedcharGR(inti,intj){
#defineAstaticintm[D][D],e,x,y,d,c[4],f,n;if(i+j<1){for(d=D*D;d;d--){m[d%D][d/D]=d%6?0:rand()%2000?1:255;}for(n=1
returnRD(i,j);
}

unsignedcharBL(inti,intj){
A;n;n++){x=R;y=R;if(B==1){f=1;for(d=0;d<4;d++){c[d]=M;f=fif(f>2){B=f-1;}else{++e%=4;d=e;if(!c[e]){B=0;M=1;}}}}}returnm[i][j];
}

最后这张图来自 Eric Tressler:

89b672b4-ba77-11ec-aa7f-dac502259ad0.jpg

这是由 logistic 映射得到的 Feigenbaum 分岔图。和刚才一样,对应的代码也巧妙地利用了宏定义来节省字符:

unsignedcharRD(inti,intj){
#defineAfloata=0,b,k,r,x
#defineBinte,o
#defineC(x)x>255?255:x
#defineRreturn
#defineDDIM
RBL(i,j)*(D-i)/D;
}

unsignedcharGR(inti,intj){
#defineEDM1
#defineFstaticfloat
#defineGfor(
#defineHr=a*1.6/D+2.4;x=1.0001*b/D
RBL(i,j)*(D-j/2)/D;
}

unsignedcharBL(inti,intj){
Fc[D][D];if(i+j<1){A;B;G;a0.1){Gb=0;b0;k1-x);if(k>D/2){e=a;o=(E*x);c[e][o]+=0.01;}}}}}RC(c[j][i])*i/D;
}

怎么样,短短几行代码,就能画出如此绚烂的图像,你有没有什么脑洞大开的想法,可以复制上面的代码来试一试啊!

-End-

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 函数
    +关注

    关注

    3

    文章

    4310

    浏览量

    62458
  • C++
    C++
    +关注

    关注

    22

    文章

    2105

    浏览量

    73516
  • 代码
    +关注

    关注

    30

    文章

    4758

    浏览量

    68380

原文标题:这几行代码,真的骚!

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    高斯滤波和均值滤波的区别

    。 高斯滤波的核心思想是对图像中的每一个像素点,用其邻域内像素的加权平均灰度值替代该的灰度值,权重由高斯函数决定,距离中心
    的头像 发表于 09-29 09:40 504次阅读

    高斯滤波和双边滤波的区别

    思想是对图像中的每一个像素点,用其邻域内像素的加权平均灰度值替代该的灰度值。 高斯滤波的权重由高斯函数决定,距离中心
    的头像 发表于 09-29 09:37 323次阅读

    显示器的像素间距越小,显示效果越好吗

    像素间距(Pixel Pitch) 是指LED显示屏或LCD等显示器上相邻两像素点之间的距离,通常以毫米(mm)为单位表示。像素间距直接决定了屏幕上能够显示的最小细节和图像的细腻程度
    的头像 发表于 08-10 09:56 916次阅读

    高光谱相机检测手机背板颜色均匀性

    高光谱成像技术是项新技术,传统的光谱分析技术只能做局部平均光谱分析,而高光谱能够做到整幅图的各个光谱分析。成像光谱有凝视成像型、推帚型、摆扫型。它能够在生成一副图像的同时获取这副图像每个
    的头像 发表于 07-30 15:46 263次阅读
    高光谱相机检测手机背板颜色均匀性

    DSP教学实验箱_数字图像处理操作_案例分享:5-13 灰度图像二值化

    像素点1灰度值+...+像素点n灰度值)/ n = 像素点平均值avg,然后每一个像素点与a
    发表于 07-25 15:03

    FPGA verilog HDL实现中值滤波

    )计数器控制模块,主要用于获得中心像素点的地址信息。 (1)系统模块开始信号之后开始获取第一个中心像素点,注意初始化信号值和系统开始的信号值的区别; (2)该时刻得到的的数据将在下一个
    发表于 06-18 18:50

    STM32F407插入USB设备后会发生DISCNT中断,这是为什么

    我的工程基于STM32F407平台,用的stm32的官方库;在usb在hs、host 模式下,上电时未插入USB设备,但是程序会发生HPRTINT中断。插入USB设备后会发生
    发表于 04-26 07:08

    freertos任务创建,每一个任务分配的内存是多大才好,怎么计算

    小白刚刚接触freertos,想问下就创建任务而言,每一个任务分配的内存是多大才好,怎么计算? 另外,每个任务的执行周期怎么确定?在任务里面放延时函数吗?
    发表于 04-23 06:39

    touchgfx显示的时候,在像素点差异比较大的地方显示错误怎么解决?

    显存是外挂SDRAM,显示是LTDC驱动800*480,GUI是touchgfx生成的,在显示的时候,在像素点差异比较大的地方,显示错误,都是显示单色R或G,求大佬!!!
    发表于 03-28 06:42

    如何看懂MOS管的每一个参数

    那么结温和热阻有什么用?--半导体器件主要通过热传递的方式对元件本身进行散热,当芯片温度升高,超过结温后会导致元件损坏。
    发表于 03-18 10:44 1615次阅读
    如何看懂MOS管的<b class='flag-5'>每一个</b>参数

    基于HTTP/3构建SSH协议会是什么样

    来自UCLouvain的François Michel 和Olivier Bonaventure在研究中思考了问题:如果使用最新的网络技术重新设计SSH协议,那新协议
    的头像 发表于 02-20 17:07 636次阅读
    基于HTTP/3构建SSH协议<b class='flag-5'>会是</b>什么样<b class='flag-5'>呢</b>?

    openocd怎么适配新的Flash驱动

    我用的是蜂鸟仿真器,芯片内核是芯來的risc-v内核,目前这个芯片的flash在openocd上没有对应的驱动,我想请教下怎么样openocd可以支持这个flash驱动,这样我可以在IDE上把
    发表于 01-15 07:56

    智能外控集成LED光源WS2812B-V5/W产品手册

      WS2812B-V5/W是集控制电路与发光电路于体的智能外控LED光源。其外型与5050LED灯珠相同,每个元件即为
    发表于 01-12 15:36 1次下载

    用AD9970采集CCD的像素,CLPOB与PBLK具体是用在像素的哪个位置?

    最近在搞项目,用AD9970采集CCD的像素,但是关于AD9970的配置我有点不明白,CLPOB与PBLK具体是用在像素的哪个位置,
    发表于 01-10 07:04

    LED显示屏各种计算公式

    每个像素点每一个相邻像素点之间的中心距离;每个像素点可以是颗LED灯[如:PH10(1R)]、两颗LED灯[如:PH16(2R)]、三颗
    的头像 发表于 12-11 13:46 2296次阅读