※現在、「wonderfl build flash online」求人コンテンツ制作に関してのアンケートを実施中です!みなさまのお力添えを頂いて、続々とアンケート結果が集まっていますが、まだまだ募集しております。ご協力のほど、どうぞよろしくお願いいたします!

wonderfl運営事務局
→アンケートページ(※ログインしてからお答えいただけるようになっています。)

 notice: Flash editor updated! Join the development! Thanks to MiniBuilder


FORKED
  1. // forked from miyaoka's Retro Avatars
  2. /*
  3. =======================================
  4. Retro Avatars for Flash
  5. =======================================
  6. -Type avatar name to generate image.
  7. -press ENTER key to save current image as PNG.
  8.  
  9. // Retro Avatars
  10. // -------------
  11.  
  12. // By Richard Phipps
  13. // (Open source, but a credit if used would be nice!)
  14.  
  15. http://retroremakes.com/forum/index.php/topic,657.0.html
  16. より移植してみました
  17.  
  18. [Sample]
  19. http://www.indiegames.com/blog/2009/06/freeware_app_pick_retro_avatar.html
  20. http://www.flickr.com/photos/miyaoka/3592194889/
  21. */
  22. package 
  23. {
  24.     import flash.display.Sprite;
  25.     import flash.text.TextField;
  26.     import flash.text.TextFormat;
  27.     import flash.text.TextFormatAlign;
  28.     import flash.text.TextFieldType;
  29.     import flash.text.TextFieldAutoSize;
  30.     import flash.ui.Keyboard;
  31.     import flash.events.KeyboardEvent;
  32.     import flash.display.Bitmap;
  33.     import flash.display.BitmapData;
  34.     import flash.utils.ByteArray;
  35.     import com.adobe.images.PNGEncoder;
  36.     import flash.net.FileReference;
  37.     import flash.geom.Matrix;
  38.     
  39.     import flash.system.Capabilities;
  40.     import flash.system.IME;
  41.     [SWF(width="465", height="465", backgroundColor= 0x0, frameRate="60")]
  42.     public class RetroAvatars
  43.     extends Sprite 
  44.     {
  45.         private    var tfd:TextField = new TextField();
  46.         private var maxNameLength:uint = 9;
  47.         private var bmd:AvatarBMD = new AvatarBMD(1212false);
  48.         private var bmd32:BitmapData = new BitmapData(bmd.width, bmd.height, true, 0x0);
  49.         private var bmp:Bitmap = new Bitmap(bmd32);
  50.         
  51.         private static const EYES_COL:int = 0;
  52.         private static const NOSE_COL:int = 0;
  53.         private static const MOUSE_COL:int = 0;
  54.         
  55.         private var isFirst:Boolean = true;
  56.         public function RetroAvatars():void 
  57.         {
  58.             //bg
  59.             graphics.beginFill(0);
  60.             graphics.drawRect(00, stage.stageWidth, stage.stageHeight);
  61.             
  62.             //ime off
  63.             if (Capabilities.hasIME)
  64.             {
  65.                 try
  66.                 {
  67.                     IME.enabled = false;
  68.                 }
  69.                 catch (e:Error) {}
  70.             }
  71.             
  72.             //bmp
  73.             bmp.scaleX = bmp.scaleY = 24;
  74.             bmp.x = (stage.stageWidth - bmp.width) / 2;
  75.             bmp.y = 40;
  76.             addChild(bmp);            
  77.             
  78.             
  79.             //text
  80.             var tft:TextFormat = new TextFormat();
  81.             tft.align = TextFormatAlign.CENTER;
  82.             tft.bold = true;
  83.             tft.font = "Verdana";
  84.             tft.letterSpacing = 5;
  85.             tft.size = 48;
  86.             
  87.             tfd.defaultTextFormat = tft;
  88.             tfd.autoSize = TextFieldAutoSize.CENTER;
  89.             
  90.             tfd.x = 465/2;
  91.             tfd.y = 380;
  92.             tfd.text = "ENTER NAME";
  93.             tfd.textColor = 0xDDDDDD;
  94.             isFirst = true;
  95.             addChild(tfd);
  96.             
  97.             //event
  98.             stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
  99.         }
  100.         private function keyDownHandler(e:KeyboardEvent):void 
  101.         {
  102.             var cc:uint = e.charCode;
  103.             
  104.             // lower case keys, so make upper case.
  105.             if (97 <= cc && cc <= 122) cc -= 32;
  106.             
  107.             if (isFirst) tfd.text = ""; isFirst = false;
  108.             if (
  109.                 tfd.length < maxNameLength && 
  110.                 (
  111.                 cc == 32 // Space
  112.                 || (cc >= 65 && cc <= 90//letters
  113.                 || (cc >= 48 && cc <= 57//numbers 
  114.                 )
  115.             )
  116.             {
  117.                 tfd.text = tfd.text.concat(String.fromCharCode(cc));
  118.             }
  119.             else if ( cc == 8 && tfd.length > 0//Backspace
  120.             {
  121.                 tfd.text = tfd.text.substr(0, tfd.length -1);
  122.             }
  123.             else if (cc == 13 && 0 < tfd.text.length) // ENTER key
  124.             {
  125.                 //save PNG to local
  126.                 var mtx:Matrix = new Matrix();
  127.                 var sc:Number = 8;
  128.                 mtx.scale(sc, sc);
  129.                 var tempBmd:BitmapData = new BitmapData(bmd32.width * sc, bmd32.height * sc, true,0);
  130.                 tempBmd.draw(bmd32, mtx);
  131.                 var ba:ByteArray = PNGEncoder.encode(tempBmd);
  132.                 var fr:FileReference = new FileReference;
  133.                 fr.save(ba, tfd.text + ".png");
  134.             }
  135.             
  136.             
  137.             var nameLen:int = tfd.text.length;
  138.             if (nameLen == 0
  139.             {
  140.                 bmd32.fillRect(bmd32.rect, 0);
  141.                 return;
  142.             }
  143.             
  144.             // ------------
  145.             // make code from text and set to srand
  146.             Crand.srand(0);
  147.             var code:int = 0;
  148.             for (var g:int = 0; g < 32; g++)
  149.             {
  150.                 code += tfd.text.charCodeAt(g % nameLen) * Crand.rand() % 1024;
  151.             }
  152.             Crand.srand(code); // Seed random generator with code.
  153.             
  154.             //make avatar color.  Random (but not too dark) colour.
  155.             var col:int =
  156.             Crand.rand() % 192 + 64
  157.             | Crand.rand() % 192 + 64 << 8
  158.             | Crand.rand() % 192 + 64 << 16;
  159.             
  160.             tfd.textColor = col;
  161.             
  162.             // ------------
  163.             // build avatar img
  164.             bmd.build();
  165.             bmd.removeNoise(0);
  166.             bmd.mirror();            
  167.             bmd.enhanceFace();
  168.             
  169.             
  170.             //copy to 32bit bmd and set color
  171.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, ">=", 0xff << 24 | AvatarBMD.SOLID_COL, 0xFF <<24  | col);
  172.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.EYES_COL, EYES_COL);
  173.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.NOSE_COL, NOSE_COL);
  174.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.MOUSE_COL, MOUSE_COL);
  175.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.BLANK_COL, 0);
  176.         }
  177.     }    
  178. }
  179. import flash.display.BitmapData
  180. import flash.geom.Matrix;
  181. import flash.geom.Rectangle;
  182. class AvatarBMD
  183. extends BitmapData
  184. {
  185.     public static const EYES_COL:int = 1;
  186.     public static const NOSE_COL:int = 2;
  187.     public static const MOUSE_COL:int = 3;
  188.     public static const SOLID_COL:int = 0xFF;
  189.     public static const BLANK_COL:int = 0x0;
  190.     public function AvatarBMD(width:int, height:int, transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF):void 
  191.     {
  192.         //bmd24
  193.         super(width, height, false, fillColor);
  194.     }
  195.     public function build():void 
  196.     {
  197.         var c:int = 158;
  198.         for (var y:int = 0; y < height; y++)
  199.         {
  200.             for (var x:int = 0; x < width; x++)
  201.             {
  202.                 setPixel(x, y, (Crand.rand() % 356 > c) ? BLANK_COL : SOLID_COL);
  203.             }
  204.         }
  205.     }
  206.     public function enhanceFace():void 
  207.     {
  208.         var eyes:Boolean;
  209.         var nose:Boolean;
  210.         var mouth:Boolean;
  211.         var x:int;
  212.         var y:int;
  213.         var hx:int = width / 2 - 1// Half width of sprite variable.
  214.         // Detect eyes one pixel away from horizontal centre (look from just below the top edge to the middle of the vertical height).
  215.         for (y = 1; y < height / 2; y++)
  216.         {
  217.             if (getPixel(hx - 1, y) == BLANK_COL) // 0 - Empty, Pixel?
  218.             {
  219.                 floodFill(hx - 1, y, EYES_COL); // Mark area with reserved colour 1 (normal colours are 0 - empty & 255 - solid).
  220.                 if (checkForFilledEdge() == 0break// If this eye area doesn't touch the edges of the image, then stop searching.
  221.                 floodFill(hx - 1, y, BLANK_COL);     // It reaches the edge, so refill as 0 - empty and keep looking.
  222.             }
  223.             if (getPixel(hx - 2, y) == BLANK_COL) // Any potential eye areas one pixel further away?
  224.             {
  225.                 floodFill(hx - 2, y, EYES_COL); 
  226.                 if (checkForFilledEdge() == 0break;
  227.                 floodFill(hx - 2, y, BLANK_COL);                     
  228.             }
  229.         }
  230.         // Ok, we didn't find anything!
  231.         if ( y == height / 2
  232.         {
  233.             // Try to make eyes from any centre pixels (converting them to one pixel further away. i.e. xx -> x  x
  234.             for ( y = 1; y < height; y++)
  235.             {
  236.                 if (getPixel(hx - 1, y) == SOLID_COL && getPixel(hx, y) == BLANK_COL)
  237.                 {
  238.                     setPixel(hx - 1, y, BLANK_COL);
  239.                     setPixel(hx, y, SOLID_COL);
  240.                     setPixel(hx - 1, y + 1, BLANK_COL); // Make the eye 2 pixels (at least) high.  
  241.                     
  242.                     floodFill(hx - 1, y, EYES_COL); 
  243.                     if (checkForFilledEdge() == 0break;
  244.                     floodFill(hx - 1, y, BLANK_COL);                     
  245.                 }
  246.             }
  247.         }
  248.         
  249.         var ny:int = y + 1;
  250.         if (y < height) eyes = true// Ok, we did find eyes
  251.         
  252.         // Still NO eyes.
  253.         if (!eyes)
  254.         {
  255.             // Ok, create fake eyes!
  256.             y = 1 + Crand.rand() % (height / 2);
  257.             
  258.             setPixel(hx - 1, y, EYES_COL);
  259.             outlineArea(1); // Outline to protect area.
  260.             
  261.             eyes = true;
  262.             ny = y + 1;
  263.         }
  264.         
  265.         // Remove any joined up eyes (i.e xx instead of x  x)
  266.         for (y = 1; y < height; y++)
  267.         {
  268.             if (getPixel(hx, y) == EYES_COL)
  269.             {
  270.                 setPixel(hx, y, SOLID_COL);
  271.                 setPixel(hx - 1, y, EYES_COL);
  272.             }
  273.             else
  274.             {
  275.                 if (getPixel(hx - 2, y) == EYES_COL) setPixel(hx, y, SOLID_COL);
  276.                 if (getPixel(hx - 1, y) == EYES_COL) setPixel(hx, y, SOLID_COL);
  277.             }
  278.         }
  279.         mirror(); // Miror all eye work.
  280.         
  281.         if (eyes) outlineArea(EYES_COL); // Protect eyes with solid outline.
  282.         
  283.         trace(ny);
  284.         
  285.         // -------
  286.         // Detect nose
  287.         for (y = ny; y < height; y++)
  288.         {
  289.             if (getPixel(hx, y) == BLANK_COL)
  290.             {
  291.                 floodFill(hx, y, NOSE_COL); // Fill with area colour 2.
  292.                 if ( checkForFilledEdge() == 0break;
  293.                 floodFill(hx, y, BLANK_COL);
  294.             }
  295.         }
  296.         if ( y < 10) nose = true;
  297.         
  298.         // No nose?
  299.         if (!nose)
  300.         {
  301.             // Ok, we won't find a mouth either, but we need to make a nose/mouth one out of any open sections (regardless of touching the edge)
  302.             for (y = ny; y < height - 1; y++)
  303.             {
  304.                 if (getPixel(hx, y) == BLANK_COL)
  305.                 {
  306.                     setPixel(hx, y, NOSE_COL)
  307.                     nose = true;
  308.                     break;
  309.                 }
  310.             }
  311.             
  312.             // Try to find a nose/mouth one pixel away which we can join up. i.e. x  x -> xxxx
  313.             if (!nose)
  314.             {
  315.                 for (y = ny; y < height - 1; y++)
  316.                 {
  317.                     if (getPixel(hx - 1, y) == BLANK_COL)
  318.                     {
  319.                         setPixel(hx -1, y, NOSE_COL)
  320.                         setPixel(hx, y, NOSE_COL)
  321.                         nose = true;
  322.                         break;
  323.                     }
  324.                 }
  325.             
  326.                 // Ok, NOTHING, just create fake mouth/nose!
  327.                 if (!nose)
  328.                 {
  329.                     y = ny + 1 + Crand.rand() % (height / 3);
  330.                     if (y > height - 2) y = height - 2;
  331.                     setPixel(hx, y, NOSE_COL)
  332.                     nose = true;
  333.                     ny = y + 1;
  334.                 }
  335.             }
  336.         }
  337.         else
  338.         {
  339.             ny = y + 1;
  340.             
  341.             // --------
  342.             // Detect mouth    
  343.             for (y = ny; y < height; y++)
  344.             {
  345.                 if (getPixel(hx, y) == BLANK_COL)
  346.                 {
  347.                     floodFill(hx, y, MOUSE_COL);
  348.                     if (checkForFilledEdge() == 0break;
  349.                     floodFill(hx, y, BLANK_COL);
  350.                 }
  351.             }
  352.             if (y < height) mouth = true;
  353.             
  354.             if (!mouth) // Still no mouse, so look one pixel further away and then if found, join up.
  355.             {
  356.                 for (y = ny; y < height - 1; y++)
  357.                 {
  358.                     if (getPixel(hx - 1, y) == BLANK_COL)
  359.                     {
  360.                         setPixel(hx, y, BLANK_COL);
  361.                         floodFill(hx, y, MOUSE_COL);
  362.                         if (checkForFilledEdge() == 0break;
  363.                         floodFill(hx, y, BLANK_COL);
  364.                     }
  365.                 }
  366.             }
  367.             if (y < height) mouth = true;
  368.         }
  369.         // Outline mouth / nose to protect and stop surrounding gfx 'bleeding' in.
  370.         if (mouth) outlineArea(MOUSE_COL);
  371.         if (nose) outlineArea(NOSE_COL);
  372.         
  373.         if (eyes) trimArea(EYES_COL, 33); // Trim eyes to no more than 3 x 3
  374.         if (nose && mouth) trimArea(NOSE_COL, 33); // Trim nose to no more than 3 x 3. Mouth can be bigger..;
  375.         
  376.         mirror(); // Mirror to fix changes symmetrically.
  377.         
  378.         // Now search for any fill in any holes that doesn't leak to the edge of the sprite (passing over eyes, mouth and nose areas).
  379.         const tmpCol:int = 4;
  380.         for (y = 1; y < height -1; y++)
  381.         {
  382.             for (x = 1; x < hx - 1; x++)
  383.             {
  384.                 if (getPixel(x, y) == BLANK_COL)
  385.                 {
  386.                     floodFill(x, y, tmpCol)
  387.                     floodFill(x, y, checkForFilledEdge() == 0 ? SOLID_COL : BLANK_COL);
  388.                 }
  389.             }
  390.         }
  391.         mirror(); // Mirror finally (neccessary?)
  392.     }
  393.     public function mirror():void 
  394.     {
  395.         var mtx:Matrix = new Matrix();
  396.         mtx.scale(-11);
  397.         mtx.translate(width, 0);
  398.         draw(this, mtx , nullnullnew Rectangle(width/20, width, height));
  399.     }
  400.     public function checkForFilledEdge():int
  401.     {
  402.         var c:int;
  403.         for (var y:int = 0; y < height; y++)
  404.         {
  405.             c = getPixel(0, y);
  406.             if (c != BLANK_COL && c != SOLID_COL) return 1;
  407.             c = getPixel(width-1, y);
  408.             if (c != BLANK_COL && c != SOLID_COL) return 1;
  409.         }
  410.         for (var x:int = 0; x < width; x++)
  411.         {
  412.             c = getPixel(x, 0);
  413.             if (c != BLANK_COL && c != SOLID_COL) return 2;
  414.             c = getPixel(x, height -1);
  415.             if (c != BLANK_COL && c != SOLID_COL) return 2;            
  416.         }
  417.         return 0;
  418.     }
  419.     public function outlineArea(col:int):void 
  420.     {
  421.         for (var y:int = 0; y < height; y++)
  422.         {
  423.             for (var x:int = 0; x < width; x++)
  424.             {
  425.                 var c:int = getPixel(x, y);
  426.                 if (c == col) 
  427.                 {
  428.                 // diagonals are only outlined if blank (and not another reserved area).
  429.                 if (getPixel(x - 1, y - 1) == BLANK_COL) setPixel(x - 1, y - 1, SOLID_COL);
  430.                 if (getPixel(x , y - 1) != col) setPixel(x, y - 1, SOLID_COL);
  431.                 if (getPixel(x + 1, y - 1) == BLANK_COL) setPixel(x +1, y - 1, SOLID_COL);
  432.                 if (getPixel(x - 1, y) != col) setPixel(x - 1, y, SOLID_COL);
  433.                 if (getPixel(x + 1, y) != col) setPixel(x + 1, y, SOLID_COL);
  434.                 if (getPixel(x - 1, y + 1) == BLANK_COL) setPixel(x - 1, y + 1, SOLID_COL);
  435.                 if (getPixel(x, y + 1) != col) setPixel(x, y + 1, SOLID_COL);
  436.                 if (getPixel(x + 1, y + 1) == BLANK_COL) setPixel(x + 1, y + 1, SOLID_COL);
  437.                 }
  438.             }
  439.         }
  440.     }
  441.     public function trimArea(col:int, x2:int, y2:int ):void 
  442.     {
  443.         var rx:int;
  444.         var nx:int = -1;
  445.         var ny:int = -1;
  446.         for (var y:int = 0; y < height; y++)
  447.         {
  448.             for (var x:int = 0; x < width / 2; x++)
  449.             {
  450.                 if (col == 1) rx = x;
  451.                 if (col > 1) rx = ((width / 2) - 1) - x;
  452.                 
  453.                 var c:int = getPixel(rx, y);
  454.                 
  455.                 if (c == col)
  456.                 {
  457.                     if (nx == -1) nx = x;
  458.                     if (ny == -1) ny = y;
  459.                     
  460.                     if (x >= nx + x2) setPixel(rx, y, SOLID_COL);
  461.                     if (y >= ny + y2) setPixel(rx, y, SOLID_COL);
  462.                 }
  463.             }
  464.         }
  465.     }
  466.     public function removeNoise(type:int):void 
  467.     {
  468.         var noise:int = 4;
  469.         var c:uint;
  470.         for (var i:int = 0; i < noise; i++)
  471.         {
  472.             //Remove isolated pixels
  473.             for (var y:int = 0; y < height; y++)
  474.             {
  475.                 for (var x:int = 0; x < width; x++)
  476.                 {
  477.                     c = getPixel(x, y);
  478.                     if (c != BLANK_COL) continue;
  479.                     
  480.                     c = getPixel(x - 1, y - 1)
  481.                     + getPixel(x, y - 1)
  482.                     + getPixel(x + 1, y - 1)
  483.                     + getPixel(x - 1, y)
  484.                     + getPixel(x + 1, y)
  485.                     + getPixel(x - 1, y + 1)
  486.                     + getPixel(x, y + 1)
  487.                     + getPixel(x + 1, y + 1);
  488.                     
  489.                     if (type == 0 && c >= 8 * SOLID_COL)
  490.                     {
  491.                         setPixel(x, y, SOLID_COL);
  492.                     }
  493.                     if (type == 1 && c >= 7 * SOLID_COL)
  494.                     {
  495.                         setPixel(x, y, SOLID_COL);                            
  496.                     }
  497.                     
  498.                     // Join up 'one pixel' horizontal and vertical gaps, (adds a little order to the image).
  499.                     if (getPixel(x, y + 1) == SOLID_COL
  500.                     && getPixel(x, y -1 ) == SOLID_COL
  501.                     && getPixel(x-1, y ) != SOLID_COL
  502.                     && getPixel(x + 1, y ) != SOLID_COL
  503.                     && Crand.rand() % 5 > 2)
  504.                     {
  505.                         setPixel(x, y, SOLID_COL);
  506.                     }
  507.                     if (getPixel(x-1, y ) == SOLID_COL
  508.                     && getPixel(x + 1, y ) == SOLID_COL
  509.                     && getPixel(x, y + 1) != SOLID_COL
  510.                     && getPixel(x, y -1 ) != SOLID_COL
  511.                     && Crand.rand() % 5 > 2)
  512.                     {
  513.                         setPixel(x, y, SOLID_COL);
  514.                     }
  515.                 }
  516.             }
  517.             
  518.             // Remove isolated pixels
  519.             for (y = 0; y < height; y++)
  520.             {
  521.                 for (x = 0; x < width; x++)
  522.                 {
  523.                     c = getPixel(x, y);
  524.                     if (c == 255)
  525.                     {
  526.                         // Add up surrounding pixels.
  527.                         c = getPixel(x, y - 1
  528.                         + getPixel(x - 1, y) 
  529.                         + getPixel(x - 1, y - 1)
  530.                         + getPixel(x + 1, y - 1)
  531.                         + getPixel(x + 1, y)
  532.                         + getPixel(x, y + 1)
  533.                         + getPixel(x - 1, y + 1)
  534.                         + getPixel(x + 1, y + 1);
  535.                         
  536.                         // No lit pixels around this one.
  537.                         if (c <= 0) setPixel(x, y, BLANK_COL);
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.     }
  543. }
  544. /*
  545. C rand()
  546. http://www001.upp.so-net.ne.jp/isaku/rand.html
  547. */
  548. class Crand
  549. {
  550.     //Visual C++ version
  551.     private static var x:int = 1;
  552.     public static function rand():int
  553.     {
  554.         x = x * 214013 + 2531011;
  555.         return (x>>16) & 32767;
  556.     }
  557.     public static function srand(s:int):void
  558.     {
  559.         x = s;
  560.     }
  561. }
noswf
  1. // forked from miyaoka's Retro Avatars
  2. /*
  3. =======================================
  4. Retro Avatars for Flash
  5. =======================================
  6. -Type avatar name to generate image.
  7. -press ENTER key to save current image as PNG.
  8.  
  9. // Retro Avatars
  10. // -------------
  11.  
  12. // By Richard Phipps
  13. // (Open source, but a credit if used would be nice!)
  14.  
  15. http://retroremakes.com/forum/index.php/topic,657.0.html
  16. より移植してみました
  17.  
  18. [Sample]
  19. http://www.indiegames.com/blog/2009/06/freeware_app_pick_retro_avatar.html
  20. http://www.flickr.com/photos/miyaoka/3592194889/
  21. */
  22. package 
  23. {
  24.     import flash.display.Sprite;
  25.     import flash.text.TextField;
  26.     import flash.text.TextFormat;
  27.     import flash.text.TextFormatAlign;
  28.     import flash.text.TextFieldType;
  29.     import flash.text.TextFieldAutoSize;
  30.     import flash.ui.Keyboard;
  31.     import flash.events.KeyboardEvent;
  32.     import flash.display.Bitmap;
  33.     import flash.display.BitmapData;
  34.     import flash.utils.ByteArray;
  35.     import com.adobe.images.PNGEncoder;
  36.     import flash.net.FileReference;
  37.     import flash.geom.Matrix;
  38.     
  39.     import flash.system.Capabilities;
  40.     import flash.system.IME;
  41.     [SWF(width="465", height="465", backgroundColor= 0x0, frameRate="60")]
  42.     public class RetroAvatars
  43.     extends Sprite 
  44.     {
  45.         private    var tfd:TextField = new TextField();
  46.         private var maxNameLength:uint = 9;
  47.         private var bmd:AvatarBMD = new AvatarBMD(1212false);
  48.         private var bmd32:BitmapData = new BitmapData(bmd.width, bmd.height, true, 0x0);
  49.         private var bmp:Bitmap = new Bitmap(bmd32);
  50.         
  51.         private static const EYES_COL:int = 0;
  52.         private static const NOSE_COL:int = 0;
  53.         private static const MOUSE_COL:int = 0;
  54.         
  55.         private var isFirst:Boolean = true;
  56.         public function RetroAvatars():void 
  57.         {
  58.             //bg
  59.             graphics.beginFill(0);
  60.             graphics.drawRect(00, stage.stageWidth, stage.stageHeight);
  61.             
  62.             //ime off
  63.             if (Capabilities.hasIME)
  64.             {
  65.                 try
  66.                 {
  67.                     IME.enabled = false;
  68.                 }
  69.                 catch (e:Error) {}
  70.             }
  71.             
  72.             //bmp
  73.             bmp.scaleX = bmp.scaleY = 24;
  74.             bmp.x = (stage.stageWidth - bmp.width) / 2;
  75.             bmp.y = 40;
  76.             addChild(bmp);            
  77.             
  78.             
  79.             //text
  80.             var tft:TextFormat = new TextFormat();
  81.             tft.align = TextFormatAlign.CENTER;
  82.             tft.bold = true;
  83.             tft.font = "Verdana";
  84.             tft.letterSpacing = 5;
  85.             tft.size = 48;
  86.             
  87.             tfd.defaultTextFormat = tft;
  88.             tfd.autoSize = TextFieldAutoSize.CENTER;
  89.             
  90.             tfd.x = 465/2;
  91.             tfd.y = 380;
  92.             tfd.text = "ENTER NAME";
  93.             tfd.textColor = 0xDDDDDD;
  94.             isFirst = true;
  95.             addChild(tfd);
  96.             
  97.             //event
  98.             stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
  99.         }
  100.         private function keyDownHandler(e:KeyboardEvent):void 
  101.         {
  102.             var cc:uint = e.charCode;
  103.             
  104.             // lower case keys, so make upper case.
  105.             if (97 <= cc && cc <= 122) cc -= 32;
  106.             
  107.             if (isFirst) tfd.text = ""; isFirst = false;
  108.             if (
  109.                 tfd.length < maxNameLength && 
  110.                 (
  111.                 cc == 32 // Space
  112.                 || (cc >= 65 && cc <= 90//letters
  113.                 || (cc >= 48 && cc <= 57//numbers 
  114.                 )
  115.             )
  116.             {
  117.                 tfd.text = tfd.text.concat(String.fromCharCode(cc));
  118.             }
  119.             else if ( cc == 8 && tfd.length > 0//Backspace
  120.             {
  121.                 tfd.text = tfd.text.substr(0, tfd.length -1);
  122.             }
  123.             else if (cc == 13 && 0 < tfd.text.length) // ENTER key
  124.             {
  125.                 //save PNG to local
  126.                 var mtx:Matrix = new Matrix();
  127.                 var sc:Number = 8;
  128.                 mtx.scale(sc, sc);
  129.                 var tempBmd:BitmapData = new BitmapData(bmd32.width * sc, bmd32.height * sc, true,0);
  130.                 tempBmd.draw(bmd32, mtx);
  131.                 var ba:ByteArray = PNGEncoder.encode(tempBmd);
  132.                 var fr:FileReference = new FileReference;
  133.                 fr.save(ba, tfd.text + ".png");
  134.             }
  135.             
  136.             
  137.             var nameLen:int = tfd.text.length;
  138.             if (nameLen == 0
  139.             {
  140.                 bmd32.fillRect(bmd32.rect, 0);
  141.                 return;
  142.             }
  143.             
  144.             // ------------
  145.             // make code from text and set to srand
  146.             Crand.srand(0);
  147.             var code:int = 0;
  148.             for (var g:int = 0; g < 32; g++)
  149.             {
  150.                 code += tfd.text.charCodeAt(g % nameLen) * Crand.rand() % 1024;
  151.             }
  152.             Crand.srand(code); // Seed random generator with code.
  153.             
  154.             //make avatar color.  Random (but not too dark) colour.
  155.             var col:int =
  156.             Crand.rand() % 192 + 64
  157.             | Crand.rand() % 192 + 64 << 8
  158.             | Crand.rand() % 192 + 64 << 16;
  159.             
  160.             tfd.textColor = col;
  161.             
  162.             // ------------
  163.             // build avatar img
  164.             bmd.build();
  165.             bmd.removeNoise(0);
  166.             bmd.mirror();            
  167.             bmd.enhanceFace();
  168.             
  169.             
  170.             //copy to 32bit bmd and set color
  171.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, ">=", 0xff << 24 | AvatarBMD.SOLID_COL, 0xFF <<24  | col);
  172.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.EYES_COL, EYES_COL);
  173.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.NOSE_COL, NOSE_COL);
  174.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.MOUSE_COL, MOUSE_COL);
  175.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.BLANK_COL, 0);
  176.         }
  177.     }    
  178. }
  179. import flash.display.BitmapData
  180. import flash.geom.Matrix;
  181. import flash.geom.Rectangle;
  182. class AvatarBMD
  183. extends BitmapData
  184. {
  185.     public static const EYES_COL:int = 1;
  186.     public static const NOSE_COL:int = 2;
  187.     public static const MOUSE_COL:int = 3;
  188.     public static const SOLID_COL:int = 0xFF;
  189.     public static const BLANK_COL:int = 0x0;
  190.     public function AvatarBMD(width:int, height:int, transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF):void 
  191.     {
  192.         //bmd24
  193.         super(width, height, false, fillColor);
  194.     }
  195.     public function build():void 
  196.     {
  197.         var c:int = 158;
  198.         for (var y:int = 0; y < height; y++)
  199.         {
  200.             for (var x:int = 0; x < width; x++)
  201.             {
  202.                 setPixel(x, y, (Crand.rand() % 356 > c) ? BLANK_COL : SOLID_COL);
  203.             }
  204.         }
  205.     }
  206.     public function enhanceFace():void 
  207.     {
  208.         var eyes:Boolean;
  209.         var nose:Boolean;
  210.         var mouth:Boolean;
  211.         var x:int;
  212.         var y:int;
  213.         var hx:int = width / 2 - 1// Half width of sprite variable.
  214.         // Detect eyes one pixel away from horizontal centre (look from just below the top edge to the middle of the vertical height).
  215.         for (y = 1; y < height / 2; y++)
  216.         {
  217.             if (getPixel(hx - 1, y) == BLANK_COL) // 0 - Empty, Pixel?
  218.             {
  219.                 floodFill(hx - 1, y, EYES_COL); // Mark area with reserved colour 1 (normal colours are 0 - empty & 255 - solid).
  220.                 if (checkForFilledEdge() == 0break// If this eye area doesn't touch the edges of the image, then stop searching.
  221.                 floodFill(hx - 1, y, BLANK_COL);     // It reaches the edge, so refill as 0 - empty and keep looking.
  222.             }
  223.             if (getPixel(hx - 2, y) == BLANK_COL) // Any potential eye areas one pixel further away?
  224.             {
  225.                 floodFill(hx - 2, y, EYES_COL); 
  226.                 if (checkForFilledEdge() == 0break;
  227.                 floodFill(hx - 2, y, BLANK_COL);                     
  228.             }
  229.         }
  230.         // Ok, we didn't find anything!
  231.         if ( y == height / 2
  232.         {
  233.             // Try to make eyes from any centre pixels (converting them to one pixel further away. i.e. xx -> x  x
  234.             for ( y = 1; y < height; y++)
  235.             {
  236.                 if (getPixel(hx - 1, y) == SOLID_COL && getPixel(hx, y) == BLANK_COL)
  237.                 {
  238.                     setPixel(hx - 1, y, BLANK_COL);
  239.                     setPixel(hx, y, SOLID_COL);
  240.                     setPixel(hx - 1, y + 1, BLANK_COL); // Make the eye 2 pixels (at least) high.  
  241.                     
  242.                     floodFill(hx - 1, y, EYES_COL); 
  243.                     if (checkForFilledEdge() == 0break;
  244.                     floodFill(hx - 1, y, BLANK_COL);                     
  245.                 }
  246.             }
  247.         }
  248.         
  249.         var ny:int = y + 1;
  250.         if (y < height) eyes = true// Ok, we did find eyes
  251.         
  252.         // Still NO eyes.
  253.         if (!eyes)
  254.         {
  255.             // Ok, create fake eyes!
  256.             y = 1 + Crand.rand() % (height / 2);
  257.             
  258.             setPixel(hx - 1, y, EYES_COL);
  259.             outlineArea(1); // Outline to protect area.
  260.             
  261.             eyes = true;
  262.             ny = y + 1;
  263.         }
  264.         
  265.         // Remove any joined up eyes (i.e xx instead of x  x)
  266.         for (y = 1; y < height; y++)
  267.         {
  268.             if (getPixel(hx, y) == EYES_COL)
  269.             {
  270.                 setPixel(hx, y, SOLID_COL);
  271.                 setPixel(hx - 1, y, EYES_COL);
  272.             }
  273.             else
  274.             {
  275.                 if (getPixel(hx - 2, y) == EYES_COL) setPixel(hx, y, SOLID_COL);
  276.                 if (getPixel(hx - 1, y) == EYES_COL) setPixel(hx, y, SOLID_COL);
  277.             }
  278.         }
  279.         mirror(); // Miror all eye work.
  280.         
  281.         if (eyes) outlineArea(EYES_COL); // Protect eyes with solid outline.
  282.         
  283.         trace(ny);
  284.         
  285.         // -------
  286.         // Detect nose
  287.         for (y = ny; y < height; y++)
  288.         {
  289.             if (getPixel(hx, y) == BLANK_COL)
  290.             {
  291.                 floodFill(hx, y, NOSE_COL); // Fill with area colour 2.
  292.                 if ( checkForFilledEdge() == 0break;
  293.                 floodFill(hx, y, BLANK_COL);
  294.             }
  295.         }
  296.         if ( y < 10) nose = true;
  297.         
  298.         // No nose?
  299.         if (!nose)
  300.         {
  301.             // Ok, we won't find a mouth either, but we need to make a nose/mouth one out of any open sections (regardless of touching the edge)
  302.             for (y = ny; y < height - 1; y++)
  303.             {
  304.                 if (getPixel(hx, y) == BLANK_COL)
  305.                 {
  306.                     setPixel(hx, y, NOSE_COL)
  307.                     nose = true;
  308.                     break;
  309.                 }
  310.             }
  311.             
  312.             // Try to find a nose/mouth one pixel away which we can join up. i.e. x  x -> xxxx
  313.             if (!nose)
  314.             {
  315.                 for (y = ny; y < height - 1; y++)
  316.                 {
  317.                     if (getPixel(hx - 1, y) == BLANK_COL)
  318.                     {
  319.                         setPixel(hx -1, y, NOSE_COL)
  320.                         setPixel(hx, y, NOSE_COL)
  321.                         nose = true;
  322.                         break;
  323.                     }
  324.                 }
  325.             
  326.                 // Ok, NOTHING, just create fake mouth/nose!
  327.                 if (!nose)
  328.                 {
  329.                     y = ny + 1 + Crand.rand() % (height / 3);
  330.                     if (y > height - 2) y = height - 2;
  331.                     setPixel(hx, y, NOSE_COL)
  332.                     nose = true;
  333.                     ny = y + 1;
  334.                 }
  335.             }
  336.         }
  337.         else
  338.         {
  339.             ny = y + 1;
  340.             
  341.             // --------
  342.             // Detect mouth    
  343.             for (y = ny; y < height; y++)
  344.             {
  345.                 if (getPixel(hx, y) == BLANK_COL)
  346.                 {
  347.                     floodFill(hx, y, MOUSE_COL);
  348.                     if (checkForFilledEdge() == 0break;
  349.                     floodFill(hx, y, BLANK_COL);
  350.                 }
  351.             }
  352.             if (y < height) mouth = true;
  353.             
  354.             if (!mouth) // Still no mouse, so look one pixel further away and then if found, join up.
  355.             {
  356.                 for (y = ny; y < height - 1; y++)
  357.                 {
  358.                     if (getPixel(hx - 1, y) == BLANK_COL)
  359.                     {
  360.                         setPixel(hx, y, BLANK_COL);
  361.                         floodFill(hx, y, MOUSE_COL);
  362.                         if (checkForFilledEdge() == 0break;
  363.                         floodFill(hx, y, BLANK_COL);
  364.                     }
  365.                 }
  366.             }
  367.             if (y < height) mouth = true;
  368.         }
  369.         // Outline mouth / nose to protect and stop surrounding gfx 'bleeding' in.
  370.         if (mouth) outlineArea(MOUSE_COL);
  371.         if (nose) outlineArea(NOSE_COL);
  372.         
  373.         if (eyes) trimArea(EYES_COL, 33); // Trim eyes to no more than 3 x 3
  374.         if (nose && mouth) trimArea(NOSE_COL, 33); // Trim nose to no more than 3 x 3. Mouth can be bigger..;
  375.         
  376.         mirror(); // Mirror to fix changes symmetrically.
  377.         
  378.         // Now search for any fill in any holes that doesn't leak to the edge of the sprite (passing over eyes, mouth and nose areas).
  379.         const tmpCol:int = 4;
  380.         for (y = 1; y < height -1; y++)
  381.         {
  382.             for (x = 1; x < hx - 1; x++)
  383.             {
  384.                 if (getPixel(x, y) == BLANK_COL)
  385.                 {
  386.                     floodFill(x, y, tmpCol)
  387.                     floodFill(x, y, checkForFilledEdge() == 0 ? SOLID_COL : BLANK_COL);
  388.                 }
  389.             }
  390.         }
  391.         mirror(); // Mirror finally (neccessary?)
  392.     }
  393.     public function mirror():void 
  394.     {
  395.         var mtx:Matrix = new Matrix();
  396.         mtx.scale(-11);
  397.         mtx.translate(width, 0);
  398.         draw(this, mtx , nullnullnew Rectangle(width/20, width, height));
  399.     }
  400.     public function checkForFilledEdge():int
  401.     {
  402.         var c:int;
  403.         for (var y:int = 0; y < height; y++)
  404.         {
  405.             c = getPixel(0, y);
  406.             if (c != BLANK_COL && c != SOLID_COL) return 1;
  407.             c = getPixel(width-1, y);
  408.             if (c != BLANK_COL && c != SOLID_COL) return 1;
  409.         }
  410.         for (var x:int = 0; x < width; x++)
  411.         {
  412.             c = getPixel(x, 0);
  413.             if (c != BLANK_COL && c != SOLID_COL) return 2;
  414.             c = getPixel(x, height -1);
  415.             if (c != BLANK_COL && c != SOLID_COL) return 2;            
  416.         }
  417.         return 0;
  418.     }
  419.     public function outlineArea(col:int):void 
  420.     {
  421.         for (var y:int = 0; y < height; y++)
  422.         {
  423.             for (var x:int = 0; x < width; x++)
  424.             {
  425.                 var c:int = getPixel(x, y);
  426.                 if (c == col) 
  427.                 {
  428.                 // diagonals are only outlined if blank (and not another reserved area).
  429.                 if (getPixel(x - 1, y - 1) == BLANK_COL) setPixel(x - 1, y - 1, SOLID_COL);
  430.                 if (getPixel(x , y - 1) != col) setPixel(x, y - 1, SOLID_COL);
  431.                 if (getPixel(x + 1, y - 1) == BLANK_COL) setPixel(x +1, y - 1, SOLID_COL);
  432.                 if (getPixel(x - 1, y) != col) setPixel(x - 1, y, SOLID_COL);
  433.                 if (getPixel(x + 1, y) != col) setPixel(x + 1, y, SOLID_COL);
  434.                 if (getPixel(x - 1, y + 1) == BLANK_COL) setPixel(x - 1, y + 1, SOLID_COL);
  435.                 if (getPixel(x, y + 1) != col) setPixel(x, y + 1, SOLID_COL);
  436.                 if (getPixel(x + 1, y + 1) == BLANK_COL) setPixel(x + 1, y + 1, SOLID_COL);
  437.                 }
  438.             }
  439.         }
  440.     }
  441.     public function trimArea(col:int, x2:int, y2:int ):void 
  442.     {
  443.         var rx:int;
  444.         var nx:int = -1;
  445.         var ny:int = -1;
  446.         for (var y:int = 0; y < height; y++)
  447.         {
  448.             for (var x:int = 0; x < width / 2; x++)
  449.             {
  450.                 if (col == 1) rx = x;
  451.                 if (col > 1) rx = ((width / 2) - 1) - x;
  452.                 
  453.                 var c:int = getPixel(rx, y);
  454.                 
  455.                 if (c == col)
  456.                 {
  457.                     if (nx == -1) nx = x;
  458.                     if (ny == -1) ny = y;
  459.                     
  460.                     if (x >= nx + x2) setPixel(rx, y, SOLID_COL);
  461.                     if (y >= ny + y2) setPixel(rx, y, SOLID_COL);
  462.                 }
  463.             }
  464.         }
  465.     }
  466.     public function removeNoise(type:int):void 
  467.     {
  468.         var noise:int = 4;
  469.         var c:uint;
  470.         for (var i:int = 0; i < noise; i++)
  471.         {
  472.             //Remove isolated pixels
  473.             for (var y:int = 0; y < height; y++)
  474.             {
  475.                 for (var x:int = 0; x < width; x++)
  476.                 {
  477.                     c = getPixel(x, y);
  478.                     if (c != BLANK_COL) continue;
  479.                     
  480.                     c = getPixel(x - 1, y - 1)
  481.                     + getPixel(x, y - 1)
  482.                     + getPixel(x + 1, y - 1)
  483.                     + getPixel(x - 1, y)
  484.                     + getPixel(x + 1, y)
  485.                     + getPixel(x - 1, y + 1)
  486.                     + getPixel(x, y + 1)
  487.                     + getPixel(x + 1, y + 1);
  488.                     
  489.                     if (type == 0 && c >= 8 * SOLID_COL)
  490.                     {
  491.                         setPixel(x, y, SOLID_COL);
  492.                     }
  493.                     if (type == 1 && c >= 7 * SOLID_COL)
  494.                     {
  495.                         setPixel(x, y, SOLID_COL);                            
  496.                     }
  497.                     
  498.                     // Join up 'one pixel' horizontal and vertical gaps, (adds a little order to the image).
  499.                     if (getPixel(x, y + 1) == SOLID_COL
  500.                     && getPixel(x, y -1 ) == SOLID_COL
  501.                     && getPixel(x-1, y ) != SOLID_COL
  502.                     && getPixel(x + 1, y ) != SOLID_COL
  503.                     && Crand.rand() % 5 > 2)
  504.                     {
  505.                         setPixel(x, y, SOLID_COL);
  506.                     }
  507.                     if (getPixel(x-1, y ) == SOLID_COL
  508.                     && getPixel(x + 1, y ) == SOLID_COL
  509.                     && getPixel(x, y + 1) != SOLID_COL
  510.                     && getPixel(x, y -1 ) != SOLID_COL
  511.                     && Crand.rand() % 5 > 2)
  512.                     {
  513.                         setPixel(x, y, SOLID_COL);
  514.                     }
  515.                 }
  516.             }
  517.             
  518.             // Remove isolated pixels
  519.             for (y = 0; y < height; y++)
  520.             {
  521.                 for (x = 0; x < width; x++)
  522.                 {
  523.                     c = getPixel(x, y);
  524.                     if (c == 255)
  525.                     {
  526.                         // Add up surrounding pixels.
  527.                         c = getPixel(x, y - 1
  528.                         + getPixel(x - 1, y) 
  529.                         + getPixel(x - 1, y - 1)
  530.                         + getPixel(x + 1, y - 1)
  531.                         + getPixel(x + 1, y)
  532.                         + getPixel(x, y + 1)
  533.                         + getPixel(x - 1, y + 1)
  534.                         + getPixel(x + 1, y + 1);
  535.                         
  536.                         // No lit pixels around this one.
  537.                         if (c <= 0) setPixel(x, y, BLANK_COL);
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.     }
  543. }
  544. /*
  545. C rand()
  546. http://www001.upp.so-net.ne.jp/isaku/rand.html
  547. */
  548. class Crand
  549. {
  550.     //Visual C++ version
  551.     private static var x:int = 1;
  552.     public static function rand():int
  553.     {
  554.         x = x * 214013 + 2531011;
  555.         return (x>>16) & 32767;
  556.     }
  557.     public static function srand(s:int):void
  558.     {
  559.         x = s;
  560.     }
  561. }
noswf
  1. // forked from miyaoka's Retro Avatars
  2. /*
  3. =======================================
  4. Retro Avatars for Flash
  5. =======================================
  6. -Type avatar name to generate image.
  7. -press ENTER key to save current image as PNG.
  8.  
  9. // Retro Avatars
  10. // -------------
  11.  
  12. // By Richard Phipps
  13. // (Open source, but a credit if used would be nice!)
  14.  
  15. http://retroremakes.com/forum/index.php/topic,657.0.html
  16. より移植してみました
  17.  
  18. [Sample]
  19. http://www.indiegames.com/blog/2009/06/freeware_app_pick_retro_avatar.html
  20. http://www.flickr.com/photos/miyaoka/3592194889/
  21. */
  22. package 
  23. {
  24.     import flash.display.Sprite;
  25.     import flash.text.TextField;
  26.     import flash.text.TextFormat;
  27.     import flash.text.TextFormatAlign;
  28.     import flash.text.TextFieldType;
  29.     import flash.text.TextFieldAutoSize;
  30.     import flash.ui.Keyboard;
  31.     import flash.events.KeyboardEvent;
  32.     import flash.display.Bitmap;
  33.     import flash.display.BitmapData;
  34.     import flash.utils.ByteArray;
  35.     import com.adobe.images.PNGEncoder;
  36.     import flash.net.FileReference;
  37.     import flash.geom.Matrix;
  38.     
  39.     import flash.system.Capabilities;
  40.     import flash.system.IME;
  41.     [SWF(width="465", height="465", backgroundColor= 0x0, frameRate="60")]
  42.     public class RetroAvatars
  43.     extends Sprite 
  44.     {
  45.         private    var tfd:TextField = new TextField();
  46.         private var maxNameLength:uint = 9;
  47.         private var bmd:AvatarBMD = new AvatarBMD(1212false);
  48.         private var bmd32:BitmapData = new BitmapData(bmd.width, bmd.height, true, 0x0);
  49.         private var bmp:Bitmap = new Bitmap(bmd32);
  50.         
  51.         private static const EYES_COL:int = 0;
  52.         private static const NOSE_COL:int = 0;
  53.         private static const MOUSE_COL:int = 0;
  54.         
  55.         private var isFirst:Boolean = true;
  56.         public function RetroAvatars():void 
  57.         {
  58.             //bg
  59.             graphics.beginFill(0);
  60.             graphics.drawRect(00, stage.stageWidth, stage.stageHeight);
  61.             
  62.             //ime off
  63.             if (Capabilities.hasIME)
  64.             {
  65.                 try
  66.                 {
  67.                     IME.enabled = false;
  68.                 }
  69.                 catch (e:Error) {}
  70.             }
  71.             
  72.             //bmp
  73.             bmp.scaleX = bmp.scaleY = 24;
  74.             bmp.x = (stage.stageWidth - bmp.width) / 2;
  75.             bmp.y = 40;
  76.             addChild(bmp);            
  77.             
  78.             
  79.             //text
  80.             var tft:TextFormat = new TextFormat();
  81.             tft.align = TextFormatAlign.CENTER;
  82.             tft.bold = true;
  83.             tft.font = "Verdana";
  84.             tft.letterSpacing = 5;
  85.             tft.size = 48;
  86.             
  87.             tfd.defaultTextFormat = tft;
  88.             tfd.autoSize = TextFieldAutoSize.CENTER;
  89.             
  90.             tfd.x = 465/2;
  91.             tfd.y = 380;
  92.             tfd.text = "ENTER NAME";
  93.             tfd.textColor = 0xDDDDDD;
  94.             isFirst = true;
  95.             addChild(tfd);
  96.             
  97.             //event
  98.             stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
  99.         }
  100.         private function keyDownHandler(e:KeyboardEvent):void 
  101.         {
  102.             var cc:uint = e.charCode;
  103.             
  104.             // lower case keys, so make upper case.
  105.             if (97 <= cc && cc <= 122) cc -= 32;
  106.             
  107.             if (isFirst) tfd.text = ""; isFirst = false;
  108.             if (
  109.                 tfd.length < maxNameLength && 
  110.                 (
  111.                 cc == 32 // Space
  112.                 || (cc >= 65 && cc <= 90//letters
  113.                 || (cc >= 48 && cc <= 57//numbers 
  114.                 )
  115.             )
  116.             {
  117.                 tfd.text = tfd.text.concat(String.fromCharCode(cc));
  118.             }
  119.             else if ( cc == 8 && tfd.length > 0//Backspace
  120.             {
  121.                 tfd.text = tfd.text.substr(0, tfd.length -1);
  122.             }
  123.             else if (cc == 13 && 0 < tfd.text.length) // ENTER key
  124.             {
  125.                 //save PNG to local
  126.                 var mtx:Matrix = new Matrix();
  127.                 var sc:Number = 8;
  128.                 mtx.scale(sc, sc);
  129.                 var tempBmd:BitmapData = new BitmapData(bmd32.width * sc, bmd32.height * sc, true,0);
  130.                 tempBmd.draw(bmd32, mtx);
  131.                 var ba:ByteArray = PNGEncoder.encode(tempBmd);
  132.                 var fr:FileReference = new FileReference;
  133.                 fr.save(ba, tfd.text + ".png");
  134.             }
  135.             
  136.             
  137.             var nameLen:int = tfd.text.length;
  138.             if (nameLen == 0
  139.             {
  140.                 bmd32.fillRect(bmd32.rect, 0);
  141.                 return;
  142.             }
  143.             
  144.             // ------------
  145.             // make code from text and set to srand
  146.             Crand.srand(0);
  147.             var code:int = 0;
  148.             for (var g:int = 0; g < 32; g++)
  149.             {
  150.                 code += tfd.text.charCodeAt(g % nameLen) * Crand.rand() % 1024;
  151.             }
  152.             Crand.srand(code); // Seed random generator with code.
  153.             
  154.             //make avatar color.  Random (but not too dark) colour.
  155.             var col:int =
  156.             Crand.rand() % 192 + 64
  157.             | Crand.rand() % 192 + 64 << 8
  158.             | Crand.rand() % 192 + 64 << 16;
  159.             
  160.             tfd.textColor = col;
  161.             
  162.             // ------------
  163.             // build avatar img
  164.             bmd.build();
  165.             bmd.removeNoise(0);
  166.             bmd.mirror();            
  167.             bmd.enhanceFace();
  168.             
  169.             
  170.             //copy to 32bit bmd and set color
  171.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, ">=", 0xff << 24 | AvatarBMD.SOLID_COL, 0xFF <<24  | col);
  172.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.EYES_COL, EYES_COL);
  173.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.NOSE_COL, NOSE_COL);
  174.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.MOUSE_COL, MOUSE_COL);
  175.             bmd32.threshold(bmd, bmd.rect, bmd.rect.topLeft, "==", 0xff << 24 | AvatarBMD.BLANK_COL, 0);
  176.         }
  177.     }    
  178. }
  179. import flash.display.BitmapData
  180. import flash.geom.Matrix;
  181. import flash.geom.Rectangle;
  182. class AvatarBMD
  183. extends BitmapData
  184. {
  185.     public static const EYES_COL:int = 1;
  186.     public static const NOSE_COL:int = 2;
  187.     public static const MOUSE_COL:int = 3;
  188.     public static const SOLID_COL:int = 0xFF;
  189.     public static const BLANK_COL:int = 0x0;
  190.     public function AvatarBMD(width:int, height:int, transparent:Boolean = true, fillColor:uint = 0xFFFFFFFF):void 
  191.     {
  192.         //bmd24
  193.         super(width, height, false, fillColor);
  194.     }
  195.     public function build():void 
  196.     {
  197.         var c:int = 158;
  198.         for (var y:int = 0; y < height; y++)
  199.         {
  200.             for (var x:int = 0; x < width; x++)
  201.             {
  202.                 setPixel(x, y, (Crand.rand() % 356 > c) ? BLANK_COL : SOLID_COL);
  203.             }
  204.         }
  205.     }
  206.     public function enhanceFace():void 
  207.     {
  208.         var eyes:Boolean;
  209.         var nose:Boolean;
  210.         var mouth:Boolean;
  211.         var x:int;
  212.         var y:int;
  213.         var hx:int = width / 2 - 1// Half width of sprite variable.
  214.         // Detect eyes one pixel away from horizontal centre (look from just below the top edge to the middle of the vertical height).
  215.         for (y = 1; y < height / 2; y++)
  216.         {
  217.             if (getPixel(hx - 1, y) == BLANK_COL) // 0 - Empty, Pixel?
  218.             {
  219.                 floodFill(hx - 1, y, EYES_COL); // Mark area with reserved colour 1 (normal colours are 0 - empty & 255 - solid).
  220.                 if (checkForFilledEdge() == 0break// If this eye area doesn't touch the edges of the image, then stop searching.
  221.                 floodFill(hx - 1, y, BLANK_COL);     // It reaches the edge, so refill as 0 - empty and keep looking.
  222.             }
  223.             if (getPixel(hx - 2, y) == BLANK_COL) // Any potential eye areas one pixel further away?
  224.             {
  225.                 floodFill(hx - 2, y, EYES_COL); 
  226.                 if (checkForFilledEdge() == 0break;
  227.                 floodFill(hx - 2, y, BLANK_COL);                     
  228.             }
  229.         }
  230.         // Ok, we didn't find anything!
  231.         if ( y == height / 2
  232.         {
  233.             // Try to make eyes from any centre pixels (converting them to one pixel further away. i.e. xx -> x  x
  234.             for ( y = 1; y < height; y++)
  235.             {
  236.                 if (getPixel(hx - 1, y) == SOLID_COL && getPixel(hx, y) == BLANK_COL)
  237.                 {
  238.                     setPixel(hx - 1, y, BLANK_COL);
  239.                     setPixel(hx, y, SOLID_COL);
  240.                     setPixel(hx - 1, y + 1, BLANK_COL); // Make the eye 2 pixels (at least) high.  
  241.                     
  242.                     floodFill(hx - 1, y, EYES_COL); 
  243.                     if (checkForFilledEdge() == 0break;
  244.                     floodFill(hx - 1, y, BLANK_COL);                     
  245.                 }
  246.             }
  247.         }
  248.         
  249.         var ny:int = y + 1;
  250.         if (y < height) eyes = true// Ok, we did find eyes
  251.         
  252.         // Still NO eyes.
  253.         if (!eyes)
  254.         {
  255.             // Ok, create fake eyes!
  256.             y = 1 + Crand.rand() % (height / 2);
  257.             
  258.             setPixel(hx - 1, y, EYES_COL);
  259.             outlineArea(1); // Outline to protect area.
  260.             
  261.             eyes = true;
  262.             ny = y + 1;
  263.         }
  264.         
  265.         // Remove any joined up eyes (i.e xx instead of x  x)
  266.         for (y = 1; y < height; y++)
  267.         {
  268.             if (getPixel(hx, y) == EYES_COL)
  269.             {
  270.                 setPixel(hx, y, SOLID_COL);
  271.                 setPixel(hx - 1, y, EYES_COL);
  272.             }
  273.             else
  274.             {
  275.                 if (getPixel(hx - 2, y) == EYES_COL) setPixel(hx, y, SOLID_COL);
  276.                 if (getPixel(hx - 1, y) == EYES_COL) setPixel(hx, y, SOLID_COL);
  277.             }
  278.         }
  279.         mirror(); // Miror all eye work.
  280.         
  281.         if (eyes) outlineArea(EYES_COL); // Protect eyes with solid outline.
  282.         
  283.         trace(ny);
  284.         
  285.         // -------
  286.         // Detect nose
  287.         for (y = ny; y < height; y++)
  288.         {
  289.             if (getPixel(hx, y) == BLANK_COL)
  290.             {
  291.                 floodFill(hx, y, NOSE_COL); // Fill with area colour 2.
  292.                 if ( checkForFilledEdge() == 0break;
  293.                 floodFill(hx, y, BLANK_COL);
  294.             }
  295.         }
  296.         if ( y < 10) nose = true;
  297.         
  298.         // No nose?
  299.         if (!nose)
  300.         {
  301.             // Ok, we won't find a mouth either, but we need to make a nose/mouth one out of any open sections (regardless of touching the edge)
  302.             for (y = ny; y < height - 1; y++)
  303.             {
  304.                 if (getPixel(hx, y) == BLANK_COL)
  305.                 {
  306.                     setPixel(hx, y, NOSE_COL)
  307.                     nose = true;
  308.                     break;
  309.                 }
  310.             }
  311.             
  312.             // Try to find a nose/mouth one pixel away which we can join up. i.e. x  x -> xxxx
  313.             if (!nose)
  314.             {
  315.                 for (y = ny; y < height - 1; y++)
  316.                 {
  317.                     if (getPixel(hx - 1, y) == BLANK_COL)
  318.                     {
  319.                         setPixel(hx -1, y, NOSE_COL)
  320.                         setPixel(hx, y, NOSE_COL)
  321.                         nose = true;
  322.                         break;
  323.                     }
  324.                 }
  325.             
  326.                 // Ok, NOTHING, just create fake mouth/nose!
  327.                 if (!nose)
  328.                 {
  329.                     y = ny + 1 + Crand.rand() % (height / 3);
  330.                     if (y > height - 2) y = height - 2;
  331.                     setPixel(hx, y, NOSE_COL)
  332.                     nose = true;
  333.                     ny = y + 1;
  334.                 }
  335.             }
  336.         }
  337.         else
  338.         {
  339.             ny = y + 1;
  340.             
  341.             // --------
  342.             // Detect mouth    
  343.             for (y = ny; y < height; y++)
  344.             {
  345.                 if (getPixel(hx, y) == BLANK_COL)
  346.                 {
  347.                     floodFill(hx, y, MOUSE_COL);
  348.                     if (checkForFilledEdge() == 0break;
  349.                     floodFill(hx, y, BLANK_COL);
  350.                 }
  351.             }
  352.             if (y < height) mouth = true;
  353.             
  354.             if (!mouth) // Still no mouse, so look one pixel further away and then if found, join up.
  355.             {
  356.                 for (y = ny; y < height - 1; y++)
  357.                 {
  358.                     if (getPixel(hx - 1, y) == BLANK_COL)
  359.                     {
  360.                         setPixel(hx, y, BLANK_COL);
  361.                         floodFill(hx, y, MOUSE_COL);
  362.                         if (checkForFilledEdge() == 0break;
  363.                         floodFill(hx, y, BLANK_COL);
  364.                     }
  365.                 }
  366.             }
  367.             if (y < height) mouth = true;
  368.         }
  369.         // Outline mouth / nose to protect and stop surrounding gfx 'bleeding' in.
  370.         if (mouth) outlineArea(MOUSE_COL);
  371.         if (nose) outlineArea(NOSE_COL);
  372.         
  373.         if (eyes) trimArea(EYES_COL, 33); // Trim eyes to no more than 3 x 3
  374.         if (nose && mouth) trimArea(NOSE_COL, 33); // Trim nose to no more than 3 x 3. Mouth can be bigger..;
  375.         
  376.         mirror(); // Mirror to fix changes symmetrically.
  377.         
  378.         // Now search for any fill in any holes that doesn't leak to the edge of the sprite (passing over eyes, mouth and nose areas).
  379.         const tmpCol:int = 4;
  380.         for (y = 1; y < height -1; y++)
  381.         {
  382.             for (x = 1; x < hx - 1; x++)
  383.             {
  384.                 if (getPixel(x, y) == BLANK_COL)
  385.                 {
  386.                     floodFill(x, y, tmpCol)
  387.                     floodFill(x, y, checkForFilledEdge() == 0 ? SOLID_COL : BLANK_COL);
  388.                 }
  389.             }
  390.         }
  391.         mirror(); // Mirror finally (neccessary?)
  392.     }
  393.     public function mirror():void 
  394.     {
  395.         var mtx:Matrix = new Matrix();
  396.         mtx.scale(-11);
  397.         mtx.translate(width, 0);
  398.         draw(this, mtx , nullnullnew Rectangle(width/20, width, height));
  399.     }
  400.     public function checkForFilledEdge():int
  401.     {
  402.         var c:int;
  403.         for (var y:int = 0; y < height; y++)
  404.         {
  405.             c = getPixel(0, y);
  406.             if (c != BLANK_COL && c != SOLID_COL) return 1;
  407.             c = getPixel(width-1, y);
  408.             if (c != BLANK_COL && c != SOLID_COL) return 1;
  409.         }
  410.         for (var x:int = 0; x < width; x++)
  411.         {
  412.             c = getPixel(x, 0);
  413.             if (c != BLANK_COL && c != SOLID_COL) return 2;
  414.             c = getPixel(x, height -1);
  415.             if (c != BLANK_COL && c != SOLID_COL) return 2;            
  416.         }
  417.         return 0;
  418.     }
  419.     public function outlineArea(col:int):void 
  420.     {
  421.         for (var y:int = 0; y < height; y++)
  422.         {
  423.             for (var x:int = 0; x < width; x++)
  424.             {
  425.                 var c:int = getPixel(x, y);
  426.                 if (c == col) 
  427.                 {
  428.                 // diagonals are only outlined if blank (and not another reserved area).
  429.                 if (getPixel(x - 1, y - 1) == BLANK_COL) setPixel(x - 1, y - 1, SOLID_COL);
  430.                 if (getPixel(x , y - 1) != col) setPixel(x, y - 1, SOLID_COL);
  431.                 if (getPixel(x + 1, y - 1) == BLANK_COL) setPixel(x +1, y - 1, SOLID_COL);
  432.                 if (getPixel(x - 1, y) != col) setPixel(x - 1, y, SOLID_COL);
  433.                 if (getPixel(x + 1, y) != col) setPixel(x + 1, y, SOLID_COL);
  434.                 if (getPixel(x - 1, y + 1) == BLANK_COL) setPixel(x - 1, y + 1, SOLID_COL);
  435.                 if (getPixel(x, y + 1) != col) setPixel(x, y + 1, SOLID_COL);
  436.                 if (getPixel(x + 1, y + 1) == BLANK_COL) setPixel(x + 1, y + 1, SOLID_COL);
  437.                 }
  438.             }
  439.         }
  440.     }
  441.     public function trimArea(col:int, x2:int, y2:int ):void 
  442.     {
  443.         var rx:int;
  444.         var nx:int = -1;
  445.         var ny:int = -1;
  446.         for (var y:int = 0; y < height; y++)
  447.         {
  448.             for (var x:int = 0; x < width / 2; x++)
  449.             {
  450.                 if (col == 1) rx = x;
  451.                 if (col > 1) rx = ((width / 2) - 1) - x;
  452.                 
  453.                 var c:int = getPixel(rx, y);
  454.                 
  455.                 if (c == col)
  456.                 {
  457.                     if (nx == -1) nx = x;
  458.                     if (ny == -1) ny = y;
  459.                     
  460.                     if (x >= nx + x2) setPixel(rx, y, SOLID_COL);
  461.                     if (y >= ny + y2) setPixel(rx, y, SOLID_COL);
  462.                 }
  463.             }
  464.         }
  465.     }
  466.     public function removeNoise(type:int):void 
  467.     {
  468.         var noise:int = 4;
  469.         var c:uint;
  470.         for (var i:int = 0; i < noise; i++)
  471.         {
  472.             //Remove isolated pixels
  473.             for (var y:int = 0; y < height; y++)
  474.             {
  475.                 for (var x:int = 0; x < width; x++)
  476.                 {
  477.                     c = getPixel(x, y);
  478.                     if (c != BLANK_COL) continue;
  479.                     
  480.                     c = getPixel(x - 1, y - 1)
  481.                     + getPixel(x, y - 1)
  482.                     + getPixel(x + 1, y - 1)
  483.                     + getPixel(x - 1, y)
  484.                     + getPixel(x + 1, y)
  485.                     + getPixel(x - 1, y + 1)
  486.                     + getPixel(x, y + 1)
  487.                     + getPixel(x + 1, y + 1);
  488.                     
  489.                     if (type == 0 && c >= 8 * SOLID_COL)
  490.                     {
  491.                         setPixel(x, y, SOLID_COL);
  492.                     }
  493.                     if (type == 1 && c >= 7 * SOLID_COL)
  494.                     {
  495.                         setPixel(x, y, SOLID_COL);                            
  496.                     }
  497.                     
  498.                     // Join up 'one pixel' horizontal and vertical gaps, (adds a little order to the image).
  499.                     if (getPixel(x, y + 1) == SOLID_COL
  500.                     && getPixel(x, y -1 ) == SOLID_COL
  501.                     && getPixel(x-1, y ) != SOLID_COL
  502.                     && getPixel(x + 1, y ) != SOLID_COL
  503.                     && Crand.rand() % 5 > 2)
  504.                     {
  505.                         setPixel(x, y, SOLID_COL);
  506.                     }
  507.                     if (getPixel(x-1, y ) == SOLID_COL
  508.                     && getPixel(x + 1, y ) == SOLID_COL
  509.                     && getPixel(x, y + 1) != SOLID_COL
  510.                     && getPixel(x, y -1 ) != SOLID_COL
  511.                     && Crand.rand() % 5 > 2)
  512.                     {
  513.                         setPixel(x, y, SOLID_COL);
  514.                     }
  515.                 }
  516.             }
  517.             
  518.             // Remove isolated pixels
  519.             for (y = 0; y < height; y++)
  520.             {
  521.                 for (x = 0; x < width; x++)
  522.                 {
  523.                     c = getPixel(x, y);
  524.                     if (c == 255)
  525.                     {
  526.                         // Add up surrounding pixels.
  527.                         c = getPixel(x, y - 1
  528.                         + getPixel(x - 1, y) 
  529.                         + getPixel(x - 1, y - 1)
  530.                         + getPixel(x + 1, y - 1)
  531.                         + getPixel(x + 1, y)
  532.                         + getPixel(x, y + 1)
  533.                         + getPixel(x - 1, y + 1)
  534.                         + getPixel(x + 1, y + 1);
  535.                         
  536.                         // No lit pixels around this one.
  537.                         if (c <= 0) setPixel(x, y, BLANK_COL);
  538.                     }
  539.                 }
  540.             }
  541.         }
  542.     }
  543. }
  544. /*
  545. C rand()
  546. http://www001.upp.so-net.ne.jp/isaku/rand.html
  547. */
  548. class Crand
  549. {
  550.     //Visual C++ version
  551.     private static var x:int = 1;
  552.     public static function rand():int
  553.     {
  554.         x = x * 214013 + 2531011;
  555.         return (x>>16) & 32767;
  556.     }
  557.     public static function srand(s:int):void
  558.     {
  559.         x = s;
  560.     }
  561. }
noswf
Get Adobe Flash Player