tb MetaImage Update (CIFilter Code)

Updated version of the Meta-Image filter I did ages ago, originally based on one of Pete Warden’s original free FreeFrame effects. This one has a couple of nice new options and the whole thing has been implemented in a single CIFilter patch, this time.

CIFilter Kernel Code:

	'Meta-Image' effect.
	Original image is scaled and tiled, optionally recoloured
	by multiplication with colour of centre pixel of each tile.
	Based on original FreeFrame effect by Pete Warden.
	toneburst 2008

//   Pre-zoom    //

kernel vec4 vvZoom(sampler Image, vec2 Center, float Level) 
	// Based on VVZoom effect, from
	// http://www.vidvox.com/phpBB2/viewtopic.php?t=1785&highlight=vvzoom
	vec2 loc = destCoord();
	loc = samplerTransform(Image,loc);
	vec2 modifiedCenter = samplerTransform(Image, Center);
	loc = (loc - modifiedCenter)*(1.0/Level) + modifiedCenter;
	return sample(Image,loc); 

// Simple version, without recolouring //

kernel vec4 tbMetaImage(sampler Image, vec2 Divisor, float Mix)
	// Input image dimensions
	vec2 dims = samplerSize(Image);
	// Normalised coords of current pixel
	vec2 xyNorm = samplerCoord(Image) / dims;
	// Coords to sample tiled image
	vec2 miniImagePos = fract(xyNorm / Divisor);
	// Output tiled image
	return sample(Image, mix(xyNorm,miniImagePos,Mix) * dims);

// With recolouring //

kernel vec4 tbMetaImageClr(sampler Image, vec2 Divisor, float Mix)
	// Input image dimensions
	vec2 dims = samplerSize(Image);
	// Normalised coords of current pixel
	vec2 xyNorm = samplerCoord(Image) / dims;
	// Coords to sample tiled image
	vec2 miniImagePos = fract(xyNorm / Divisor);
	// Coords to sample centre pixel of each tile
	vec2 colorPos = (floor(xyNorm / Divisor) * Divisor) + 0.5 * Divisor;
	// Color at centre of current tile
	vec4 centreColor = sample(Image, colorPos * dims);
	// Sample scaled input image for current tile
	vec4 miniImage = sample(Image, mix(xyNorm,miniImagePos,Mix) * dims);
	// Output tiled image * centre color
	// mixed with original mini image color
	return mix(miniImage,miniImage * centreColor,Mix);

.. and the JavaScript from the bottom panel:

function __image main(__image Image, __vec2 Divisor, __number Type, __number PreZoom, __number Mix)
	// Scale and round control values
	Divisor.x = 1 / Math.round(Divisor.x); // Range 50 > 1, exponential-in
	Divisor.y = 1 / Math.round(Divisor.y); // Range 50 > 1, exponential-in
	// Pre-zoom
	center = new Vec(0.5 * Image.extent.width,0.5 * Image.extent.width);
	var zoomedImage = vvZoom.apply(Image.definition,null,Image,center,PreZoom);
	if(Type == 0.0) {
		return tbMetaImage.apply(zoomedImage.definition, null, zoomedImage, Divisor,Mix);
	} else if(Type == 1.0) {
		return tbMetaImageClr.apply(Image.definition, null, Image, Divisor,Mix);	}	

One nice new feature I’ve added is the ability to ‘mix’ between the effect and original image, but not as a simple crossfade- it’s actually mixing between the coordinates the image is sampled at, so you get this weird zooming effect.

I’ve realised I should be thinking more about making my effects start in an interesting way. Rather than just being on or off, I could have them transition in some interesting way from the original image to the effected version. Or maybe this wouldn’t be such a great idea, usability-wise. Anyone any thoughts on this?

2 Responses to “tb MetaImage Update (CIFilter Code)”

  1. October 28, 2008 at 5:52 pm

    These sorts of effects are a really good reason to stick to pure GLSL, as the lack matrix operations makes this code a looooooot longer. You could roll all of that into one matrix and apply the transform to the sampler. I really wish they would update Core Image in 10.6 to support this, it could make things a lot faster too!

    Nice work 🙂

  2. 2 toneburst
    October 28, 2008 at 6:07 pm

    If you take out all the comments, there’s really very little code actually there. The first kernel function, for example, only has 4 operational lines of code, and could be cut down even further by sacrificing some readability.

    For more complex effects, however, you’re probably right- you could write them much more simply using pure GLSL.

    I like the way you can use JavaScript to switch between the kernel functions in a CIFilter, though, it helps eliminate cable clutter outside the patch. It’s also useful not having to Render In Image to apply further fragment processing.

    You’re right about CIKernel slang being hobbled though. It’s about time it was updated to use more of the features that more recent GPUs support.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s


October 2008


Blog Stats

  • 493,214 hits

%d bloggers like this: