PsychedeliCat


With the image from
Fat Cat with Greens in Sunbeam
http://www.photos-public-domain.com/2010/08/28/fat-cat-with-greens-in-sunbeam/




With the image from
Cat and Kitten looking out Door
http://www.photos-public-domain.com/2010/08/28/cat-and-kitten-looking-out-door/


About this code.

I learned how to manipulate images on Processing. And it's my first image manipulation program.

I wrote codes to fetch images via Google Custom Search.
You can change loadImage() to use your image in the data directory.
So you can easily make your own "PsychedeliCow", "PsychedeliChewbacca", "PsychedeliCateBlanchett" or others. ;-)

Processing example code.


// PsychedeliCat
// Processing 3.2.1
// 2017.05.21

import java.net.*;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.io.*;
import java.util.Properties;
import java.util.Random;
import java.util.regex.*;

/* ---------------------------------------------------------------------- */
abstract class PshapeElement {

  PShape anElement;
  float elementColor, elementSaturation, elementBright, elementAlpha;
  
  PshapeElement() {
    anElement = pscreateElement();
    elementColor = 0;
    elementSaturation = 0;
    elementBright = 0;
    elementAlpha = 0;
  }

  abstract PShape pscreateElement();

  void setElementFill(float pcolor, float psaturation, float pbright, float palpha) {
    elementColor = pcolor;
    elementSaturation = psaturation;
    elementBright = pbright;
    elementAlpha = palpha;
    resetColor();
  }

  void resetColor() {
    anElement.setFill(color(elementColor, elementSaturation, elementBright, elementAlpha));
  }

  void changeColor(float scolor) {
    elementColor = scolor;
    resetColor();
  }

  void changeBright(float sbright) {
    elementBright = sbright;
    resetColor();
  }

  void resetSize() {
    anElement.resetMatrix();
  }

  void changeSize(float scaleX, float scaleY) {
    anElement.scale(scaleX, scaleY);
  }

  void rotate(float radX) {
    anElement.rotate(radX);
  }

  void show() {
    shape(anElement);
  }

}

/* ---------------------------------------------------------------------- */
class BoxBrush extends PshapeElement {
  
  BoxBrush() {
    super();
  }

  PShape pscreateElement() {

    noStroke();
    PShape psDp = createShape(RECT, -3, -3, 6, 6);
    return psDp;

  }

}

/* ---------------------------------------------------------------------- */
class RoundBrush extends PshapeElement {
  
  RoundBrush() {
    super();
  }

  PShape pscreateElement() {

    noStroke();
    PShape psDp = createShape(ELLIPSE, 0, 0, 6, 8);
    return psDp;

  }

}

/* ---------------------------------------------------------------------- */
class TriBrush extends PshapeElement {
  
  TriBrush() {
    super();
  }

  PShape pscreateElement() {

    noStroke();
    PShape psDp = createShape(
                              TRIANGLE,
                              0, -6,
                              -4, 3,
                              4, 3
                              );
    return psDp;

  }

}
/* ---------------------------------------------------------------------- */
class ArcBrush extends PshapeElement {
  
  ArcBrush() {
    super();
  }

  PShape pscreateElement() {

    noStroke();
    PShape psDp = createShape(
                              ARC,
                              0, -2,
                              10, 10,
                              0, PI,
                              PIE
                              );
    return psDp;

  }

}

/* ---------------------------------------------------------------------- */
class Utils {

  Random obj_random;

  Utils() {
    obj_random = new Random();
  }
  
  float gaussdist(float pmean, float plimit, float pdevi) {
    /**
       Gaussian distribution
       1.parameters.
       pmean  : mean value
       plimit : max value of abs(deviation)
       ex. plimit >= 0
       pmean = 0.5, plimit = 0.5 -> return value = from 0.0 to 1.0
       pdevi  : standard deviation value
       ex. good value? -> pdevi = plimit / 2
       2.return.
       gaussian distribution
    **/

    if (plimit == 0) {
      return pmean;
    }

    float gauss = (float) obj_random.nextGaussian() * pdevi;
    // not good idea
    if (abs(gauss) > plimit) {
      gauss = pow(plimit, 2) / gauss;
    }

    return pmean + gauss;
    
  }
}

/* ---------------------------------------------------------------------- */

Utils ut;
PImage img;
PshapeElement brush;
RoundBrush rbr;
BoxBrush bbr;
TriBrush tbr;
ArcBrush abr;

int divX, divY;
float nsRX, nsRY;
float minBright, maxBright, meanBright;
float canvasW, canvasH;
float rateSize;

void setup() {
  size(1200, 1200);
  float baseWH = 1100;
  float numDiv = 500;
  
  colorMode(HSB, 360, 100, 100, 100);
  blendMode(SCREEN);
  smooth(4);
  noStroke();
  noLoop();

  ut = new Utils();  
  rbr = new RoundBrush();
  bbr = new BoxBrush();
  tbr = new TriBrush();
  abr = new ArcBrush();

  nsRX = random(50);
  nsRY = random(50);

  // get image via Google Custom Search
  // print them to standard output to use in shell script
  String[] imageUrl = getImageUrl();
  println(imageUrl[0]); // Title
  println(imageUrl[1]); // Page URL
  println(imageUrl[2]); // Image URL
  img = loadImage(imageUrl[2]);

  // ex. also you can use your photo in ./data/your_image.jpg
  //  img = loadImage("your_image.jpg");

  img.loadPixels();

  // fit to canvas size
  rateSize = baseWH / max(img.width, img.height);
  canvasW = img.width * rateSize;
  canvasH = img.height * rateSize;

  // divide same length
  float minSide = min(img.width, img.height);
  divX = round(minSide / numDiv);
  divY = round(minSide / numDiv);

  minBright = 100;
  maxBright = 0;
  meanBright = 0;
  int cntDivs = 0;
  for (int idxW = 0; idxW < img.width; idxW += divX) {  
    for (int idxH = 0; idxH < img.height; idxH += divY) {
      float valBright = brightness(img.pixels[idxH * img.width + idxW]);
      minBright = minBright > valBright ? valBright : minBright;
      maxBright = maxBright < valBright ? valBright : maxBright;

      meanBright += valBright;
      ++cntDivs;
    }
  }
  meanBright = meanBright / cntDivs;
  
}

void draw() {

  background(0, 0, 0);
  translate((width - canvasW) / 2, (height - canvasH) / 2);
  
  nsRX += 0.01;
  nsRY += 0.01;

  float fctSize = sqrt(pow(divX, 2) + pow(divY, 2));
  float nfRX = nsRX;
  for (int idxW = 0; idxW < img.width; idxW += divX) {  
    float nfRY = nsRY;
    for (int idxH = 0; idxH < img.height; idxH += divY) {
      color c = img.pixels[idxH * img.width + idxW];


      float valSize = ut.gaussdist(1.0, 0.9, 0.6) * fctSize * rateSize;
      float valColor = ut.gaussdist(hue(c), 100, 50) % 360;
      float valBright = map(brightness(c) + (50 - meanBright), 0, 100, 0.5, 1.2); // * map(rad, 1, 11, 1.2, 0.8);
      float valRotate = radians(180 * noise(nfRX, nfRY));
        
      pushMatrix();
      translate(idxW * rateSize, idxH * rateSize);

      // choose brush
      if (brightness(c) < minBright + (meanBright - minBright)) {
        if (saturation(c) < 50) {
          brush = bbr;
        } else {
          brush = tbr;
        }
      } else {
        if (saturation(c) < 50) {
          brush = abr;
        } else {
          brush = rbr;
        }
      }

      brush.setElementFill(valColor, 100, valBright, 100);
      brush.resetSize();
      brush.changeSize(valSize, valSize);
      brush.rotate(valRotate);
      brush.show();

      popMatrix();

      nfRY += 0.02;

    }

    nfRX += 0.02;
    
  }
  /*
  saveFrame("frames/####.png");
  exit();
  */
}


String[] getImageUrl() {
  /**
     Get Image Url via Google Custom Search
     1.parameters.
       nothing.
     2.return.
       in String array
          Title
          Page URL
          Image URL
     3.remark
       Google API key and Custom Search id are in ./data/google_api_keys.properties
          key = ***
          cxCat = ***
  **/

  // get Google API key & Custom Search id from file
  String qry = "Traveling++Cats++from";
  String fileType = "jpg";
  String searchType = "image";
  String startIndex = String.valueOf(floor(random(20)+1));
  String key = "";
  String cx = "";

  Properties prop = new Properties();
  String propFile = "./data/google_api_keys.properties";
  try {
    InputStream inputStream = new FileInputStream(propFile);
    prop.load(inputStream);
    inputStream.close();
    key = prop.getProperty("key");
    cx = prop.getProperty("cxCat");
  } catch (Exception e) {
    e.printStackTrace();
  }
  
  // search
  String[] matches;
  matches = new String[3];
  matches[0] = "";
  matches[1] = "";
  matches[2] = "cat10.jpg"; // fail safe

  try {

    URL url = new URL (
                       "https://www.googleapis.com/customsearch/v1?key=" + key
                       + "&cx=" + cx
                       + "&q=" + qry
                       + "&fileType=" + fileType
                       + "&searchType=" + searchType
                       + "&start=" + startIndex
                       + "&alt=json"
                       );

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Accept", "application/json");
    BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

    StringBuilder response = new StringBuilder();
    String line = "";
    String[] lines;
    while ((line = br.readLine()) != null) {
      response.append(line + "\n");
    }
    lines = response.toString().split("\n");
 
    br.close();
    conn.disconnect();

    // get first match title & jpg urls
    // precondition : must image link and page url after title
    Pattern ptnTitle = Pattern.compile("\"title\":.\"(Cat.+).-.Traveling.*$");
    Pattern ptnImage = Pattern.compile("\"link\":.\"(.+jpg).*$");
    Pattern ptnUrl = Pattern.compile("\"contextLink\":.\"(http.+)\".*$");
    boolean titleMatched = false;
    boolean imageMatched = false;
    boolean urlMatched = false;
    for (int i = 0; i < lines.length; ++i) {
      Matcher mchTitle = ptnTitle.matcher(lines[i]);
      if(mchTitle.find()) {
        titleMatched = true;
        matches[0] = mchTitle.group(1);
      }
      if (titleMatched) {
        Matcher mchImage = ptnImage.matcher(lines[i]);
        Matcher mchUrl = ptnUrl.matcher(lines[i]);
        if(mchImage.find()) {
          imageMatched = true;
          matches[2] = mchImage.group(1);
        }
        if(mchUrl.find()) {
          urlMatched = true;
          matches[1] = mchUrl.group(1);
        }
      }

      if (titleMatched && imageMatched && urlMatched) {
        break;
      }
      
    }

  } catch(MalformedURLException e){
    e.printStackTrace();
  } catch(IOException e){
    e.printStackTrace();
  }

  return matches;

}


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