Permalink
Browse files

Initial, fragile support for Convolution Matrices (in /demo/ only for…

… now)
  • Loading branch information...
1 parent 948eac4 commit 0043591c6cfe2582169be11bda11eed876a532a6 Dave Shea committed Aug 30, 2010
Showing with 155 additions and 12 deletions.
  1. +23 −0 demo/index.html
  2. +132 −12 demo/script/paintbrush-0.2.js
View
23 demo/index.html
@@ -66,6 +66,12 @@
<figcaption>Mosaic, default (img)</figcaption>
</figure>
</li>
+ <li>
+ <figure>
+ <img src="images/240-lighthouse.jpg" class="filter-matrix" width="240" height="160" alt="Point Atkinson Lighthouse">
+ <figcaption>Matrix, default (img)</figcaption>
+ </figure>
+ </li>
</ul>
@@ -124,6 +130,11 @@
<p>Mosaic: Amount 0.5, Size 10 (CSS Background)</p>
</div>
</li>
+ <li>
+ <div class="bee filter-matrix">
+ <p>Matrix: default (CSS Background)</p>
+ </div>
+ </li>
</ul>
@@ -196,6 +207,13 @@
<figcaption>Mosaic: Size 3 (img)</figcaption>
</figure>
</li>
+ <li>
+ <figure>
+ <img src="images/240-road.jpg" class="filter-matrix"
+ width="240" height="160" alt="West Coast roads, New Zealand">
+ <figcaption>Matrix: default (img)</figcaption>
+ </figure>
+ </li>
</ul>
@@ -253,6 +271,11 @@
<p>Mosaic: Size 15 (CSS Background)</p>
</div>
</li>
+ <li>
+ <div class="stones filter-matrix">
+ <p>Matrix: default (CSS Background)</p>
+ </div>
+ </li>
</ul>
View
144 demo/script/paintbrush-0.2.js
@@ -33,6 +33,9 @@ addLoadEvent(function() {
addFilter("filter-posterize");
addFilter("filter-sepia");
addFilter("filter-tint");
+
+ // early experimental phase
+ addFilter("filter-matrix");
}
// only use this if you're going to time the script, otherwise you can safely delete the next three lines
@@ -87,27 +90,35 @@ function addFilter(filterType) {
//
// pre-processing for various filters
//
- // blur has to exist outside the main loop
+ // blur and matrix filters have to exist outside the main loop
if (filterType == "filter-blur") {
pixels = gaussianBlur(img, pixels, params.blurAmount);
}
+ if (filterType == "filter-matrix") {
+ pixels = applyMatrix(img, pixels, params);
+ }
+
+
// we need to figure out RGB values for tint, let's do that ahead and not waste time in the loop
if (filterType == "filter-tint") {
var src = parseInt(createColor(params.tintColor), 16),
dest = {r: ((src & 0xFF0000) >> 16), g: ((src & 0x00FF00) >> 8), b: (src & 0x0000FF)};
}
- // the main loop through every pixel to apply effects
- // (data is per-byte, and there are 4 bytes per pixel, so lets only loop through each pixel and save a few cycles)
- for (var i = 0, data = pixels.data, length = data.length; i < length >> 2; i++) {
- var index = i << 2;
-
- // get each colour value of current pixel
- var thisPixel = {r: data[index], g: data[index + 1], b: data[index + 2]};
-
- // the biggie: if we're here, let's get some filter action happening
- pixels = applyFilters(filterType, params, img, pixels, index, thisPixel, dest);
+
+ if (filterType != "filter-blur") {
+ // the main loop through every pixel to apply effects
+ // (data is per-byte, and there are 4 bytes per pixel, so lets only loop through each pixel and save a few cycles)
+ for (var i = 0, data = pixels.data, length = data.length; i < length >> 2; i++) {
+ var index = i << 2;
+
+ // get each colour value of current pixel
+ var thisPixel = {r: data[index], g: data[index + 1], b: data[index + 2]};
+
+ // the biggie: if we're here, let's get some filter action happening
+ pixels = applyFilters(filterType, params, img, pixels, index, thisPixel, dest);
+ }
}
// redraw the pixel data back to the working buffer
@@ -170,7 +181,9 @@ function addFilter(filterType) {
"posterizeAmount" : 5, // 0 - 255, though 0 and 1 are relatively useless
"sepiaAmount" : 1, // between 0 and 1
"tintAmount" : 0.3, // between 0 and 1
- "tintColor" : "#FFF" // any hex color
+ "tintColor" : "#FFF", // any hex color
+
+ "matrixAmount" : 0.2 // between 0 and 1
};
// check for every attribute, throw it into the params object if it exists.
@@ -318,11 +331,118 @@ function addFilter(filterType) {
findColorDifference(params.tintAmount, dest.b, thisPixel.b));
break;
+
+ }
+ return(pixels);
+ }
+
+
+
+ function applyMatrix(img, pixels, params) {
+
+ // -------------
+ // been leaning on this a lot:
+ // http://forum.processing.org/topic/controlled-blur-or-edge-detect-effect-using-convolution-kernel
+ // -------------
+
+ // speed up access
+ var data = pixels.data, imgWidth = img.width;
+
+ // 3x3 matrix can be any combination of digits, though to maintain brightness they should add up to 1
+ // (-1 x 8 + 9 = 1)
+ var matrix = [
+ -1, -1, -1,
+ -1, 9, -1,
+ -1, -1, -1
+
+/*
+ 0, -1, 0,
+ -1, 5, -1,
+ 0, -1, 0
+*/
+
+/*
+ 0.111, 0.111, 0.111,
+ 0.111, 0.111, 0.111,
+ 0.111, 0.111, 0.111
+*/
+
+ ];
+
+ // though theoretically we're also going to account for non-1 arrays
+ matrix = normalizeMatrix(matrix);
+
+ // calculate the dimensions, just in case this ever expands to 5 and beyond
+ var matrixSize = Math.sqrt(matrix.length);
+
+ // loop through every pixel
+ for (var i = 1; i < imgWidth - 1; i++) {
+ for (var j = 1; j < img.height - 1; j++) {
+
+ // temporary holders for matrix results
+ var sumR = sumG = sumB = 0;
+
+ // loop through the matrix itself
+ for (var h = 0; h < matrixSize; h++) {
+ for (var w = 0; w < matrixSize; w++) {
+
+ // get a refence to a pixel position in the matrix
+ var r = convertCoordinates(i + h - 1, j + w - 1, imgWidth) << 2;
+
+ // find RGB values for that pixel
+ var currentPixel = {
+ r: data[r],
+ g: data[r + 1],
+ b: data[r + 2]
+ };
+
+ // apply the value from the current matrix position
+ sumR += currentPixel.r * matrix[w + h];
+ sumG += currentPixel.g * matrix[w + h];
+ sumB += currentPixel.b * matrix[w + h];
@wdacgrs
wdacgrs Aug 30, 2010

Should be matrix[w + h * matrixSize]

@mezzoblue
mezzoblue Aug 30, 2010

Yep, you're right. Late night commits are fun like that.

+ }
+ }
+
+ // get a reference for the final pixel
+ var ref = convertCoordinates(i, j, imgWidth) << 2;
+ var thisPixel = {
+ r: data[ref],
+ g: data[ref + 1],
+ b: data[ref + 2]
+ };
+
+ // finally, apply the adjusted values
+ data = setRGB(data, ref,
+ findColorDifference(params.matrixAmount, sumR, thisPixel.r),
+ findColorDifference(params.matrixAmount, sumG, thisPixel.g),
+ findColorDifference(params.matrixAmount, sumB, thisPixel.b));
+ }
}
+
return(pixels);
}
+ // convert x/y coordinates to pixel index reference
+ function convertCoordinates(x, y, w) {
+ return x + (y * w);
+ }
+
+ // ensure that values in the matrix add up to 1
+ function normalizeMatrix(matrix) {
+ var j = 0;
+ for (var i = 0; i < matrix.length; i++) {
+ j += matrix[i];
+ }
+ for (var i = 0; i < matrix.length; i++) {
+ matrix[i] /= j;
+ }
+ return matrix;
+ }
+
+
+
+
// calculate random noise. different every time!
function noise(noiseValue) {
return Math.floor(noiseValue / 2 - (Math.random() * noiseValue));

0 comments on commit 0043591

Please sign in to comment.