Archive for the 'JavaScript' Category

09
Mar
10

Apply Core Image Kernel To Area Of Image

I always knew this was possible. Never got an answer from anyone ‘in the know’ on how to do it though, so eventually worked it out on my own.

/*
	Apply effect to area of image.
	
	toneburst 2010
*/

function __image main(__image image) {
	
	// Define rect (x-pos, y-pos, width, height)
	var rect = new Vec(100,100,100,200);
	
	// Apply effect to area of image defined by rect
	var inverted = fx.apply(rect, null, image);
	
	// Composite processed area on top of original image and return result
	return Filter.CISourceOverCompositing(inverted, image);
}

This snipped of JavaScript in a Core Image Filter (with ‘Edit filter function’ turned on) will apply the kernel function ‘fx’ in the top panel to the area of the image defined by the variable ‘rect’. Then I return the result of compositing the processed area on top of the original image.

I have a use for this, actually. Not sure anyone else out there will, mind you…

UPDATE:
Added demo QTZ to the Box.net widget
‘tb_CIFilter_wipe_demo.qtz’

02
Mar
10

3D Lissajous Curves

JavaScript Array > Kineme GL Line Structure.

17
Feb
10

Long-Time-No-Post

It’s been a long time since I posted here. Sadly, I’ve been caught up in other things lately- mainly PHP and web-tinkering (I hesitate to call it ‘development’, since what I’m mainly developing is a headache).

Soo.. until I get around to doing some more QC stuff (and believe me, I wish I had time for it), here’s some old stuff I found lying around on my computer:

17
Jun
09

Random Gradients Variation

///////////////////////
// CIFilter Kernel Code
///////////////////////

kernel vec4 combineChannels(sampler ImageR, sampler ImageG, sampler ImageB)  
{  
    float R = sample(ImageR, samplerCoord(ImageR)).r;  
    float G = sample(ImageG, samplerCoord(ImageG)).r;  
    float B = sample(ImageB, samplerCoord(ImageB)).r;  
  
    return vec4(R, G, B, 1.0);  
}

kernel vec4 multiplyChannels(sampler ImageR, sampler ImageG, sampler ImageB)  
{  
    float R = sample(ImageR, samplerCoord(ImageR)).r;  
    float G = sample(ImageG, samplerCoord(ImageG)).r;  
    float B = sample(ImageB, samplerCoord(ImageB)).r;
    float shade = R * G * B; 
  
    return vec4(vec3(shade), 1.0);  
}

///////////////////
// JavaScript
///////////////////

function __image main(__boolean Trigger, __index Type) {  
  
    var dims = new Vec(256,256);  
    var gradDims = new Vec(0,0,dims.x,dims.y);  
  
    var black = new Vec(0,0,0,1);  
    var white = new Vec(1,1,1,1);  
  
    var p0 = new Vec(Math.random() * dims.x, Math.random() * dims.y);  
    var p1 = new Vec(Math.random() * dims.x, Math.random() * dims.y);  
  
    var gradR = Filter.CILinearGradient(p0, p1, black, white);  
    gradR = Filter.CICrop(gradR, gradDims);  
  
    p0 = new Vec(Math.random() * dims.x, Math.random() * dims.y);  
    p1 = new Vec(Math.random() * dims.x, Math.random() * dims.y);  
  
    var gradG = Filter.CILinearGradient(p0, p1, black, white);  
    gradG = Filter.CICrop(gradG, gradDims);  
  
    p0 = new Vec(Math.random() * dims.x, Math.random() * dims.y);  
    p1 = new Vec(Math.random() * dims.x, Math.random() * dims.y);  
  
    var gradB = Filter.CILinearGradient(p0, p1, black, white);  
    gradB = Filter.CICrop(gradB, gradDims);  
  
    switch (Type) {
    case 0:
    		// Call kernel function and return result  
    		return combineChannels.apply(gradR.definition, null, gradR, gradG, gradB);
    		break;
    	case 1:
    		return multiplyChannels.apply(gradR.definition, null, gradR, gradG, gradB);
    		break;
	} 
}

Makes greyscale triangles and squares.

EDIT:
Just uploaded a QTZ with three variations on the basic random gradients theme, all in one CIFilter patch.
Download it if you think you’ll find it useful…
‘tb_randomGradients_1.0.qtz’ in the box.net widget on right.

And here’s a clip of it in action, courtesy of Lee Grosbauer:

Cheers, Lee!

05
Jun
09

Random-Walk Bezier JavaScript Code

This is my first proper attempt at using object methods in JS, so it might be a bit messy. Seems to work quite well though.
It’s the code (with additions) behind the clip in the previous post:

/*
	Generates points along a 3D bezier curve.
	
	Outputs should be connected to Queue patches to draw curve or points
	using Kineme GL Line Structure or GL Point Structure patches.
	
	//////////////
	// Controls //
	//////////////
	
	Draw:				Calculate point on curve
	CurveSteps:			Number of steps in curve segment
	CurveMaxLength:		Maximum XYZ distance between first and second anchor points
	CurveMaxTension:	Maximum XYZ distance between each anchor and its handle
	Scribbley:			Creates cursive looping scribbles
	ScribbleAmt:		Average size of scribble loops
	Jump:				Creates straight line segments by forcing recalculation
						of curve points
	dummy:				Connect Patch Time to force JS to run every frame
	
	///////////////
	// Copyright //
	///////////////
	
	Please credit if using.
	
	toneburst 2009
	https://machinesdontcare.wordpress.com
*/

////////////////////////////
// Point Object & Methods //
////////////////////////////

// Declare custom object to hold point data
function point() { this.X = 0.1; this.Y = 0; this.Z = 0; }

// Set point to values from another point
point.prototype.settopoint = function(p) { this.X = p.X; this.Y = p.Y; this.Z = p.Z; }

// Object method for point (creates new random Anchor point as offset from last point)
point.prototype.newpointA = function(lastpoint, maxdist) {
	this.X = lastpoint.X + (Math.random() * (2 * maxdist) - maxdist);
	this.Y = lastpoint.Y + (Math.random() * (2 * maxdist) - maxdist);
	this.Z = lastpoint.Z + (Math.random() * (2 * maxdist) - maxdist);
}

// New handle point for smoother 's-curves' (based on handle at end of previous curve)
point.prototype.newpointH = function(lastanchor, lasthandle, tightness) {
	this.X = lastanchor.X + -lasthandle.X * tightness;
	this.Y = lastanchor.Y + -lasthandle.Y * tightness;
	this.Z = lastanchor.Z + -lasthandle.Z * tightness;
}

// Calculates point on bezier-curve, taking 4 variables of type point
// and 1 value for time (in 0 > 1 range)
point.prototype.bezierpoint = function(A, B, D, C, t) {
	var a = t; var b = 1 - t;
	this.X = A.X * Math.pow(b, 3) + 3 * B.X * Math.pow(b, 2) * a + 3 * C.X * b * Math.pow(a, 2) + D.X * Math.pow(a, 3);
	this.Y = A.Y * Math.pow(b, 3) + 3 * B.Y * Math.pow(b, 2) * a + 3 * C.Y * b * Math.pow(a, 2) + D.Y * Math.pow(a, 3);
	this.Z = A.Z * Math.pow(b, 3) + 3 * B.Z * Math.pow(b, 2) * a + 3 * C.Z * b * Math.pow(a, 2) + D.Z * Math.pow(a, 3);
}

////////////////////
// Init Variables //
////////////////////

// Point instances
var p0 = new point(); var p1 = new point(); var p2 = new point(); var p3 = new point(); var pbezier = new point();
// Objects to hold final values
var pout = new Object(); var anchors = new Object(); var handles = new Object();
var count = 0;		// Counter
var curveIncrement;	// Variable to hold increment amount for each curve segment

///////////////////////
// Main Program Loop //
///////////////////////

function (__structure Point, __structure Anchors, __structure Handles)
			main
		(__boolean Draw, __index CurveSteps, __number CurveMaxLength, __number CurveMaxTension,
		 __boolean Scribbley, __number ScribbleAmt, __boolean Jump,
		 __number dummy)
{

	if(_testMode) {
	
	// Init points on first run
		p1.newpointA(p0, CurveMaxTension);
		p2.newpointA(p0, CurveMaxLength);
		p3.newpointA(p2, CurveMaxTension);	
	
	} else if(Draw) {
		
		////////////////////
		// Scale Controls //
		////////////////////
		
		CurveMaxLength = CurveMaxLength * 0.95 + 0.05;
		CurveMaxTension = CurveMaxLength * 0.95 + 0.05;
		
		////////////////////////
		// Init Output Object //
		////////////////////////
		
		var result = new Object();
		
		///////////////////////////////
		// Reset Points if Necessary //
		///////////////////////////////
		
		// IF count EQUALS CurveSteps OR Jump is TRUE, generate new points
		if(count == CurveSteps || Jump) {
		
		// Set curve points for next segment
			// Anchor 0 reset with position of p2 (Anchor 1)
			p0.settopoint(p2);
			// Handle 0: Discontinuous  or 'Loopy' curves
			if(!Scribbley) { p1.newpointA(p0, CurveMaxTension); } else { p1.newpointH(p2, p3, ScribbleAmt); }
			// Anchor 1
			p2.newpointA(p0, CurveMaxLength);
			// Handle 1
			p3.newpointA(p2, CurveMaxTension);
			
			// Curve step incremement
			curveIncrement = 1.0 / CurveSteps;
			
			// Set value for anchor and handle points
			anchors.X = p0.X; anchors.Y = p0.Y; anchors.Z = p0.Z;
			handles.X = p1.X; handles.Y = p1.Y; handles.Z = p1.Z;
			result.Anchors = anchors;	// Anchor-points for current segment
			result.Handles = handles;	// Handles for current segment
				
			// Reset counter
			count = 0;
		}

		/////////////////////	
		// Calculate Point //
		/////////////////////

		// Current time (position of point along curve)
		var time = curveIncrement * count;
		
		// Calculate point on Bezier
		pbezier.bezierpoint(p0, p1, p2, p3, time);
		
		// Set object for point
		// Prevents extra unwanted object properties being output
		// (JS bug? May be fixed in future WebKit version)
		pout.X = pbezier.X; pout.Y = pbezier.Y; pout.Z = pbezier.Z;
		
		if (count == Math.floor(0.5 * CurveSteps)) {
		// IF curve half-drawn, output second anchor and handle points
			anchors.X = p2.X; anchors.Y = p2.Y; anchors.Z = p2.Z;
			handles.X = p3.X; handles.Y = p3.Y; handles.Z = p3.Z;
			result.Anchors = anchors;	// Anchor-points for current segment
			result.Handles = handles;	// Handles for current segment
		}
				
		// Increment counter
		count++;
		
		/////////////////
		// Set Outputs //
		/////////////////
	
		// Set output point objects
		result.Point = pout;		// Bezier point along current segment
			
		// Output point
		return result;
	}
}
01
Jun
09

Object-Orientated Coding In JS

I’ve just (re)started leaning Objective-C, and thought I’d sabotage the learning-process (I always find a way to do this), by trying to do a bit of object-orientated coding in JavaScript, too.

Of course, I’ve used objects in JS/QC before, but I’ve never used proper OO concepts when writing JS before.

Here’s some example code:

// Declare custom object to hold point data
function point() {this.X = 0; this.Y = 0; this.Z = 0;}

// Re-initialise point
point.prototype.initpoint = function() {this.X = 0; this.Y = 0; this.Z = 0;}

// Object method for point (creates new random point)
point.prototype.newpoint = function(lastpoint, maxdist) {
	this.X = lastpoint.X + (Math.random() * (2 * maxdist) - maxdist);
	this.Y = lastpoint.Y + (Math.random() * (2 * maxdist) - maxdist);
	this.Z = lastpoint.Z + (Math.random() * (2 * maxdist) - maxdist);
}

// Calculates point on bezier-curve, taking 4 variables of type point and 1 value for time (in 0 > 1 range)
point.prototype.bezierpoint = function(A, B, C, D, t) {
	var a = t; var b = 1 - t;
	this.X = A.X * Math.pow(b, 3) + 3 * B.X * Math.pow(b, 2) * a + 3 * C.X * b * Math.pow(a, 2) + D.X * Math.pow(a, 3);
	this.Y = A.Y * Math.pow(b, 3) + 3 * B.Y * Math.pow(b, 2) * a + 3 * C.Y * b * Math.pow(a, 2) + D.Y * Math.pow(a, 3);
	this.Z = A.Z * Math.pow(b, 3) + 3 * B.Z * Math.pow(b, 2) * a + 3 * C.Z * b * Math.pow(a, 2) + D.Z * Math.pow(a, 3);
}

The idea of OO coding is that you define objects, with particular properties, and then you can define methods, that act on those properties in some way. Once you’ve defined an object, its properties and its methods, the object becomes a kind of prototype, and you can then create lots of independent instances of that object, each with their own, independent properties.

So, in the code above, I’m defining an object called ‘point’ to hold an X, Y and X position.

function point() {
	this.X = 0;
	this.Y = 0;
	this.Z = 0;
}

Once I’ve defined the properties that every instance of the point object will have, I can define methods to do things with those properties. Here’s the simplest one:

point.prototype.initpoint = function() {this.X = 0; this.Y = 0; this.Z = 0;}

To create a new object of type ‘point’, I’d do this:

var p0 = new point();

I can then apply the methods I defined above to the X Y and Z values for p0, using dot-syntax:

p0.initpoint();

for example, would initialise all values for p0 to 0.

The other methods I’ve defined are a bit more complicated, in that they require input variables to be passed to them when they are invoked, but the principle is the same.

Of course, this kind of thing will be second-nature to anyone who has done work in C++, Java, or any of the many other OO programming and scripting languages (though the syntax may vary), but it’s quite novel to me. I’ve been messing around with bits of code for years, now, but, apart from the odd dabbling with ActionScript, I’ve never really got beyond relatively simple procedural, C-style coding. I think I’ll be using OO techniques like this a lot more in the future, though. It’s definitely something I’ll need to get my head around conceptually, when I learn to write Objective-C, so it makes sense to apply the same principles in JavaScript, too.

01
Jun
09

Quartz Composer JavaScript Reference

A really useful resource for coding JavaScript in Quartz Composer.

Nice one cybero!




Twitter

May 2017
M T W T F S S
« Aug    
1234567
891011121314
15161718192021
22232425262728
293031  

Links

Blog Stats

  • 470,218 hits