Image manipulation program adding a Cubism taste to the original image
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 the '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.
Put a little randomness.
Original image is 'Orange White Cat' by Pixabay.
Yet another example image.
An example code of the '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 under the terms of the GPL. 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/>
*/