forked from: Bitmap Edge and Orientation Transform Best
forked from Bitmap Edge and Orientation Transform Best (diff: 50)
written by j2e japanese2english@gmail.com The function itself takes bitmapData and overwrites it with edge data. The edge data is color-coded and can be used to determine the orientation of the edge at any point when read or further manipulated. Vertical edges are more red. Horizontal edges are more cyan/green. Edges which go from upper right to lower left are more yellow, and edges which go from upper left to lower right are more blue. I think this is similar to the edge filter in Photoshop, but may be less efficient. At any rate, this is the fixed version that I wrote from scratch. Use at your own risk (-_^) This demo version takes a snapshot from a webcam when you click the mouse over flash stage, and it shows the effects of the function.
ActionScript3 source code
/**
* Copyright j2e ( http://wonderfl.net/user/j2e )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/9SNm
*/
// forked from j2e's Bitmap Edge and Orientation Transform Best
// forked from j2e's Bitmap Edge and Orientation Transform
package {
/// written by j2e japanese2english@gmail.com
/// The function itself takes bitmapData and overwrites it with edge data.
/// The edge data is color-coded and can be used to determine
/// the orientation of the edge at any point when read or further manipulated.
/// Vertical edges are more red. Horizontal edges are more cyan/green.
/// Edges which go from upper right to lower left are more yellow, and
/// edges which go from upper left to lower right are more blue.
/// I think this is similar to the edge filter in Photoshop, but may be less efficient.
/// At any rate, this is the fixed version that I wrote from scratch. Use at your own risk (-_^)
/// This demo version takes a snapshot from a webcam when you click the mouse over
/// flash stage, and it shows the effects of the function.
import flash.display.AVM1Movie;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BitmapDataChannel;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.media.Camera;
import flash.media.Video;
import flash.events.MouseEvent;
import flash.filters.ConvolutionFilter;
import flash.filters.BitmapFilter;
public class FlashTest extends Sprite {
//private var bmd:BitmapData = new BitmapData(0, 0, 200, 200);
private var cam:Camera;
private var vid:Video;
private var myBmd:BitmapData;
//quickEdges.matrixX = 3;
//quickEdges.matrixY = 3;
//quickEdges.matrix = [-1, -1, -1, -1, 8, -1, -1, -1, -1];
//Filter = new GlowFilter(0xFFFFFF, 0, 5, 5, 2, 3, true, true);
private const SMOOTHING:uint = 1;
// SMOOTHING defines how far away sampled pixels will be for comparison,
//higher numbers help to eliminate graininess
public function FlashTest() {
// write as3 code here..
cam = Camera.getCamera();
cam.setMode(640, 480, 10, false);
vid = new Video();
vid.attachCamera(cam);
stage.addEventListener(MouseEvent.CLICK, onClick);
myBmd = new BitmapData(cam.width, cam.height, false, 0);
myBmd.draw(vid);
QuickEdges(myBmd);
}
private function onClick(event:MouseEvent):void {
myBmd = new BitmapData(cam.width, cam.height, false, 0);
var rect:Rectangle = new Rectangle(0, 0, myBmd.width, myBmd.height);
var pt:Point = new Point(0, 0);
myBmd.draw(vid);
//EdgeTransform(myBmd);
//myBmd.applyFilter(myBmd, rect, pt, quickEdges);
QuickEdges(myBmd);
this.addChild(new Bitmap(myBmd));
}
private function QuickEdges(bmd:BitmapData):void {
var rect:Rectangle = new Rectangle(0, 0, bmd.width, bmd.height);
var pt:Point = new Point(0, 0);
var vertEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, 0, 0, -1, 2, -1, 0, 0, 0]);
var horEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, -1, 0, 0, 2, 0, 0, -1, 0]);
var verthorEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, 0, -1, 0, 2, 0, -1, 0, 0]);
var horvertEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [-1, 0, 0, 0, 2, 0, 0, 0, -1]);
var verthorvertEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [-1, 0, 0, -1, 4, -1, 0, 0, -1]);
var horhorvertEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [-1, -1, 0, 0, 4, 0, 0, -1, -1]);
var horverthorEdges:ConvolutionFilter = new ConvolutionFilter(3, 3, [0, -1, -1, 0, 4, 0, -1, -1, 0]);
// Create bitmaps for writing edge info to
var nRedBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var nGreenBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var nBlueBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
nRedBmd.applyFilter(bmd, rect, pt, verthorvertEdges);
nGreenBmd.applyFilter(bmd, rect, pt, horhorvertEdges);
nBlueBmd.applyFilter(bmd, rect, pt, horverthorEdges);
bmd.copyChannel(nRedBmd, rect, pt, BitmapDataChannel.RED, BitmapDataChannel.RED);
bmd.copyChannel(nGreenBmd, rect, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
bmd.copyChannel(nBlueBmd, rect, pt, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
}
/// EdgeTransform takes bitmapData and overwrites it with its edge info
private function EdgeTransform(bmd:BitmapData):void {
var rect:Rectangle = new Rectangle(0, 0, bmd.width, bmd.height);
var pt:Point = new Point(0, 0);
/// Split input bitmap into different color channels to preserve color contrast effect
var redBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var greenBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var blueBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
redBmd.copyChannel(bmd, rect, pt, BitmapDataChannel.RED, BitmapDataChannel.RED);
greenBmd.copyChannel(bmd, rect, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
blueBmd.copyChannel(bmd, rect, pt, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
// Create bitmaps for writing edge info to
var nRedBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var nGreenBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var nBlueBmd:BitmapData = new BitmapData(bmd.width, bmd.height, false, 0x000000);
var rgbR:uint;
var rgbG:uint;
var rgbB:uint;
var oldRgbR:uint;
var oldRgbG:uint;
var oldRgbB:uint;
var newRgbR:uint;
var newRgbG:uint;
var newRgbB:uint;
var vertOrientation:uint;
var horOrientation:uint;
var verthorOrientation:uint;
var horvertOrientation:uint;
var ul:uint;
var ll:uint;
var dl:uint;
var uu:uint;
var ur:uint;
var rr:uint;
var dr:uint;
var c:uint;
var dd:uint;
var y:uint;
var x:uint;
//// Go through each channel bitmap separately to preserve color contrast effect
//// First red channel
//// Go through each channel bitmap separately to preserve color contrast effect
//// First red channel
for (y = SMOOTHING; y < bmd.height; y++)
{
// Get pixel colors from a 2x3 box of bitmap
c = redBmd.getPixel(SMOOTHING, y);
ul = redBmd.getPixel(0, y-SMOOTHING);
ll = redBmd.getPixel(0, y);
dl = redBmd.getPixel(0, y+SMOOTHING);
uu = redBmd.getPixel(SMOOTHING, y-SMOOTHING);
dd = redBmd.getPixel(SMOOTHING, y+SMOOTHING);
for (x = SMOOTHING; x < bmd.width; x++)
{
// Get pixel colors from right-hand column of 3x3 box
ur = redBmd.getPixel(x+SMOOTHING, y-SMOOTHING);
rr = redBmd.getPixel(x+SMOOTHING, y);
dr = redBmd.getPixel(x+SMOOTHING, y+SMOOTHING);
//calculate the angle of the edge for the center point c
// depending upon surrounding edge pattern in 3x3 box
vertOrientation = uint((Math.abs(ll - c) + Math.abs(rr - c)) / 2);
horOrientation = uint((Math.abs(uu - c) + Math.abs(dd - c)) / 2);
verthorOrientation = uint((Math.abs(ur - c) + Math.abs(dl - c)) / 2);
horvertOrientation = uint((Math.abs(dr - c) + Math.abs(ul - c)) / 2);
// Give each instantaneous edge orientation angle a color code
rgbR = uint((vertOrientation + horvertOrientation)/0x010101);
rgbG = uint((horOrientation + horvertOrientation)/0x010101);
rgbB = uint((horOrientation + verthorOrientation)/0x010101);
rgbR *= 0x010000;
rgbG *= 0x000100;
rgbB *= 0x000001;
oldRgbR = nRedBmd.getPixel(x, y);
oldRgbG = nGreenBmd.getPixel(x, y);
oldRgbB = nBlueBmd.getPixel(x, y);
nRedBmd.setPixel(x, y, rgbR + oldRgbR);
nGreenBmd.setPixel(x, y, rgbG + oldRgbG);
nBlueBmd.setPixel(x, y, rgbB + oldRgbB);
//shift values for next pass when checking next 3x3 box
ll = c;
c = rr;
ul = uu;
uu = ur;
dl = dd;
dd = dr;
}
}
// Next blue channel
for (y = SMOOTHING; y < bmd.height; y++)
{
// Get pixel colors from a 2x3 box of bitmap
c = blueBmd.getPixel(SMOOTHING, y);
ul = blueBmd.getPixel(0, y-SMOOTHING);
ll = blueBmd.getPixel(0, y);
dl = blueBmd.getPixel(0, y+SMOOTHING);
uu = blueBmd.getPixel(SMOOTHING, y-SMOOTHING);
dd = blueBmd.getPixel(SMOOTHING, y+SMOOTHING);
for (x = SMOOTHING; x < bmd.width; x++)
{
// Get pixel colors from right-hand column of 3x3 box
ur = blueBmd.getPixel(x+SMOOTHING, y-SMOOTHING);
rr = blueBmd.getPixel(x+SMOOTHING, y);
dr = blueBmd.getPixel(x+SMOOTHING, y+SMOOTHING);
//calculate the angle of the edge for the center point c
// depending upon surrounding edge pattern in 3x3 box
vertOrientation = uint((Math.abs(ll - c) + Math.abs(rr - c)) / 2);
horOrientation = uint((Math.abs(uu - c) + Math.abs(dd - c)) / 2);
verthorOrientation = uint((Math.abs(ur - c) + Math.abs(dl - c)) / 2);
horvertOrientation = uint((Math.abs(dr - c) + Math.abs(ul - c)) / 2);
// Give each instantaneous edge orientation angle a color code
rgbR = uint((vertOrientation + horvertOrientation)/0x010101);
rgbG = uint((horOrientation + horvertOrientation)/0x010101);
rgbB = uint((horOrientation + verthorOrientation)/0x010101);
rgbR *= 0x010000;
rgbG *= 0x000100;
rgbB *= 0x000001;
oldRgbR = nRedBmd.getPixel(x, y);
oldRgbG = nGreenBmd.getPixel(x, y);
oldRgbB = nBlueBmd.getPixel(x, y);
nRedBmd.setPixel(x, y, rgbR + oldRgbR);
nGreenBmd.setPixel(x, y, rgbG + oldRgbG);
nBlueBmd.setPixel(x, y, rgbB + oldRgbB);
//shift values for next pass when checking next 3x3 box
ll = c;
c = rr;
ul = uu;
uu = ur;
dl = dd;
dd = dr;
}
}
/// Next green channel
for (y = SMOOTHING; y < bmd.height; y++)
{
// Get pixel colors from a 2x3 box of bitmap
c = greenBmd.getPixel(SMOOTHING, y);
ul = greenBmd.getPixel(0, y-SMOOTHING);
ll = greenBmd.getPixel(0, y);
dl = greenBmd.getPixel(0, y+SMOOTHING);
uu = greenBmd.getPixel(SMOOTHING, y-SMOOTHING);
dd = greenBmd.getPixel(SMOOTHING, y+SMOOTHING);
for (x = SMOOTHING; x < bmd.width; x++)
{
// Get pixel colors from right-hand column of 3x3 box
ur = greenBmd.getPixel(x+SMOOTHING, y-SMOOTHING);
rr = greenBmd.getPixel(x+SMOOTHING, y);
dr = greenBmd.getPixel(x+SMOOTHING, y+SMOOTHING);
//calculate the angle of the edge for the center point c
// depending upon surrounding edge pattern in 3x3 box
vertOrientation = uint((Math.abs(ll - c) + Math.abs(rr - c)) / 2);
horOrientation = uint((Math.abs(uu - c) + Math.abs(dd - c)) / 2);
verthorOrientation = uint((Math.abs(ur - c) + Math.abs(dl - c)) / 2);
horvertOrientation = uint((Math.abs(dr - c) + Math.abs(ul - c)) / 2);
// Give each instantaneous edge orientation angle a color code
rgbR = uint((vertOrientation + horvertOrientation)/0x010101);
rgbG = uint((horOrientation + horvertOrientation)/0x010101);
rgbB = uint((horOrientation + verthorOrientation)/0x010101);
rgbR *= 0x010000;
rgbG *= 0x000100;
rgbB *= 0x000001;
oldRgbR = nRedBmd.getPixel(x, y);
oldRgbG = nGreenBmd.getPixel(x, y);
oldRgbB = nBlueBmd.getPixel(x, y);
nRedBmd.setPixel(x, y, rgbR + oldRgbR);
nGreenBmd.setPixel(x, y, rgbG + oldRgbG);
nBlueBmd.setPixel(x, y, rgbB + oldRgbB);
//shift values for next pass when checking next 3x3 box
ll = c;
c = rr;
ul = uu;
uu = ur;
dl = dd;
dd = dr;
}
}
// Copy edge information from each respective channel over to original bitmap
bmd.copyChannel(nRedBmd, rect, pt, BitmapDataChannel.RED, BitmapDataChannel.RED);
bmd.copyChannel(nGreenBmd, rect, pt, BitmapDataChannel.GREEN, BitmapDataChannel.GREEN);
bmd.copyChannel(nBlueBmd, rect, pt, BitmapDataChannel.BLUE, BitmapDataChannel.BLUE);
}
}
}
