文档章节

Tweetable Mathematical Art 代码框架

__赵小刚__
 __赵小刚__
发布于 2015/08/27 16:48
字数 1836
阅读 218
收藏 2

昨晚在微信公众号看到 《有没有一段代码,让你觉得人类的智慧也可以璀璨无比》里面介绍了一个叫《Tweetable Mathematical Art》的代码游戏,看完我激动不已,这些人都太NB了。

我迫不及待要试一下,可惜该代码游戏原来的框架生成的图片是ppm格式的,ppm格式的图片在Windwos上打开比较麻烦,所以我索性写了一个生成bmp格式的代码框架。

在这个代码框架下,如果有新idea,只需在body.hpp中加入一个新类,然后用REG注册,就可以生成新的图片了。

这个代码框架支持gcc和msvc.

pic.hpp

#ifndef _PIC_HPP_
#define _PIC_HPP_

#include <cstdio>
#include <cstring>

class pic {
public:
  pic() {}
  virtual ~pic() {}

  //  ----x--------->
  //  |
  //  y
  //  |
  //  v
  virtual void set(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b) = 0;

  bool save(const char * fname) {
    char * new_name = new char[strlen(fname) + strlen(ext) + 2];
    sprintf(new_name, "%s.%s", fname, ext);

    FILE * f = fopen(new_name, "wb");
    delete [] new_name;

    if(f == NULL)
      return false;

    fwrite(p, 1, sz, f);
    fclose(f);
    return true;
  }

protected:
  unsigned char * p;
  unsigned int sz;
  unsigned int w;
  unsigned int h;
  char ext[8];
};

class ppm : public pic {
public:
  ppm(unsigned int width, unsigned int height) {
    w = width & 0xFFF;
    h = height & 0xFFF;

    char hdr[64];
    sprintf(hdr, "P6\n%u %u\n255\n", w, h);

    hdr_offset = strlen(hdr);
    sz = hdr_offset + (w * 3 * h);

    p = new unsigned char[sz];
    memcpy(p, hdr, hdr_offset);
    memset(p + hdr_offset, 0xFF, sz - hdr_offset);

    strcpy(ext, "ppm");
  }

  ~ppm() { delete [] p; }

  void set(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b) {
    if(x < w && y < h) {
      unsigned int offset = hdr_offset + (w * 3 * y) + (x * 3);
      p[offset] = r;
      p[offset + 1] = g;
      p[offset + 2] = b;
    }
  }

private:
  unsigned int hdr_offset;
};

class bmp : public pic {
public:
  bmp(unsigned int width, unsigned int height) {
    w = width & 0xFFF;
    h = height & 0xFFF;
    w3 = (w * 3 + 3) & ~3;
    sz = 54 + (w3 * h);

    p = new unsigned char[sz];
    memset(p, 0, 54);
    memset(p + 54, 0xFF, sz - 54);

    p[0] = 'B';
    p[1] = 'M';
    p[2] = sz;
    p[3] = sz >> 8;
    p[4] = sz >> 16;
    p[5] = sz >> 24;
    p[10] = 54;
    p[14] = 40;
    p[18] = w;
    p[19] = w >> 8;
    p[22] = h;
    p[23] = h >> 8;
    p[26] = 1;
    p[28] = 24;
    p[34] = sz - 54;
    p[35] = (sz - 54) >> 8;
    p[36] = (sz - 54) >> 16;
    p[37] = (sz - 54) >> 24;

    strcpy(ext, "bmp");
  }

  ~bmp() { delete [] p; }

  void set(unsigned int x, unsigned int y, unsigned char r, unsigned char g, unsigned char b) {
    if(x < w && y < h) {
      unsigned int offset = 54 + w3 * (h - 1 - y) + x * 3;
      p[offset] = b;
      p[offset + 1] = g;
      p[offset + 2] = r;
    }
  }

private:
  unsigned int w3;
};

#endif

core.hpp

#ifndef _CORE_HPP_
#define _CORE_HPP_

#include <cstdio>
#include <cstdlib>
#include <cstring>

struct core {
  core():DIM(1024) {}
  virtual ~core() {}

  virtual unsigned char RD(int i, int j) = 0;
  virtual unsigned char GR(int i, int j) = 0;
  virtual unsigned char BL(int i, int j) = 0;

  unsigned int DIM;
};

typedef core * (*CTOR)();

struct name_ctor {
  char name[64];
  CTOR ctor;
};

static name_ctor nc[128];
static unsigned int nc_num = 0;

static int reg_nc(const char * name, CTOR ctor){
  if(strlen(name) >= sizeof(nc[0].name) || nc_num >= sizeof(nc)/sizeof(nc[0])) {
    printf("Error at %s line %d\n", __FILE__, __LINE__);
    exit(1);
  }

  strcpy(nc[nc_num].name, name);
  nc[nc_num].ctor = ctor;
  nc_num++;

  return 0;
}

#define REG(NAME) \
static core * NAME##_ctor_() { return new NAME; } \
static int NAME##_reg_ = reg_nc(#NAME, NAME##_ctor_);

#endif

body.cc

#ifndef _BODY_HPP_
#define _BODY_HPP_

#include "core.hpp"
#include <cmath>

#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./3)) // cube root

struct colorful : public core {
  unsigned char RD(int i,int j){
    return (char)(_sq(cos(atan2(j-512.,i-512)/2))*255);
  }
  unsigned char GR(int i,int j){
    return (char)(_sq(cos(atan2(j-512.,i-512)/2-2*acos(-1.)/3))*255);
  }
  unsigned char BL(int i,int j){
    return (char)(_sq(cos(atan2(j-512.,i-512)/2+2*acos(-1.)/3))*255);
  }
};
REG(colorful);

struct flat : public core {
  unsigned char RD(int i,int j){
    float s=3./(j+99);
    return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127;
  }
  unsigned char GR(int i,int j){
    float s=3./(j+99);
    return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127;
  }
  unsigned char BL(int i,int j){
    float s=3./(j+99);
    return (int((i+DIM)*s+j*s)%2+int((DIM*2-i)*s+j*s)%2)*127;
  }
};
REG(flat);

struct ripple : public core {
  unsigned char RD(int i,int j){
    float s=3./(j+99);
    float y=(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;
  }
  unsigned char GR(int i,int j){
    float s=3./(j+99);
    float y=(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;
  }
  unsigned char BL(int i,int j){
    float s=3./(j+99);
    float y=(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;
  }
};
REG(ripple);

struct cripple : public core {
  unsigned char RD(int i,int j){
    float s=3./(j+99);
    float y=(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;
  }
  unsigned char GR(int i,int j){
    float s=3./(j+99);
    float y=(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;
  }
  unsigned char BL(int i,int j){
    float s=3./(j+99);
    float y=(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;
  }
};
REG(cripple);

struct randx: public core {
#define r(n)(rand()%n)
  unsigned char RD(int i,int j){
    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];
  }
  unsigned char GR(int i,int j){
    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];
  }
  unsigned char BL(int i,int j){
    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];
  }
};
REG(randx);

struct omg1: public core {
  unsigned char RD(int i,int j){
    float x=0,y=0;int k;for(k=0;k++<256;){float a=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;}return k>31?256:k*8;
  }
  unsigned char GR(int i,int j){
    float x=0,y=0;int k;for(k=0;k++<256;){float a=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;}return k>63?256:k*4;
  }
  unsigned char BL(int i,int j){
    float x=0,y=0;int k;for(k=0;k++<256;){float a=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;}return k;
  }
};
REG(omg1);

struct omg2: public core {
  unsigned char RD(int i,int j){
    double a=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;}
    return 255*pow((n-80)/800,3.);
  }
  unsigned char GR(int i,int j){
    double a=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;}
    return 255*pow((n-80)/800,.7);
  }
  unsigned char BL(int i,int j){
    double a=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;}
    return 255*pow((n-80)/800,.5);
  }
};
REG(omg2);

struct size800 : public core {
  size800() { DIM = 640; }

  unsigned char RD(int i,int j){
    return (unsigned short)sqrt((double)(_sq(i-DIM/2)*_sq(j-DIM/2))*2.0);
  }
  unsigned char GR(int i,int j){
    return (unsigned short)sqrt((double)((_sq(i-DIM/2)|_sq(j-DIM/2))*(_sq(i-DIM/2)&_sq(j-DIM/2))));
  }
  unsigned char BL(int i,int j){
    return (unsigned short)sqrt((double)(_sq(i-DIM/2)&_sq(j-DIM/2))*2.0);
  }
};
REG(size800);

#endif

main.cc

/*
http://www.zhihu.com/question/30262900
http://www.matrix67.com/blog/archives/6039
http://codegolf.stackexchange.com/questions/35569/tweetable-mathematical-art
*/

#include "body.hpp"
#include "pic.hpp"

int main(int argc, char * argv[]) {
  if(argc < 2) {
    printf("Usage: %s <-all|name> [bmp|ppm]\n", argv[0]);
    printf("name list:\n");
    for(unsigned int i = 0; i < nc_num; i++) {
      printf("\t%s\n", nc[i].name);
    }
    return 1;
  }

  for(unsigned int i = 0; i < nc_num; i++) {
    if(strcmp(argv[1], nc[i].name)==0 || strcmp(argv[1], "-all")==0) {
      core * c = nc[i].ctor();
      pic * p;

      if(argc > 2 && strcmp(argv[2],"ppm") == 0) {
        p = new ppm(c->DIM, c->DIM);
      } else {
        p = new bmp(c->DIM, c->DIM);
      }

      for(unsigned int y = 0; y < c->DIM; y++)
        for(unsigned int x = 0; x < c->DIM; x++)
          p->set(x, y, c->RD(x,y), c->GR(x,y), c->BL(x,y));

      p->save(nc[i].name);

      delete p;
      delete c;
    }
  }

  return 0;
}

Makefile

ifndef T
A=-all
endif

run :: math_art
	./math_art $A

math_art : pic.hpp core.hpp body.hpp main.cc
	g++ -Wall main.cc -lm -o math_art

clean ::
	rm -f math_art *.bmp *.ppm

build.bat

@echo off
call "C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
del *.bmp 2>nul
cl main.cc & main.exe -all & del main.obj main.exe
pause



© 著作权归作者所有

共有 人打赏支持
__赵小刚__
粉丝 5
博文 40
码字总数 19021
作品 0
成都
程序员
有没有一段代码,让你觉得人类的智慧也可以璀璨无比?

网友在知乎的一个提问帖,网址:https://www.zhihu.com/question/30262900 : 有没有一段代码,让你觉得人类的智慧也可以璀璨无比? 不一定要是完整算法,就是那种看着看着就觉得嗨爆了,惊为...

oschina
2016/03/26
7.2K
21
关于使用SSH 获取数据,对象属性取不到问题

我的问题代码: by

tianjiII
2015/10/23
1K
3
下一版本的Android移除了Dalvik并默认使用ART

就在昨晚,AOSP 代码的 master 分支上的提交显示 Dalvik 被开除,然后 ART 接替了默认的位置。这个变更是以提交 98553 和 98618 被合并的形式展现的。 前者负责把 Dalvik 从 AOSP 的 master...

hentai
2014/06/20
6.9K
35
Android动态加载入门 简单加载模式

基本信息 作者:kaedea 项目:android-dynamical-loading 初步了解Android动态加载 Java程序中,JVM虚拟机是通过类加载器ClassLoader加载.jar文件里面的类的。Android也类似,不过Android用的...

Kaede
2017/11/29
0
0
看我如何绕过android P的Restrictions on non-SDK interfaces(限制反射调用系统私有方法)

0x1:背景 android P出了个新特性,限制了对hidden field 和 method 的 反射调用,那组件化这些是不是都快要挂了。我第一感觉应该是可以绕过的,于是马上研究了下,详情可以看 https://develo...

fashaodexiaohai
07/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

SQL基础-多表操作

外键 作为外键一定要和关联主键的数据类型保持一致,被绑定的表为主表,需要绑定的表为子表 语法示例 示例方式,详细示例参考下文实例 创建外键 CREATE TABLE 动物表(ID int primary key,动物...

ZHAO_JH
3分钟前
0
0
一文深入了解Redis!

我们使用 Redis 时,会接触 Redis 的 5 种对象类型(字符串、哈希、列表、集合、有序集合),丰富的类型是 Redis 相对于 Memcached 等的一大优势。 在了解 Redis 的 5 种对象类型的用法和特点...

hensemlee
13分钟前
0
0
庄子

熙熙攘攘,即为名利~ 看淡名利,言语犀利!

柴高八斗之父
26分钟前
1
0
python标准输入输出

input() 读取键盘输入 input() 函数从标准输入读入一行文本,默认的标准输入是键盘。 input 可以接收一个Python表达式作为输入,并将运算结果返回。 print()和format()输出 format()输出...

colinux
35分钟前
0
0
Python 核心编程 (全)

浅拷贝和深拷贝 1.浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。相当于把变量里面指向的一个地址给了另一个变量就是浅拷贝,而没有创建一个新的对象,如a...

代码打碟手
47分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部