Skip to content

Instantly share code, notes, and snippets.

@Coridyn
Created September 9, 2014 02:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Coridyn/67a0ff75afaa0163f673 to your computer and use it in GitHub Desktop.
Save Coridyn/67a0ff75afaa0163f673 to your computer and use it in GitHub Desktop.
Bitwise XOR two images in PixelBender
<languageVersion : 1.0;>
kernel Crossfade
< namespace : "AIF";
vendor : "Coridyn - https://github.com/Coridyn";
version : 2;
description : "Perform a bitwise XOR of two images"; >
{
input image4 inputImage;
input image4 diffImage;
output pixel4 dst;
// Getting an error in Pixel Bender Toolkit when this
// is a bool parameter so changing to int instead.
parameter int ignoreAlpha
<
defaultValue: 1;
minValue: 0;
maxValue: 1;
description: "If 1 then ignore the alpha channel when diffing.";
>;
// Bitwise algorithm was adapted from the "mathematical equivalents" formula on Wikipedia:
// http://en.wikipedia.org/wiki/Bitwise_operation#Mathematical_equivalents
// Macro for 2^n (it needs to be done a lot).
#define POW2(n) pow(2.0, n)
// Slight optimisation for the zeroth case - 2^0 = 1 is redundant so remove it.
#define XOR_i_0(x, y) ( mod( mod(floor(x), 2.0) + mod(floor(y), 2.0), 2.0 ) )
// Calculations for a given "iteration".
#define XOR_i(x, y, i) ( POW2(i) * ( mod( mod(floor(x / POW2(i)), 2.0) + mod(floor(y / POW2(i)), 2.0), 2.0 ) ) )
// Flash doesn't support loops.
// Unroll the loop by defining macros that call the next macro in the sequence.
// Adapted from: http://www.simppa.fi/blog/category/pixelbender/
// http://www.simppa.fi/source/LoopMacros2.pbk
#define XOR_0(x, y) XOR_i_0(x, y)
#define XOR_1(x, y) XOR_i(x, y, 1.0) + XOR_0(x, y)
#define XOR_2(x, y) XOR_i(x, y, 2.0) + XOR_1(x, y)
#define XOR_3(x, y) XOR_i(x, y, 3.0) + XOR_2(x, y)
#define XOR_4(x, y) XOR_i(x, y, 4.0) + XOR_3(x, y)
#define XOR_5(x, y) XOR_i(x, y, 5.0) + XOR_4(x, y)
#define XOR_6(x, y) XOR_i(x, y, 6.0) + XOR_5(x, y)
#define XOR_7(x, y) XOR_i(x, y, 7.0) + XOR_6(x, y)
// Entry point for XOR function.
// This will calculate the XOR the current pixels.
#define XOR(x, y) XOR_7(x, y)
// PixelBender uses floats from 0.0 to 1.0 to represent 0 to 255
// but the bitwise operations above work on ints.
// These macros convert between float and int values.
#define FLOAT_TO_INT(x) float(x) * 255.0
#define INT_TO_FLOAT(x) float(x) / 255.0
#define FLOAT_TO_INT_3(x) float3(x) * 255.0
#define INT_TO_FLOAT_3(x) float3(x) / 255.0
void evaluatePixel()
{
// Acquire the pixel values from both images at the current location.
float4 frontPixel = sampleNearest(inputImage, outCoord());
float4 backPixel = sampleNearest(diffImage, outCoord());
// Set up the output variable - RGBA.
pixel4 result = pixel4(0.0, 0.0, 0.0, 1.0);
// In CPU mode we can "swizzle" the values to pass all three channels at once - cool!
// result.rgb = INT_TO_FLOAT_3 ( XOR(FLOAT_TO_INT_3(frontPixel.rgb), FLOAT_TO_INT_3(backPixel.rgb)) );
// In Flash we need to calculate each channel separately.
result.r = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.r), FLOAT_TO_INT(backPixel.r)) );
result.g = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.g), FLOAT_TO_INT(backPixel.g)) );
result.b = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.b), FLOAT_TO_INT(backPixel.b)) );
if (ignoreAlpha == 0){
// Don't diff alpha channel so we can actually see the result on screen! (because FF ^ FF = 0)
result.a = INT_TO_FLOAT ( XOR(FLOAT_TO_INT(frontPixel.a), FLOAT_TO_INT(backPixel.a)) );
}
dst = result;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment