Category Archives: graphics algorithms

Seamless Tiles

Actionscript:
  1. [SWF(width=600, height=500, backgroundColor=0xFFFFFF, frameRate=30)]
  2.  
  3. function seamlessTile(img:BitmapData, featherSize:Number = 5):BitmapData{
  4.     var pnt:Point = new Point(0,0);
  5.     var tile:BitmapData = new BitmapData(img.width, img.height, true, 0xFF000000);
  6.     tile.copyPixels(img, img.rect, pnt, null, null, true);
  7.    
  8.     var flipped:BitmapData = new BitmapData(img.width, img.height, true, 0xFF000000);
  9.     var m:Matrix = new Matrix();
  10.     m.scale(-1, 1);
  11.     m.translate(tile.width,0);
  12.     flipped.draw(tile, m);
  13.    
  14.     var aChannel:BitmapData = new BitmapData(img.width, img.height, true, 0x00000000);
  15.     var grad:Sprite = new Sprite();
  16.     m.createGradientBox(img.width, img.height, 0, 0, 0);
  17.    
  18.     grad.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF],  [1, 0], [0, (255 / img.width) * img.width / featherSize], m, SpreadMethod.PAD);
  19.    
  20.     grad.graphics.drawRect(0,0,img.width, img.height);
  21.     aChannel.draw(grad);
  22.  
  23.     tile.copyPixels(flipped, flipped.rect, pnt, aChannel, pnt, true);
  24.    
  25.     m.identity();
  26.     m.scale(1, -1);
  27.     m.translate(0,tile.height);
  28.     flipped.draw(tile, m)
  29.    
  30.     aChannel.fillRect(aChannel.rect, 0x00000000);
  31.     m.createGradientBox(img.width, img.height, Math.PI / 2, 0, 0);
  32.     grad.graphics.clear();
  33.     grad.graphics.beginGradientFill(GradientType.LINEAR, [0xFFFFFF, 0xFFFFFF], [1, 0], [0, (255 / img.height) * img.height / featherSize],  m, SpreadMethod.PAD);
  34.    
  35.     grad.graphics.drawRect(0,0,img.width, img.height);
  36.     aChannel.draw(grad, grad.transform.matrix);
  37.    
  38.     tile.copyPixels(flipped, flipped.rect, pnt, aChannel, pnt, true);
  39.     return tile;
  40. }
  41.  
  42. // test out the function:
  43. var canvas:BitmapData = new BitmapData(600, 470, true, 0xFF000000);
  44. addChild(new Bitmap(canvas));
  45.  
  46. var image:Loader = new Loader();
  47. image.load(new URLRequest("http://actionsnippet.com/imgs/paper.jpg"));
  48. image.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
  49. var texture:BitmapData;
  50.  
  51. function onLoaded(evt:Event):void {
  52.     texture =  Bitmap(image.content).bitmapData;
  53.     addEventListener(Event.ENTER_FRAME, onLoop);
  54.     image.removeEventListener(Event.COMPLETE, onLoaded);
  55. }
  56.  
  57. function onLoop(evt:Event):void{
  58.     var tile:BitmapData = seamlessTile(texture, Math.max(1,mouseX/30));
  59.     var p:Point = new Point();
  60.     for (var i:int = 0; i<8; i++){
  61.         p.x = (i % 4) * tile.width;
  62.         p.y = int(i / 4) * tile.height;
  63.         canvas.copyPixels(tile, tile.rect, p);
  64.     }
  65. }

The above demos a function called seamlessTile() which takes a BitmapData object and uses an oldschool seamless tile technique on it.

The result is that you can have an image that would normally tile like this:


end up looking like this:



You can take a look at the swf here.

I learned how seamless tiles worked by observing the KPT seamless welder filter while I was in highschool. I wish I could dig up all that old KPT stuff again....

There are better seamless tile algorithms out there.... this one is very primitive, but it will work nicely if used properly. Could work well with a composite texture in Papervision 3D for instance...

Also posted in BitmapData, pixel manipulation | Tagged , | 5 Comments

Quadratic Bezier

Actionscript:
  1. var canvas:BitmapData=new BitmapData(280,280,false,0x000000);
  2. addChild(new Bitmap(canvas, PixelSnapping.AUTO, true));
  3. var color:uint;
  4. // anchor x1, anchor y1,
  5. // control-handle x2, control-handle y2,
  6. // anchor x3, anchor y3, [resolution incremental value between 0-1]
  7. function quadBezier(x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number, resolution:Number=.03):void {
  8.     var b:Number,pre1:Number,pre2:Number,pre3:Number,pre4:Number;
  9.     for (var a:Number = 0; a <1;a+=resolution) {
  10.    
  11.         b=1-a;
  12.         pre1=(a*a);
  13.         pre2=2*a*b;
  14.         pre3=(b*b);
  15.        
  16.         canvas.setPixel(pre1*x1 + pre2*x2  + pre3*x3 ,
  17.                                      pre1*y1 + pre2*y2 + pre3*y3, color);
  18.     }
  19. }
  20.  
  21. // draw a few
  22. color = 0xFFFFFF;
  23.  
  24. for (var i:int = 0; i<20; i++){
  25. quadBezier(40,100, 150 , 20 + i * 10 , 200, 100,.01);
  26. }
  27.  
  28. color = 0xFF0000;
  29.  
  30. for (i= 0; i<20; i++){
  31. quadBezier(150,200, 100 + i * 10, 100  , 120, 30,.01);
  32. }

The above demos a function that draws quadratic bezier curves using setPixel().

One of the first posts on this site was a snippet that used setPixel() to draw a cubic bezier curve. I recently needed to do the exact same thing but I wanted to use a quadratic bezier... I knew I had the code laying around somewhere, but I couldn't seem to find it so I just looked on wikipedia and changed the previous cubicBezier() function accordingly.

Also posted in BitmapData, bezier, pixel manipulation, setPixel | Tagged , , | 2 Comments

Bresenham Circle Filled

Actionscript:
  1. var canvas:BitmapData = new BitmapData(400, 400, false, 0xCCCCCC);
  2. addChild(new Bitmap(canvas));
  3.  
  4. fillCircle(100,100,50,0xFF0000);
  5.  
  6. function fillCircle(xp:Number,yp:Number, radius:Number, col:uint = 0x000000):void {
  7.     var xoff:int =0;
  8.     var yoff:int = radius;
  9.     var balance:int = -radius;
  10.  
  11.     while (xoff <= yoff) {
  12.          var p0:int = xp - xoff;
  13.          var p1:int = xp - yoff;
  14.          
  15.          var w0:int = xoff + xoff;
  16.          var w1:int = yoff + yoff;
  17.          
  18.          hLine(p0, yp + yoff, w0, col);
  19.          hLine(p0, yp - yoff, w0, col);
  20.          
  21.          hLine(p1, yp + xoff, w1, col);
  22.          hLine(p1, yp - xoff, w1, col);
  23.        
  24.         if ((balance += xoff++ + xoff)>= 0) {
  25.             balance-=--yoff+yoff;
  26.         }
  27.     }
  28. }
  29.  
  30. function hLine(xp:Number, yp:Number, w:Number, col:uint):void {
  31.     for (var i:int = 0; i <w; i++){
  32.         canvas.setPixel(xp + i, yp, col);
  33.     }
  34. }

An implementation of yesterdays post that draws a filled circle instead of an outlined circle.

Also posted in BitmapData, pixel manipulation, setPixel | Tagged , | Leave a comment

Bresenham Circle No Multiplication

Actionscript:
  1. var canvas:BitmapData = new BitmapData(400, 400, false, 0xCCCCCC);
  2. addChild(new Bitmap(canvas));
  3.  
  4. drawCircle(200,100, 50);
  5.  
  6. // y, y radius, color
  7. function drawCircle(xp:Number,yp:Number, radius:Number, col:uint =0x000000):void {
  8.     var balance:int;
  9.     var xoff:int;
  10.     var yoff:int;
  11.     xoff=0;
  12.     yoff=radius;
  13.     balance=- radius;
  14.  
  15.     while (xoff <= yoff) {
  16.         canvas.setPixel(xp+xoff, yp+yoff, col);
  17.         canvas.setPixel(xp-xoff, yp+yoff, col);
  18.         canvas.setPixel(xp-xoff, yp-yoff, col);
  19.         canvas.setPixel(xp+xoff, yp-yoff, col);
  20.         canvas.setPixel(xp+yoff, yp+xoff, col);
  21.         canvas.setPixel(xp-yoff, yp+xoff, col);
  22.         canvas.setPixel(xp-yoff, yp-xoff, col);
  23.         canvas.setPixel(xp+yoff, yp-xoff, col);
  24.  
  25.         if ((balance += xoff++ + xoff)>= 0) {
  26.             balance-=--yoff+yoff;
  27.         }
  28.     }
  29. }

The above demos a circle drawing algorithm. This will draw an outlined circle with no fill. This implementation doesn't use multiplication.

Using setPixel to draw primitive shapes can be a good learning experience. I found this basic implementation of the Bresenham Circle algorithm a few years back and lost the original link.... I dug around for a good hour trying to find the original but to no avail. So if someone recognizes this interesting implementation .... let me know :)

The original code was written in java I think.

If your curious. The standard implementation I keep finding online looks something like this:

Actionscript:
  1. // ported from http://www.codeuu.com/Bresenham_Circle
  2. function drawCircle(cx:Number, cy:Number, r:Number, col:uint):void{
  3.     var xp:int  = 0, yp:int= r ;
  4.     var d:int = 3 - (2 * r);
  5.    
  6.     while(xp <= yp){
  7.        
  8.         canvas.setPixel(cx+xp,cy+yp,col);
  9.         canvas.setPixel(cx+yp,cy+xp,col);
  10.         canvas.setPixel(cx-xp,cy+yp,col);
  11.         canvas.setPixel(cx+yp,cy-xp,col);
  12.         canvas.setPixel(cx-xp,cy-yp,col);
  13.         canvas.setPixel(cx-yp,cy-xp,col);
  14.         canvas.setPixel(cx+xp,cy-yp,col);
  15.         canvas.setPixel(cx-yp,cy+xp,col);
  16.        
  17.         if (d<0){
  18.             d += (4*xp)+6;
  19.         }else{
  20.             d += (4*(xp-yp))+10;
  21.             yp -= 1;
  22.         }
  23.         xp++;
  24.     }
  25.    
  26. }

I did a few speed tests against the first one that doesn't make use of multiplication and it is only ever so slightly faster....

Also posted in BitmapData, pixel manipulation, setPixel | Tagged , , , | Leave a comment