Antialiased lines on bitmap
/**
* Copyright hortobagyi.tom ( http://wonderfl.net/user/hortobagyi.tom )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/hLYi
*/
package {
import flash.text.TextField;
import flash.geom.Matrix;
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Shape;
import flash.utils.getTimer;
import flash.display.StageQuality;
public class FlashTest extends Sprite
{
public var bmd:BitmapData;
public var bm:Bitmap;
public var line:Shape;
public var w:int = 300;
public var txt:TextField;
private var coeff_1:Number = Math.PI / 4;
private var coeff_2:Number;
private var r:Number;
private var angle:Number;
private var absY:Number;
public function FlashTest()
{
// write as3 code here..
bmd = new BitmapData(w, w, true, 0x0);
bm = new Bitmap(bmd, "auto", false);
this.addChild(bm);
txt = new TextField();
this.addChild(txt)
txt.width = 400;
txt.y = w;
txt.text = "debug";
line = new Shape();
line.graphics.beginFill(0x0, 0.2);
line.graphics.drawRect(0, 0, 1, 1.0);
line.graphics.endFill();
var ms:int = getTimer();
bmd.lock();
for (var i:int = 0; i < 1000; i++) // benchmark
{
lineTo( Math.random() * w, Math.random() * w, Math.random() * w, Math.random() * w ); // drawWithQuality
//efla( Math.random() * w, Math.random() * w, Math.random() * w, Math.random() * w, 0x33000000 ); // draw with setPixel32 - this is still faster
}
bmd.unlock();
txt.text = (getTimer() - ms) + " ms";
}
/*
public function atan2(y:Number,x:Number):Number
{
coeff_2 = 3 * coeff_1;
absY = y;
if (absY < 0) absY = -absY; //Math.abs
if(x >= 0)
{
r= (x - absY) / (x + absY);
angle = coeff_1 - coeff_1 * r;
} else
{
r = (x + absY) / (absY - x);
angle = coeff_2 - coeff_1 * r;
}
return y < 0 ? -angle : angle;
}
//*/
public function lineTo(x0:Number, y0:Number, x1:Number, y1:Number):void
{
var ydiff:Number = y1 - y0, xdiff:Number = x1 - x0;
var mtx:Matrix = new Matrix();
mtx.scale(Math.sqrt(ydiff * ydiff + xdiff * xdiff), 1.0);
//*
// inplace atan2 - faster a bit
coeff_2 = 3 * coeff_1;
absY = ydiff;
if (absY < 0) absY = -absY; //Math.abs
if(x >= 0)
{
r= (xdiff - absY) / (xdiff + absY);
angle = coeff_1 - coeff_1 * r;
} else
{
r = (xdiff + absY) / (absY - xdiff);
angle = coeff_2 - coeff_1 * r;
}
mtx.rotate(ydiff < 0 ? -angle : angle);
//*/
//mtx.rotate(Math.atan2(ydiff, xdiff));
mtx.translate(x0, y0);
bmd.drawWithQuality(line, mtx, null, null, null, false, StageQuality.MEDIUM);
}
/**
EFLA with antialiasing
**/
private function efla(x:int, y:int, x2:int, y2:int, color:uint):void
{
var shortLen:int = y2-y;
var longLen:int = x2-x;
if((shortLen ^ (shortLen >> 31)) - (shortLen >> 31) > (longLen ^ (longLen >> 31)) - (longLen >> 31))
{
shortLen ^= longLen;
longLen ^= shortLen;
shortLen ^= longLen;
var yLonger:Boolean = true;
}
else
{
yLonger = false;
}
var inc:int = longLen < 0 ? -1 : 1;
var multDiff:Number = (longLen == 0 ? shortLen : shortLen / longLen) * inc;
var tcol:uint = 0, xx:Number = x, yy:Number = y, alfa:uint = color >> 24;
var a:Number;
color &= 0xffffff;
//bmd.lock();
if (yLonger)
{
for (var i:int = 0; i != longLen; i += inc)
{
a = xx - int(xx);
tcol = blendColors( color | (int(alfa * (1.0 - a)) << 24), bmd.getPixel32(int(xx), y + i));
bmd.setPixel32(int(xx), y + i, tcol);
tcol = blendColors( color | (int(alfa * a) << 24), bmd.getPixel32(int(xx + 1), y + i));
bmd.setPixel32(int(xx + 1), y + i, tcol);
xx += multDiff;
}
}
else
{
for (i = 0; i != longLen; i += inc)
{
a = yy - int(yy);
tcol = blendColors( color | (int(alfa * (1.0 - a)) << 24), bmd.getPixel32(x + i, int(yy)));
bmd.setPixel32(x + i, int(yy), tcol);
tcol = blendColors( color | (int(alfa * a) << 24), bmd.getPixel32(x + i, int(yy + 1)));
bmd.setPixel32(x + i, int(yy + 1), tcol);
yy += multDiff;
}
}
//bmd.unlock();
}
private function blendColors(col1:uint, col2:uint):uint
{
var aT:uint = col1 >>> 24;
var rT:uint = (col1 >>> 16 & 0xFF) * (aT/0xFF);
var gT:uint = (col1 >>> 8 & 0xFF) * (aT/0xFF);
var bT:uint = (col1 & 0xFF) * (aT/0xFF);
var aB:uint = col2 >>> 24;
var rB:uint = (col2 >>> 16 & 0xFF) * (aB/0xFF);
var gB:uint = (col2 >>> 8 & 0xFF) * (aB/0xFF);
var bB:uint = (col2 & 0xFF) * (aB /0xFF);
var alpValue:Number = (0xFF - aT)/0xFF;
var aN:uint = Math.min(aB + aT, 0xFF);
var rN:uint = Math.min(rB * alpValue + rT, 0xFF);
var gN:uint = Math.min(gB * alpValue + gT, 0xFF);
var bN:uint = Math.min(bB * alpValue + bT, 0xFF);
return(aN << 24 | rN << 16 | gN << 8 | bN);
}
}
}