扫我~扫我~

获取更多资讯

    查看: 2388|回复: 1

    [互动项目] 怎样用Processing设计出用图形和文字拼出的图案?

      [复制链接]

    10

    主题

    102

    帖子

    413

    积分

    小松鼠

    Rank: 7Rank: 7Rank: 7

    积分
    413
    发表于 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


    回复

    使用道具 举报

    0

    主题

    1

    帖子

    37

    积分

    小松籽

    Rank: 1

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

    使用道具 举报

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

    本版积分规则

    快速回复 返回顶部 返回列表