DoMewno.

Generative art processing code examples.
Close-Up Photography of Tabby Cat · Free Stock Photo

Creative coding examples.
Calico Cat · Free Stock Photo

Description of this image manipulation.

Creative coding image manipulation work made with Processing.

I tried to draw an image without the color in the original image.
I did not use primary color like RGB nor CMY, I used a +-45 degree phase difference color from the original color.
You can enjoy these results in 3 or 4 meters distance.

Processin example code.

Please feel free to use it, if you like it.
To see other works based on my code is my pleasure. And my honor.



/**
 * DoMewno.
 * Draw original color image WITHOUT original color.
 * run : processing-java --force --sketch=/path/to/DoMewno/ --run "image path"
 * 
 * @author @deconbatch
 * @version 0.1
 * Processing 3.2.1
 * 2019.03.21
 */

/**
 * main
 */
void setup() {

  size(1080, 1080);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  //  rectMode(CENTER);
  smooth();
  noLoop();
  noStroke();

}

void draw() {

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

  // I brought domino pattern parameters in class.
  DominoParams bp = new BackgroundParams();
  DominoParams ep = new EdgeParams();

  ImageLoader imgLoader = new ImageLoader(baseCanvas);
  PImage img = imgLoader.load();

  // edge detection
  int edgeAry[][] = detectEdge(img);
    
  translate((width - img.width) / 2, (height - img.height) / 2);
  background(0.0, 0.0, 90.0, 100.0);

  // draw domino pattern
  putDominos(bp, img, edgeAry);
  putDominos(ep, img, edgeAry);
  
  casing(caseWidth, img.width, img.height);
  saveFrame("frames/0001.png");

  exit();

}

/**
 * putDominos : draw pattern like domino.
 * @param  _dp       : domino pattern parameters class.
 * @param  _img      : origimal photo image.
 * @param  _edge     : detented edge information.
 */
private void putDominos(DominoParams _dp, PImage _img, int[][] _edge) {

  int   initDiv    = _dp.initDiv();

  float colorDiff = 45.0;
  int   halfDiv  = round(initDiv * 0.5);
  
  for (int xInit = 0; xInit < _img.width; xInit += initDiv) {
    for (int yInit = 0; yInit < _img.height; yInit += initDiv) {
      if (_dp.isTarget(_edge, xInit, yInit)) {

        // I want to draw diffrent color like this
        // ---------
        // | - | + |
        // ---------
        // | + | - |
        // ---------
        int xW = constrain(xInit, 0, _img.width - 1);
        int xE = constrain(xInit + halfDiv, 0, _img.width - 1);
        int yN = constrain(yInit, 0, _img.height - 1);
        int yS = constrain(yInit + halfDiv, 0, _img.height - 1);

        paintDiffCol(_img, xW, yN, halfDiv, -colorDiff); // West-North
        paintDiffCol(_img, xW, yS, halfDiv, +colorDiff); // West-South
        paintDiffCol(_img, xE, yN, halfDiv, +colorDiff); // East-North
        paintDiffCol(_img, xE, yS, halfDiv, -colorDiff); // East-South
        
      }
    }
  }
}
        
/**
 * paintDiffCol : paint rect and ellipse with different color.
 * @param  _img               : origimal photo image.
 * @param  _xCorner, _yCorner : West-North point of rect to draw.
 * @param  _size              : width and height of rect to draw.
 * @param  _colorDiff         : phase differenct of color in HSB(360).
 */
private void paintDiffCol(PImage _img, int _xCorner, int _yCorner, int _size, float _colorDiff) {

  int xTo = constrain(_xCorner + _size, 0, _img.width - 1);
  int yTo = constrain(_yCorner + _size, 0, _img.height - 1);
  
  // using RGB to calculate the average hue
  colorMode(RGB);
  int   sumCnt = 0;
  float sumRed = 0.0;
  float sumGre = 0.0;
  float sumBlu = 0.0;
  for (int sumX = _xCorner; sumX < xTo; ++sumX) {
    for (int sumY = _yCorner; sumY < yTo; ++sumY) {
      color pix = _img.pixels[sumY * _img.width + sumX];
      sumRed += red(pix);
      sumGre += green(pix);
      sumBlu += blue(pix);
      ++sumCnt;
    }
  }
  float eHue  = hue(color(sumRed / sumCnt, sumGre / sumCnt, sumBlu / sumCnt));

  // using HSB to calculate the average saturation and brightness
  // Q. Why I do not keep using RGB?
  // A. I need to calculate _colorDiff different hue value. And I don't know how to do it with RGB.
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  sumCnt = 0;
  float sumSat = 0.0;
  float sumBri = 0.0;
  for (int sumX = _xCorner; sumX < xTo; ++sumX) {
    for (int sumY = _yCorner; sumY < yTo; ++sumY) {
      color pix = _img.pixels[sumY * _img.width + sumX];
      sumSat += saturation(pix);
      sumBri += brightness(pix);
      ++sumCnt;
    }
  }
  float eSat = sumSat * 1.1 / sumCnt;
  float eBri = sumBri / sumCnt;
  float eAlp = 100.0;

  fill((eHue + 360 + _colorDiff) % 360.0, eSat, eBri, eAlp);
  rect(_xCorner, _yCorner, _size, _size);
  fill((eHue + 360 - _colorDiff) % 360.0, eSat, eBri, eAlp);
  ellipse(_xCorner + _size * 0.5, _yCorner + _size * 0.5, _size * 0.65, _size * 0.65);

      
}

/**
 * casing : draw fancy casing
 */
private 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);
  noStroke();
  noFill();
}

/**
 * detectEdge : detect edge of photo image.
 * @param  _img      : detect edge of thid image.
 * @return int[x][y] : 2 dimmension array. it holds 0 or 1, 1 = edge
 */
private int[][] detectEdge(PImage _img) {

  int edgeAry[][] = new int[_img.width][_img.height];
  for (int idxW = 0; idxW < _img.width; ++idxW) {  
    for (int idxH = 0; idxH < _img.height; ++idxH) {
      edgeAry[idxW][idxH] = 0;
    }
  }
    
  _img.loadPixels();
  for (int idxW = 1; idxW < _img.width - 1; ++idxW) {  
    for (int idxH = 1; idxH < _img.height - 1; ++idxH) {

      int pixIndex = idxH * _img.width + idxW;

      // saturation difference
      float satCenter = saturation(_img.pixels[pixIndex]);
      float satNorth  = saturation(_img.pixels[pixIndex - _img.width]);
      float satWest   = saturation(_img.pixels[pixIndex - 1]);
      float satEast   = saturation(_img.pixels[pixIndex + 1]);
      float satSouth  = saturation(_img.pixels[pixIndex + _img.width]);
      float lapSat = pow(
                         - satCenter * 4.0
                         + satNorth
                         + satWest
                         + satSouth
                         + satEast
                         , 2);

      // brightness difference
      float briCenter = brightness(_img.pixels[pixIndex]);
      float briNorth  = brightness(_img.pixels[pixIndex - _img.width]);
      float briWest   = brightness(_img.pixels[pixIndex - 1]);
      float briEast   = brightness(_img.pixels[pixIndex + 1]);
      float briSouth  = brightness(_img.pixels[pixIndex + _img.width]);
      float lapBri = pow(
                         - briCenter * 4.0
                         + briNorth
                         + briWest
                         + briSouth
                         + briEast
                         , 2);

      // hue difference
      float hueCenter = hue(_img.pixels[pixIndex]);
      float hueNorth  = hue(_img.pixels[pixIndex - _img.width]);
      float hueWest   = hue(_img.pixels[pixIndex - 1]);
      float hueEast   = hue(_img.pixels[pixIndex + 1]);
      float hueSouth  = hue(_img.pixels[pixIndex + _img.width]);
      float lapHue = pow(
                         - hueCenter * 4.0
                         + hueNorth
                         + hueWest
                         + hueSouth
                         + hueEast
                         , 2);

      // bright and saturation difference
      if (
          brightness(_img.pixels[pixIndex]) > 30.0
          && lapSat > 20.0
          ) edgeAry[idxW][idxH] = 1;

      // bright and some saturation and hue difference
      if (
          brightness(_img.pixels[pixIndex]) > 30.0
          && saturation(_img.pixels[pixIndex]) > 10.0
          && lapHue > 100.0
          ) edgeAry[idxW][idxH] = 1;

      // just brightness difference
      if (lapBri > 100.0) edgeAry[idxW][idxH] = 1;

    }
  }

  return edgeAry;
}

/**
 * ImageLoader : load and resize image
 */
public class ImageLoader {

  PImage imgInit;
  String imgPass;

  ImageLoader(int baseCanvas) {

    if (args == null) {
      // you can use your photo in ./data/your_image.jpg
      imgPass = "your_image.jpg";
    } else {
      // args[0] must be image path
      imgPass = args[0];
    }    
    imgInit = loadImage(imgPass);
      
    float rateSize = baseCanvas * 1.0 / max(imgInit.width, imgInit.height);
    imgInit.resize(floor(imgInit.width * rateSize), floor(imgInit.height * rateSize));

    println(int(imgInit.width)); // Image width
    println(int(imgInit.height)); // Image height

  }

  /**
   * load : return loaded image
   */
  public PImage load() {
    return imgInit;
  }

}

/**
 * DominoParams : holding domino pattern parameters.
 */
interface DominoParams {

  /**
   * isTarget : is this point(x, y) drawing target?
   * @return true : draw target
   */
  Boolean isTarget(int _points[][], int _x, int _y);

  /**
   * just returns parameter value
   */
  int   initDiv();

}

public class BackgroundParams implements DominoParams {
  
  public Boolean isTarget(int _points[][], int _x, int _y) {
    // every point
    return true;
  }

  public int initDiv() {
    return 40;
  }

}

public class EdgeParams implements DominoParams {

  public Boolean isTarget(int _points[][], int _x, int _y) {
    // only edge is target
    if (_points[_x][_y] == 1) {
      return true;
    }
    return false;
  }

  public int initDiv() {
    return 20;
  }
  
}

/*
Copyright (C) 2019- 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 
*/




No comments :

Post a Comment