找回密码
 立即注册

QQ登录

怎样用Processing设计出用图形和文字拼出的图案?

来源: 互动项目 奥松-Tony 2015-1-12 15:45 显示全部楼层 |阅读模式


fc79eca30535a1e47217e143cc3eace8_b.jpg

这个图的Processing代码大约90行.
  1. PFont font;
  2. String[]words={"阿扎尔","兰帕德","阿什利科尔","伊万诺维奇","切赫","特里","阿兹皮利奎塔","拉米雷斯","托雷斯","奥斯卡","米克尔","大卫路易斯","魔力鸟"};
  3. PGraphics[]wordPic=new PGraphics[words.length];
  4. PImage pic;
  5. int total=180;
  6. PGraphics manyC,finalSave;

  7. void setup(){
  8. pic=loadImage("China.png");
  9. pic.filter(THRESHOLD,0.9);
  10. pic.resize(1800,0);

  11. font=createFont("MSYHBD.TTF",240);
  12. textFont(font);
  13. float strHt=textAscent()+textDescent();
  14. println(strHt);

  15. size(pic.width,pic.height);
  16. background(255);
  17. manyC=createGraphics(pic.width,pic.height);
  18. finalSave=createGraphics(pic.width,pic.height);
  19. finalSave.smooth();

  20. for(int i=0;i<wordpic.length;i++){
  21.   wordPic[i]=createGraphics((int)textWidth(words[i]),(int)strHt);
  22.   wordPic[i].beginDraw();
  23.   wordPic[i].textFont(font);
  24.   wordPic[i].textAlign(LEFT,TOP);
  25.   wordPic[i].fill(color(0,0,255));
  26.   wordPic[i].text(words[i],0,0);
  27.   wordPic[i].endDraw();

  28.   if(wordPic[i].width>=width){
  29.     wordPic[i].resize(width*2/3,0);
  30.   }
  31. }

  32. for(int i=0;i<total;i++){

  33.   getOut:

  34.   while(wordPic[i%wordPic.length].width>10){
  35.     int tryTimes=150;
  36.     float shrinkFactor=0.7;
  37.     for(int j=0;j<trytimes;j++){
  38.       int xstart=int(random(width-wordPic[i%wordPic.length].width));
  39.       int ystart=int(random(height-wordPic[i%wordPic.length].height));
  40.       if(fitPic(wordPic[i%wordPic.length],xstart,ystart)){
  41.         if(fitCube(wordPic[i%wordPic.length],xstart,ystart)){
  42.           image(wordPic[i%wordPic.length],xstart,ystart);
  43.           finalSave.image(wordPic[i%wordPic.length],xstart,ystart);
  44.           manyC.beginDraw();
  45.           manyC.fill(0);
  46.           manyC.rect(xstart,ystart,wordPic[i%wordPic.length].width,wordPic[i%wordPic.length].height);
  47.           manyC.endDraw();
  48.           break getOut;
  49.         }
  50.       }
  51.     }
  52.     wordPic[i%wordPic.length].resize(int(wordPic[i%wordPic.length].width*shrinkFactor),0);
  53.   }
  54. }
  55. //saveFrame("Chelsea.jpg");
  56. finalSave.save("mosiac.png");
  57. }

  58. boolean fitPic(PGraphics cube,int xstart,int ystart){
  59.   boolean fitPic=true;
  60.   getOut:
  61.   for (int m=0;m<cube.width;m++){
  62.     for (int n=0;n<cube.height;n++){
  63.       if(pic.get(xstart+m,ystart+n)!=color(0)){
  64.         fitPic=false;
  65.         break getOut;
  66.       }
  67.     }
  68.   }
  69.   return fitPic;
  70. }

  71. boolean fitCube(PGraphics cube,int xstart,int ystart){
  72.   boolean fit=true;

  73.   getOut:
  74.   for (int m=0;m<cube.width;m++){
  75.     for (int n=0;n<cube.height;n++){
  76.       if(manyC.get(xstart+m,ystart+n)==color(0)){
  77.         fit=false;
  78.         break getOut;
  79.       }
  80.     }
  81.   }
  82.   return fit;
  83. }
复制代码



为方便说明,我制作了个示意图如下,这张图中的三层图片从上到下姑且命名为,图一图二图三。
909a6242b2d639f450ac936e2d70ba89_b.jpg

这三张图尺寸相同,都是建在内存里的,图一是我们需要的最终结果;图三是外部导入的底图,稍作处理后分成两块区域:可用文字填充区域(绿色)和不能填充区域(黑色);图二用来在填充过程中记录已填充区域。

1.在图一上随机找点,在随机点处划出一个和文字短语占地面积一样大的区域,然后对照图二图三里相同位置的区域,如果图三里这片区域全绿(可填充区域)并且图二里这片区域也全绿(黑方块代表已经填充了的区域,全绿表示这片区域没被其它已填充文字占据),就表示在图一中此区域可用,在图一中填上文字,图二中画上对应大小的黑方块,然后开始找填充下一个文字的地方。
如果找的这个随机点不符合上述条件,就继续随机找点,随机上几百次,比方说500次。
2.如果找了500次之后还找不到合适点,说明确实找不着能放下这么大文字的地方了,就把文字缩小一圈(我这里是把尺寸乘以了0.85)之后重复步骤1。

思路很简单,明晰这个思路之后就能在代码里稍加变化就能衍生出更多的玩法。
比如题目中的第二张骆驼图片,里面的文字大部分都是倾斜的,而我上面的代码里文字都是水平放置的。如何让文字倾斜?只要在步骤1里面加一个循环即可,即随机到一个点之后,如果该区域不满足图二图三的条件,那就让该区域旋转10度看看是否满足条件,还不满足的话继续旋转10度,以此类推直到旋转完180度。

再比如下图这种小字填在大字间隙处的图片。只要把图二方块控制图拿掉,直接用图一控制已填充区域即可达成效果。
dd579ea1849d8b9c51f0d519fd62fdbd_b.jpg


题图里的手枪图o(╯□╰)o~~的枪管处和转轮处的字是加粗的。我认为是先手工填上去的(同时填图一和图二)然后剩余部分用代码完成,当然也有可能是全图就没用代码,纯手工打造出来的。

当然这种文字拼的图片还可以更复杂些,比如下图这种,仔细看的话会发现文字按颜色浓淡分成了几个层次,同层次内的文字不重叠,但不同层次间的文字有重叠,可以猜到大致的思路是把底图分成了数个色阶,然后在每个色阶上都拼了一张图片,最后把拼成的几个色阶的图片叠在一起,当然像这种玩法对于选择底图的要求也很苛刻。
cbc4b8fa83fa74246e5bc9803088539a_b.jpg


最后,其实除了拼图案,文字还有很多其它玩法的 ^_^
5531c16e45b815db93d6be91ac496ac0_b.jpg 90a3117f8da23c82a1450780c55a2c92_b.jpg c8c6a16d22e5657627deac497cddfdb0_b.jpg


回复

使用道具 举报

大神点评1

fdk5no 2016-11-7 10:43 显示全部楼层
支持一下吧,确实是不错的贴子。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册