Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0

Monday, 26 August 2013

Simple pixellator using a cfdg end point

In hommage to guigui's original, the output cfdg file is called haddock.cfdg (after capt haddock "tintin"), the sketch data gets shoved into data.cfdg, that is called from haddock.cfdg by the cfdg program (requires version 3.0+). To adjust to different axis conventions I could just have made y negative. But because evolution of an non deterministic design (this isn't one) is from centre out, I adjusted x and y accordingly. Tune-able value is skip 3..10 is sensible choice, you could also add a posterize filter if needed. Nice to have would be a rectangle mask to define area to pixel-ate. Where an actual image is uses as basis you might be better doing img.load_pixels and accessing the pixel array thus img.pixels[x +y * width]. However the following sketch could be readily adapted to use processing generated images.
load_library :file_chooser
attr_reader :img, :data, :skip

# Example file chooser (in this case as an image file chooser).
# We delay setting size of sketch until we know image size, probably
# would not work vanilla processing. Note we can wrap much code in the
# file_chooser block, no need for reflection. As with selectInput vanilla
# processing.

def setup
  color_mode(HSB, 1.0);
  file_chooser do |fc|
    fc.look_feel "Gtk+"                            # optional, default is "Metal"
    fc.set_filter "Image Files",  [".png", ".jpg"] # easily customizable chooser
    @img = load_image(fc.display)                  # fc.display returns a path String
    size(img.width, img.height)
  @skip = 5
  @data = []

def draw
  background img                                  # img must be same size as sketch

def write_data name, data
  open("data.cfdg", "w") do |pw|
    pw.puts "shape #{name}{\n"
    data.each do |row|
      pw.puts "  #{row[0]}[x #{row[1]} y #{row[2]} s #{row[3]} hue #{row[4]} sat #{row[5]} brightness #{row[6]}]\n"
    pw.puts "}\n"

def write_start start, data
  open("#{start}.cfdg", "w") do |pw|
  pw.puts "CF::Background = [b -1]"
  pw.puts "startshape #{start}\n"
  pw.puts "shape dot{CIRCLE[]}\n"
  pw.puts "import data.cfdg\n"
write_data start, data

def mouse_clicked
  export = Thread.new do
    shp = "dot"
    (skip ... img.width).step(skip) do |x|
      (skip ... img.height).step(skip) do |y|
        pix = pixels[x +y * width]
        sat = saturation(pix)
        hue = hue(pix)
        sz = brightness(pix) * skip
        data << [shp, -width/2 + x, height/2 - y, sz.round(2), (hue * 360).round, sat.round(4), 1] if sz > 0.03
    write_start "haddock", data
  puts "done"

Sunday, 25 August 2013

The Gtk+ look and feel using openjdk

I just did some further experiments with my ruby-processing file chooser, and now I think the "Gtk+" look and feel might be the way to go on linux:-
However it is not that you should call the "Gtk+" look and feel, you should probably call "Metal", but specify system wide that the system and default look and feel is GTK (on archlinux you can do this in /etc/jre.sh in others you might use a flag or otherwise specify an environmental variable, be sure to set GTK fonts too).

Friday, 23 August 2013

Image Viewer Ruby Processing

Here is a little sketch, exploring the possibility of using my file_chooser to create a neat little image viewer. I does not make too much sense on its own, but we can take a look at images in ruby-processing, and then possibly do something with them along the lines of exporting to a "pixelated" sketch to cfdg for example.
load_library :file_chooser
attr_reader :img

# Example usage of file_chooser (in this case image file chooser) 
# not sure this is exactly possible with vanilla processing. Here we
# defer setting the size of the sketch, until we know the size of image.

def setup
  file_chooser do |fc|
    fc.look_feel "Nimbus"
    fc.set_filter "Image Files",  [".png", ".jpg"]
    my_file = fc.display
    @img = load_image(my_file)
    size img.width, img.height

def draw
  background img

File Chooser Library For ruby-processing

Well here it is in action my ruby-processing file_chooser library, that like control panel takes a block the fc.display returns a a string that you can use in load_image etc to load a file, you can do all this in a block if you like (see below). Is a replacement for vanilla processing selectInput function that relies on reflection (and the chooser cannot be so easily customised). PS the my_file temporary variable is not required. The chooser starts in the users home folder on unix (mac/linux) or the working directory on windoes.
load_library :file_chooser
attr_reader :img

# Example file chooser (in this case image file chooser)
# the image loading and resizing is encapsulated in the block,
# borrows heavily off control_panel. 

def setup
  size 600, 600
  file_chooser do |fc|
    fc.look_feel "Nimbus"
    fc.set_filter "Image Files",  [".png", ".jpg"]
    my_file = fc.display
    @img = load_image(my_file)
    img.resize(width, height)

def draw
  image img, 0, 0

The Chooser (a customised JFileChooser)
The Sketch

Saturday, 17 August 2013

File Chooser in JRuby

Having convinced myself that the vanilla processing selectInput is a piece of crap (yet more reflection nonsense) I though I had better come up with an alternative for ruby processing, here is such an example (yielded by my good friend google and a bit of imagination, works for me):-
require 'rbconfig'
require 'pathname'

System = Java::JavaLang::System
JFile = Java::JavaIo::File
JXChooser = Java::javax::swing::JFileChooser

class ImageFilter < Java::javax::swing::filechooser::FileFilter
  def accept fobj
    return [".png",".jpg"].include? File.extname(fobj.to_s).downcase
    return fobj.isDirectory

  def getDescription
    "Image Files"

# Detect OS
OS = case RbConfig::CONFIG['host_os']
  when /darwin/      then :mac
  when /mswin|mingw/ then :windows

# Asks the user to choose an editor.
# Returns either a Pathname object or nil (if canceled)
def pickImage
  # Create a FileChooser
  fc = JXChooser.new("Image Chooser")
  fc.set_dialog_title("Please select an image")
  fc.setFileFilter ImageFilter.new

  if :mac == OS
    fc.setCurrentDirectory(JFile.new(System.getProperty("user.home") << "/Pictures"))
  elsif :windows == OS

  success = fc.show_open_dialog(nil)
  if success == JXChooser::APPROVE_OPTION
    return Pathname.new(fc.get_selected_file.get_absolute_path)

puts "The user picked: #{pickImage}"

This would be the wrapper for ruby-processing?
def select_input(*args, &block)
  if block_given?
    # code using FileChooser output?
    raise ArgumentError, "select_input must be called with a block" , caller

Thursday, 15 August 2013

Ruby-processing-2.1.3 is released (features processing-2.0.2)

In recent weeks I've changed the default mode of ruby-processing from using the included jruby-complete by default to using an external (system installed) jruby. So the --jruby flag is now deprecated (it doesn't do anything) and is replaced by the --nojruby flag which causes the installed jruby-complete to be used instead of the system version. The jruby-complete is retained for the following uses:-

  1. To support application export
  2. To run certain sketches (mainly GLSL shader sketches) that wont run with installed jruby
  3. For people without an installed jruby (for whatever reason), make sure and use --nojruby flag.
Anyway I've also revisited, some of the samples with a view to introducing some more idiomatic ruby, and one thing I came up with was the idea to replace the heavyweight PVector class with a lightweight Struct alternative when the PVector class was being used as a repository for x, y, z values.
Vect = Struct.new(:x, :y, :z) do
  def add v
    self.x += v.x
    self.y += v.y
    self.z += v.z

Monday, 12 August 2013

Netbeans for ruby-processing

Hey this looks pretty promising, you can now install a plugin for netbeans-7.3 (for ruby and ruby-on-rails development). I will report how I get on install seemed to go ok, Once I figured out I needed to add *.jar as well as *.nbm sub-modules.

Wednesday, 7 August 2013

Avoiding classpath conflict with jruby-complete

Well the simplest thing to do, would be ditch to jruby-complete, except:-
  1. Shader sketches still refuse to run. 
  2. We would lose export. 
  3. We would lose ability to install to system without requiring an installed jruby.
For me 1. is the biggest problem, any exported sketches will probably still be unable to use gems, also installing without jruby also means no access to gems.

See this gist for work in progress https://gist.github.com/monkstone/6172815. I propose to work on this independently on my monkstone branch will need updating from master. 

Motivation we could potentially use rubygems with P2D and P3D modes (even PImage sketches could not be run with rubygems). If we radically exclude jruby-complete until export gem would be much smaller.

Well it seem possible solution is to put jruby-complete.jar in its own directory, and possibly use:-


So the solution is:-

Move ruby-complete.jar to its own folder (so we no-longer 'require jruby-complete.jar' in app.rb)

Dir["#{RP5_ROOT}/lib/core/\*.jar"].each { |jar| require jar }

Consequently we need to adjust the path jruby-complete.jar. And in the first place make sure we extract it to its new location easy. Seems to work, we retain the --jruby flag, which should be default unless we haven't installed jruby or we want to run shader sketches.

However it occurs to me this is the ideal opportunity to set using an external jruby as the default. Now all we need is a flag "--nojruby"  for when we need/prefer to use the included jruby-complete (which will remain handy to support export of applications). The shader sketches are the only ones now requiring such a flag. However it will also be required if ruby-processing gets installed without using system jruby (in this case you won't be able to use gems with ruby-processing). 

Well I've done it now since version 2.1.2 the default is to run ruby-processing from an external jruby, to revert to using installed jruby-complete now use the --nojruby flag (replaces the --jruby flag which had the opposite effect).

Tuesday, 6 August 2013

Conways Game of Life in ruby-processing (featuring MDArray)

# game_of_life.rb featuring MDArray in ruby-processing
# A Processing implementation of Game of Life
# By Joan Soler-Adillon
# Press SPACE BAR to pause and change the cell's values with the mouse
# On pause, click to activate/deactivate cells
# Press R to randomly reset the cells' grid
# Press C to clear the cells' grid
# The original Game of Life was created by John Conway in 1970.

require 'mdarray'

ALIVE = true
DEAD = false
WIDTH = 960
HEIGHT = 640
SKIP = 10

attr_reader :pause, :cells, :row, :column, :last_time, :alive, :cells_buffer

# signature-specific aliases for overloaded methods
java_alias :my_color, :color, [Java::float, Java::float, Java::float]
java_alias :my_fill, :fill, [Java::int]
java_alias :my_stroke, :stroke, [Java::float, Java::float]
java_alias :my_background, :background, [Java::int]

def setup
  @row = WIDTH / CELL_SIZE
  @column = HEIGHT / CELL_SIZE
  stroke_weight 2
  @last_time = 0
  @pause = false
  @cells = MDArray.boolean([row, column], random_data)
  @alive = my_color(100, 255, 100)
  my_stroke(48, 100)

def draw
  #Draw live cells
  (0 ... row).each do |x|
    (0 ... column).each do |y|
      if (cells.get([x, y]))
        rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
  # Iterate if timer ticks
  if (millis - last_time > INTERVAL)
    if (!pause)
      @last_time = millis

  # Create  new cells manually on pause
  if (pause && mouse_pressed?)
    # # Map and avoid out of bound errors
    x_cell_over = (map(mouse_x, 0, width, 0, row)).to_i
    x_cell_over = constrain(x_cell_over, 0, row - 1)
    y_cell_over = (map(mouse_y, 0, height, 0, column)).to_i
    y_cell_over = constrain(y_cell_over, 0, column - 1)

    # Check against cells in buffer
    if (cells_buffer.get([x_cell_over, y_cell_over]))  # Cell is alive
      cells.set([x_cell_over, y_cell_over], DEAD) # Kill
      my_fill(0) #reflect changed status
    else  # Cell is dead
      cells.set([x_cell_over, y_cell_over], ALIVE) # Make alive
      my_fill(alive) # Fill alive color

  elsif (pause && !mouse_pressed?)  # And then save to buffer once mouse goes up
    # Save cells to buffer (so we operate with one array keeping the other intact)
    @cells_buffer = cells.copy

def tick!  # When the clock ticks
  # Save cells to buffer (so we operate with one array keeping the other intact)
  @cells_buffer = cells.copy
  # Visit each cell:
  (0 ... row).each do |x|
    (0 ... column).each do |y|
      # And visit all the neighbours of each cell
      neighbours = 0 # We'll count the neighbours
      (x - 1 .. x + 1).each do |xx|
        (y - 1 .. y + 1).each do |yy|
          # Make sure you are not out of bounds
          if [(xx>=0), (xx<row), (yy>=0), (yy<column)].all? {|in_bounds| in_bounds == true}
            # Make sure to check against self
            if ![(xx == x), (yy == y)].all? {|is_self| is_self == true}
              if (cells_buffer.get([xx, yy])) # true == ALIVE
                neighbours += 1 # Check alive neighbours and count them
              end # alive
            end # End of if self
          end # End of if grid bounds
        end # End of yy loop
      end #End of xx loop
      # We've checked the neighbours: apply rules in one line (only in ruby)!
      cells.set([x, y], (cells_buffer.get([x, y]))?  ((2 .. 3) === neighbours) : (neighbours == 3))
    end # End of y loop
  end # End of x loop
end # End of function

def key_pressed
  case key
  when 'r', 'R'
    # Restart: reinitialization of cells 
    @cells = MDArray.boolean([row, column], random_data)
  when ' ' # On/off of pause
    @pause = !pause
  when 'c', 'C' # Clear all
    @cells = MDArray.boolean([row, column], DEAD)

def random_data
  data = []
  (0 ... row * column).each do
    data << (rand(1000) < ALIVE_START)
  return data

Saturday, 3 August 2013

Using MDArray in ruby-processing

Well quite excited with this jruby gets its own flavour of numpy, namely MDArray. I had to give it a go here is a simple example:-
#  Demonstrates the syntax for creating a two-dimensional (2D) array,
#  fromfunction (actually a block) using MDArray (for jruby).
#  Values in a 2D array are accessed through two index values.  
#  2D arrays are useful for storing images. In this example, each dot 
#  is colored in relation to its distance from the center of the image.

require 'mdarray'


def setup
  background 0
  stroke_weight 2
  max_distance = ( (WIDTH / 2 - WIDTH)**2  + (HEIGHT / 2 - HEIGHT)**2 )**0.5
  distances = MDArray.fromfunction("float", [WIDTH, HEIGHT]) do |x, y|
    255 * ( (WIDTH / 2 - x)**2  + (HEIGHT / 2 - y)**2 )**0.5 / max_distance
  (SKIP ... WIDTH).step(SKIP) do |x|
      (SKIP ... HEIGHT).step(SKIP) do |y|
        stroke distances[x, y]
        point x, y

According to the limited documentation it might be more efficient to use the accessor to "get" data rather than using bare array access see below. For actual image manipulation in ruby-processing we might be in a bind, we require external jruby to access the gem, but that appears not to work with PImage sketches?
distances.get([x, y])


Blog Archive

About Me

My photo
I have developed JRubyArt and propane new versions of ruby-processing for JRuby- and processing-3.2.2