Archive for the 'CIFilter Code' Category


Adaptive Tiling Remake

Following a request for the Adaptive Tiling composition mentioned in a previous post from 2012, I spend a fruitless hour or so trying to track down the file. So I decided to try and recreate the setup, based on an iterative Core Image Filter.

It’s a long time since I did any Quartz Composer work, and I can’t remember exactly how I did it last time, so I don’t know if the remade version is as efficient as the original, but it does seem to work.

Here’s the Dropbox link to the file.

As usual, you’re welcome to do whatever you want with it, but some form of credit would be nice if you use it as part of your own work (especially if it’s used commercially). Drop me a message and let me know what you did with it, if you do find it useful.

This composition uses a builtin camera, but could easily to adapted into a plugin for VDMX or other realtime video applications.


Adaptive Tiling

It’s a lonnnnnnng time since I did anything in QC, so I thought I’d try and keep my hand in a bit, by doing something really simple.

As usual, it didn’t turn out to do quite as simple as I thought it would, in the end, but it looks very simple 😉

It’s basically just a 2D tiling effect, but works iteratively, so brighter areas of the image are subdivided into small tiles.

Uses a JavaScript loop inside a Core Image Kernel. I don’t know what the latest state-of-play is with JavaScript in CIFilter patches. There used to be memory leaks. Dunno if this is still the case.


The Beauty of Bilinear

I’ve recently got into making very low-res images. For various reasons, they’re quite useful for some purposes. Here are some nice examples of what happens when you blow up very small images (in this case from a simple RGB random pixel generator CIFilter), using QCs default bilinear filtering.

‘tb Bilinear 1.0.qtz’ in the widget.


Core Image Language Reference

Just (re)discovered this Core Image Language Reference doc on Apple’s Developer site.
Might prove useful to someone out there.

This entry on Core Image in WikiPedia might be of interest.


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…

Added demo QTZ to the widget



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:


The 27 Permutions Of The RGB Channels

Sometimes it’s nice to do something really simple.

Core Image Filter Kernels:

	The 27 permutations of the RGB channels.
	toneburst 2009

kernel vec4 RRR(sampler image) { return sample(image, samplerCoord(image)).rrra; }
kernel vec4 RRG(sampler image) { return sample(image, samplerCoord(image)).rrga; }
kernel vec4 RRB(sampler image) { return sample(image, samplerCoord(image)).rrba; }
kernel vec4 RGG(sampler image) { return sample(image, samplerCoord(image)).rgga; }
kernel vec4 RGB(sampler image) { return sample(image, samplerCoord(image)).rgba; }
kernel vec4 RGR(sampler image) { return sample(image, samplerCoord(image)).rgra; }
kernel vec4 RBR(sampler image) { return sample(image, samplerCoord(image)).rbra; }
kernel vec4 RBG(sampler image) { return sample(image, samplerCoord(image)).rbga; }
kernel vec4 RBB(sampler image) { return sample(image, samplerCoord(image)).rbba; }

kernel vec4 GRR(sampler image) { return sample(image, samplerCoord(image)).grra; }
kernel vec4 GRG(sampler image) { return sample(image, samplerCoord(image)).grga; }
kernel vec4 GRB(sampler image) { return sample(image, samplerCoord(image)).grba; }
kernel vec4 GGR(sampler image) { return sample(image, samplerCoord(image)).ggra; }
kernel vec4 GGG(sampler image) { return sample(image, samplerCoord(image)).ggga; }
kernel vec4 GGB(sampler image) { return sample(image, samplerCoord(image)).ggba; }
kernel vec4 GBR(sampler image) { return sample(image, samplerCoord(image)).gbra; }
kernel vec4 GBG(sampler image) { return sample(image, samplerCoord(image)).gbga; }
kernel vec4 GBB(sampler image) { return sample(image, samplerCoord(image)).gbba; }

kernel vec4 BRR(sampler image) { return sample(image, samplerCoord(image)).brra; }
kernel vec4 BRG(sampler image) { return sample(image, samplerCoord(image)).brga; }
kernel vec4 BRB(sampler image) { return sample(image, samplerCoord(image)).brba; }
kernel vec4 BGR(sampler image) { return sample(image, samplerCoord(image)).bgra; }
kernel vec4 BGG(sampler image) { return sample(image, samplerCoord(image)).bgga; }
kernel vec4 BGB(sampler image) { return sample(image, samplerCoord(image)).bgba; }
kernel vec4 BBR(sampler image) { return sample(image, samplerCoord(image)).bbra; }
kernel vec4 BBG(sampler image) { return sample(image, samplerCoord(image)).bbga; }
kernel vec4 BBB(sampler image) { return sample(image, samplerCoord(image)).bbba; }

Filter Function javascript:

	The 27 permutations of the RGB channels.
	toneburst 2009

function __image main(__image Image, __index Permutation) {
	switch(Permutation) {
		case  0: return RRR.apply(Image.definition, null, Image); break;
		case  1: return RRG.apply(Image.definition, null, Image); break;
		case  2: return RRB.apply(Image.definition, null, Image); break;
		case  3: return RGG.apply(Image.definition, null, Image); break;
		case  4: return RGB.apply(Image.definition, null, Image); break;
		case  5: return RGR.apply(Image.definition, null, Image); break;
		case  6: return RBR.apply(Image.definition, null, Image); break;
		case  7: return RBG.apply(Image.definition, null, Image); break;
		case  8: return RBB.apply(Image.definition, null, Image); break;
		case  9: return GRR.apply(Image.definition, null, Image); break;
		case 10: return GRG.apply(Image.definition, null, Image); break;
		case 11: return GRB.apply(Image.definition, null, Image); break;
		case 12: return GGR.apply(Image.definition, null, Image); break;
		case 13: return GGG.apply(Image.definition, null, Image); break;
		case 14: return GGB.apply(Image.definition, null, Image); break;
		case 15: return GBR.apply(Image.definition, null, Image); break;
		case 16: return GBG.apply(Image.definition, null, Image); break;
		case 17: return GBB.apply(Image.definition, null, Image); break;
		case 18: return BRR.apply(Image.definition, null, Image); break;
		case 19: return BRG.apply(Image.definition, null, Image); break;
		case 20: return BRB.apply(Image.definition, null, Image); break;
		case 21: return BGR.apply(Image.definition, null, Image); break;
		case 22: return BGG.apply(Image.definition, null, Image); break;
		case 23: return BGB.apply(Image.definition, null, Image); break;
		case 24: return BBR.apply(Image.definition, null, Image); break;
		case 25: return BBG.apply(Image.definition, null, Image); break;
		case 26: return BBB.apply(Image.definition, null, Image); break;

Volumetric Light Scattering Attempt 2

This attempt is slightly better.
I’ve implemented the shader as a Core Image Filter this time, mainly to make it easier to do the various compositing operations necessary.

I’m still not particularly pleased with it, to be honest. Maybe it just needs something more interesting than 3 cubes…


Borg 2D Polar Mapping

This is the Borg equation with polar coordinates.

Here’s the CIFilter Kernel code for cartesian and polar versions (I’ll let you work out sensible ranges for the various controls):

	Borg equation in cartesian and polar varieties.
	From 3D surface equation found here:
	Quartz Composer setup
	toneburst 2009

kernel vec4 tb_borg_cartesian(sampler Image, vec2 NormFactor, float Z, vec2 Scale, vec2 Offset)
	// Normalised coords of current pixel
	vec2 xyNorm = samplerCoord(Image) * NormFactor;
	xyNorm -= 0.5;
	xyNorm *= Scale;
	xyNorm += Offset;
	float borg = sin(xyNorm.x * xyNorm.y) + sin(xyNorm.y * Z) + sin(Z * xyNorm.x);
	// Sample image and return pixel
	return vec4(vec3(1.0), borg);

kernel vec4 tb_borg_polar(sampler Image, vec2 NormFactor, float Phi, vec2 Scale, vec2 Offset)
	// Normalised coords of current pixel
	vec2 xyNorm = samplerCoord(Image) * NormFactor;
	xyNorm -= 0.5;
	xyNorm = abs(xyNorm);
	// Cartesian to polar
	vec2 polar;
	polar[0] = length(xyNorm);				// R
	polar[1] = atan(xyNorm.x/xyNorm.y);		// Theta
	polar *= Scale;
	polar += Offset;
	float borg = sin(polar[0] * polar[1]) + sin(polar[1] * Phi) + sin(Phi * polar[0]);
	// Sample image and return pixel
	return vec4(vec3(1.0), borg);

Added ‘tb_borg2D_1.0.qtz’ to download widget.


More Moiré Screenshots

Moiré variations.


July 2020


Blog Stats

  • 493,214 hits