创意编程——自画像

创意编程 专栏收录该内容
9 篇文章 0 订阅

基于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;
  }
}
  • 4
    点赞
  • 3
    评论
  • 6
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值