Break Up to Make Up : Adding a Cubism taste to the original image.

Saturday, December 12, 2020
An interesting effect during trying to make cutting glass refraction.

Original image is 'Boats and Body of Water' by Pixabay.

An interesting effect during trying to make cutting glass refraction.

I wanted to make some image manipulation program with Processing. And I found some interesting effects during the way to the goal that was making cutting glass refraction. And I changed the destination as always. 😝

This is the creative coding of image manipulation. It adds a Cubism taste to the original image.

I used the Worley noise to draw. The reference is Mr. Shiffman's 'Worley Noise - Coding in the Cabana Challenge #4 · The Coding Train'.

I mistook and wrote a code like this. It caused overdosed saturation! And I addicted. 🤪

float m = minDist / _range;
~
n.satVal * (1.0 - m) + saturation(_img.pixels[i]) * m,


The result images.

Points on a mesh.

Points on a mesh.

Points on a mesh.

Put a little randomness.

Put a little randomness.

Put a little randomness.

Original image is 'Orange White Cat' by Pixabay.

Yet another example image.

An interesting effect during trying to make cutting glass refraction.

 


An example code of Processing.

This code does not display any images on the screen but generates image files in frames directory. Please feel free to use this example code. To see other works based on my code is my pleasure. And my honor.



/**
 * Break Up to Make Up.
 * An image processing code with Worley noise.
 *
 * @author @deconbatch
 * @version 0.1
 * @license GPL Version 3 http://www.gnu.org/licenses/
 * Processing 3.5.3
 * 2020.12.12
 */

void setup() {
  size(1080, 1080);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noLoop();
}

void draw() {

  int caseWidth  = 30;
  int baseCanvas = width - caseWidth * 2;

  PImage img = loadImage("your_photo.jpg");
  float rateSize = baseCanvas * 1.0 / max(img.width, img.height);
  img.resize(floor(img.width * rateSize), floor(img.height * rateSize));

  translate((width - img.width) / 2, (height - img.height) / 2);

  // squre mesh
  background(0.0, 0.0, 90.0, 100.0);
  drawWorley(img, getMesh(img, 30, 0.0), 0.5);
  casing(caseWidth, img.width, img.height);
  saveFrame("frames/bm0001.png");

  // with little randomness
  background(0.0, 0.0, 90.0, 100.0);
  drawWorley(img, getMesh(img, 40, 0.5), 4.0);
  casing(caseWidth, img.width, img.height);
  saveFrame("frames/bm0002.png");

  exit();
  
}

/**
 * getMesh : locate Nodes on mesh with some randomness.
 * @param _img  : original image to get color.
 * @param _step : mesh step.
 * @param _rate : lack rate, 0.0 : no lack, 1.0 totally lack.
 * @return ArrayList<Node> : holds nodes.
 */
public ArrayList<Node> getMesh(PImage _img, int _step, float _rate) {

  int   start = floor(_step * 0.5);
  ArrayList<Node> nodes = new ArrayList<Node>();
  _img.loadPixels();

  for (int fX = start; fX < _img.width; fX += _step) {
    for (int fY = start; fY < _img.height; fY += _step) {
      if (random(1.0) >= _rate) {
        // add node
        int pixIndex = floor(fY * _img.width + fX);
        nodes.add(new Node(
                           fX,
                           fY,
                           hue(_img.pixels[pixIndex]),
                           saturation(_img.pixels[pixIndex]),
                           brightness(_img.pixels[pixIndex])
                           ));
      }
    }
  }
  return nodes;
}

/**
 * drawWorley : draw 
 * @param _img   : original image.
 * @param _nodes : point's location and color.
 * @param _range : distance range, lower value will make strong result.
 */
public void drawWorley(PImage _img, ArrayList<Node> _nodes, float _range) {

  float heighValue = _img.width + _img.height;
  noFill();
  strokeWeight(1.0);
  for (int iX = 0; iX < _img.width; iX++) {
    for (int iY = 0; iY < _img.height; iY++) {
      // get nearest node
      int   minIndx = 0;
      float minDist = heighValue;
      for (int i = 0; i < _nodes.size(); i++) {
        float distance = dist(iX, iY, _nodes.get(i).x, _nodes.get(i).y);
        if (minDist > distance) {
          minIndx = i;
          minDist = distance;
        }
      }

      Node  n = _nodes.get(minIndx);
      float r = constrain(minDist / _range, 0.0, 100.0); // weird ratio
      int   i = floor(iY * _img.width + iX);
      
      stroke(
             n.hueVal,
             (n.satVal * (2.0 - r) + saturation(_img.pixels[i]) * r),
             (n.briVal * (2.0 - r) + brightness(_img.pixels[i]) * r),
             100.0
             );
      point(iX, iY);
    }
  }
}

/**
 * casing : draw fancy casing
 */
public void casing(int _casing, float _w, float _h) {
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(_casing + 4.0);
  stroke(0.0, 0.0, 30.0, 100.0);
  rect(-_casing * 0.5, -_casing * 0.5, _w + _casing, _h + _casing);
  strokeWeight(_casing);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(-_casing * 0.5, -_casing * 0.5, _w + _casing, _h + _casing);
}

/**
 * Node : draw and hold location and color.
 */
public class Node {

  public  int   x, y;   // location of point
  private float hueVal; // hue value of point
  private float satVal; // saturation value of point
  private float briVal; // brightness value of point

  Node(int _x, int _y, float _c, float _s, float _b) {
    x = _x;
    y = _y;
    hueVal = _c;
    satVal = _s;
    briVal = _b;
  }

}


/*
Copyright (C) 2020- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/



Comments

No comments :

Post a Comment