創意編程——自畫像

基於processing實現


**最終效果演示(已把自己臉馬賽克)**

在這裏插入圖片描述

繪製

貓貓

在這裏插入圖片描述
這是一個貓貓臉飾,繪製方法如下,eyes用於繪製眼睛,whisker用於繪製鬍鬚:

void eyes(){
  float r1 = dist(mouseX+(0),mouseY+(-0),width/2-(40),height/2+(-0));
  float si1 = (mouseX-(width/2-(40)))/r1;
  float co1 = (mouseY-height/2+(0))/r1;
  float r2 = dist(mouseX+(-0),mouseY+(-0),width/2+(40),height/2+(-0));
  float si2 = (mouseX-(width/2+(40)))/r2;
  float co2 = (mouseY-height/2+(-0))/r2;
  if(abs(r1)<20){
    ox1 = mouseX;
    oy1 = mouseY;
  }else{
    ox1 = width/2+37*si1-(-80);
    oy1 = height/2+17*co1+(-320);
  }
  if(abs(r2)<20){
    ox2 = mouseX;
    oy2 = mouseY;
  }else{
    ox2 = width/2+37*si2+(265);
    oy2 = height/2+17*co2+(-320);
  }
  fill(254,237,185);
  ellipse(width/2-(-80),height/2+(-320),110,80);
  ellipse(width/2+(265),height/2+(-320),110,80);
  
  fill(248,251,212);
  ellipse(width/2-(-80),height/2+(-320),67,76);
  ellipse(width/2+(264),height/2+(-320),67,77);
  
  fill(253,253,250);
  ellipse(width/2-(-54),height/2+(-336),36,32);
  ellipse(width/2+(242),height/2+(-336),36,32);
  
  fill(27,25,25);
  if(pressed){
    ellipse(ox1,oy1,9,49);
    ellipse(ox2,oy2,9,49);
  }
  else{
    ellipse(ox1,oy1,22,49);
    ellipse(ox2,oy2,22,49);
  }
}

void whisker(){
  fill(254,254,252);
  ellipse(width/2-(-19),height/2+(-194),156,7);
  fill(254,254,252);
  ellipse(width/2-(-19),height/2+(-165),156,7);
  fill(254,254,252);
  ellipse(width/2-(-19),height/2+(-140),156,7);
  fill(254,254,252);
  ellipse(width/2-(-315),height/2+(-194),156,7);
  fill(254,254,252);
  ellipse(width/2-(-315),height/2+(-165),156,7);
  fill(254,254,252);
  ellipse(width/2-(-315),height/2+(-140),156,7);
}

粒子

(壓縮成gif不知咋的鮮豔度降得這麼猛)
在這裏插入圖片描述
Particle類:

class Particle {
  PVector location;
  PVector velocity;
  PVector acceleration;
 
  float lifespan;
  Particle(PVector l) {
    // The acceleration
    acceleration = new PVector(0, 0.05);
    // circel's x and y ==> range
    velocity = new PVector(random(-1, 1), random(-2, 0));
    // apawn's position
    location = l.copy();
    // the circle life time
    lifespan = 255.0;
  }
  void run() {
    update();
    display();
  }
  void update() {
    velocity.add(acceleration);
    location.add(velocity);
    lifespan-=1.0;
  }
 
  boolean isDead() {
    if (lifespan <= 0) {
      return true;
    } else {
      return false;
    }
  }
  void display() {
    // border
    //stroke(0, lifespan);
    // border's weight
    //strokeWeight(1);
    float r = random(0,255);
    float g = random(0,255);
    float b = random(0,255);
    // random the circle's color
    fill(r,g,b, lifespan);
    // draw circle
    ellipse(location.x, location.y, 8, 8);
  }
}

ParticleSystem管理類:

// A class to describe a group of Particles
// An ArrayList is used to manage the list of Particles 
 
class ParticleSystem {
  ArrayList<Particle> particles;
  PVector origin;
 
  ParticleSystem(PVector position) {
    origin = position.copy();
    particles = new ArrayList<Particle>();
  }
 
  void addParticle() {
    particles.add(new Particle(origin));
  }
 
  void run() {
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = particles.get(i);
      p.run();
      if (p.isDead()) {
        particles.remove(i);
      }
    }
  }
}

交互

鼠標(按鍵與滾輪)

繪製色塊

在這裏插入圖片描述
首先創建三個PImage對象,分別用於存放原圖像,色塊處理後圖像,與原圖像與色塊圖像混合的預覽圖像。
再setup中我們將colorImg與mixImg創建爲與rawImg相同大小的圖片數據進行對應。

PImage rawImg;
PImage colorImg;
PImage mixImg;

void setup(){
  size(1000, 980);
  pressed = false;
  mouseSize = 50;
     
  time =0;
  auto = false;
  change = false;
  cat = false;
  
  rawImg = loadImage("me.png");
  
  pressedX = pressedY = 0;
  releasedX = rawImg.width;
  releasedY = rawImg.height;
  
  colorImg = createImage(rawImg.width, rawImg.height, RGB);
  colorImg.loadPixels();
  
  mixImg = createImage(rawImg.width, rawImg.height, RGB);
  mixImg.loadPixels();

  noStroke();
}

再進行預覽時我們需要得到rawImg與colorImg的混合圖像,因爲定義update_mixImg,將鼠標所在位置的特定大小區域的原圖像與色塊圖像進行混合:

void update_mixImg(){
  mixImg.set(0, 0, colorImg);
  mixImg.set(mouseX-mouseSize/2,mouseY-mouseSize/2,rawImg.get(mouseX-mouseSize/2,mouseY-mouseSize/2,mouseSize,mouseSize));
  
}

在更新colorImg時,要根據選區內顏色的平均值進行色塊處理,因此需定義get_mean_image函數計算選取內的色彩平均值

color get_mean_image(int x,int y,int w,int h){
  PImage meanImg;
  meanImg = rawImg.get(x,y,w,h);
  float meanR = 0.0f;
  float meanG = 0.0f;
  float meanB = 0.0f;
  
  for(int i=x;i<=x+w;i++){
    for(int j=y;j<=y+h;j++){
      meanR += red(rawImg.get(i,j));
      meanG += green(rawImg.get(i,j));
      meanB += blue(rawImg.get(i,j));
    }
  }
  
  meanR /= w*h;
  meanG /= w*h;
  meanB /= w*h;

  return color(meanR,meanG,meanB);
}

在獲得色彩平均值後要對colorImg進行上色,這裏採用多PImage拼接的方法以實現此目的並封裝入update_colorImg函數:

void update_colorImg(int x,int y,int w,int h){
  PImage meanImg;
  meanImg = createImage(w, h, RGB);
  color mean = get_mean_image(x,y,w,h);
  for (int i = 0; i < meanImg.pixels.length; i++) {
    meanImg.pixels[i] = mean; 
  }
  colorImg.set(x,y,meanImg);
}

貓眼樣式改變

在這裏插入圖片描述
在鼠標點擊時貓眼的瞳孔會縮小,在鼠標移動時。貓眼睛也會跟着移動。
定義pressed全局變量用於記錄鼠標是否按下,在eyes()中根據是否點下繪製不同半徑橢圓:

boolean pressed;

void mousePressed(){
  pressed = true;
}

void mouseReleased(){
  pressed = false;
}

void eyes(){
  ……
  fill(27,25,25);
  if(pressed){
    ellipse(ox1,oy1,9,49);
    ellipse(ox2,oy2,9,49);
  }
  else{
    ellipse(ox1,oy1,22,49);
    ellipse(ox2,oy2,22,49);
  }
}

下方按鈕

此處使用了controlP5,這是一個專門爲Processing提供的GUI庫,方便一些交互操作。
在這裏插入圖片描述
從左往右依次控制:色塊與預覽原圖區域大小,自動填充色快,重新選擇填充區域,貓貓臉飾顯示,粒子顯示。
其GUI實現代碼如下:

import controlP5.*;
ControlP5 cp5;
Slider2D s;

boolean auto,change,cat,particle,pressed;

void setup(){
  size(1000, 980);
  cp5 = new ControlP5(this);
  ……
  auto = false;
  change = false;
  cat = false;
  
  ……
  
  cp5.addSlider("mouseSize")
     .setPosition(40,700)
     .setRange(0,255)
     .setSize(200,20)
     ;
  
  cp5.addToggle("auto")
     .setPosition(320,700)
     .setSize(50,20)
     .setMode(ControlP5.SWITCH)
     ;
     
  cp5.addToggle("change")
     .setPosition(400,700)
     .setSize(50,20)
     .setMode(ControlP5.SWITCH)
     ;
  cp5.addToggle("cat")
     .setPosition(480,700)
     .setSize(50,20)
     .setMode(ControlP5.SWITCH)
     ;
  cp5.addToggle("particle")
     .setPosition(560,700)
     .setSize(50,20)
     .setMode(ControlP5.SWITCH)
     ;
     

  noStroke();
}

功能

自動填充

在這裏插入圖片描述
對其添加範圍內的隨機數以達到隨即填充目的

void draw(){
  ……
  if(auto){
    update_colorImg(random_width()-mouseSize/2,random_height()-mouseSize/2,mouseSize,mouseSize);
  }
  ……
}

更改隨即填充範圍

當change此bool值爲true即下方選項選中時可以更改範圍,達到更改隨即填充位置目的
在這裏插入圖片描述
代碼如下:

void mousePressed(){
  pressed = true;
  if(change){
    pressedX = mouseX;
    pressedY = mouseY;
  }
}

void mouseReleased(){
  pressed = false;
  if(change){
    releasedX = mouseX;
    releasedY = mouseY;
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章