A Trick of Using PNGs to Mask Images

Problem Summery: I want an approach to mask images with given PNGs. However, the inner of some of the PNG images are transparent. After I set the PNG as a mask, the area of the masked image below the inner of the PNG is invisible.

Search-256x256 Demo | DownloadDownload Full Project

clip_image002

PNG

clip_image004

Current effect

The problem is how to approach to the effect like this:

clip_image006

Target effect

Solution Summery: The method floodFill of class BitmapData provides me a way to achieve my goal. For a mask image, if the pixel is transparent or its color is #FFFFFF, the pixel of the masked image below the pixel are invisible; otherwise, they are visible. floodFill will perform a flood fill operation on an image starting at an (x, y) coordinate and filling with a certain color, it is similar to the paint bucket tool in various paint programs. Therefore, if the center pixel of PNG is transparent, I do a flood fill operation starting at the center coordinate with the color #FF000000. Now, the pixels of the masked image below the pixels of the inner of the shape will be visible.

Following is the source of ArbitraryPNGMask.mxml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application 
  3.     xmlns:mx="http://www.adobe.com/2006/mxml" 
  4.     layout="horizontal"
  5.     backgroundColor="#FFFFFF"
  6.     paddingTop="0"
  7.     paddingRight="0"
  8.     paddingLeft="0"
  9.     paddingBottom="0" viewSourceURL="srcview/index.html">
  10.    
  11.     <mx:Script>
  12.         <![CDATA[
  13.             import mx.core.UIComponent;
  14.             import mx.events.FlexEvent;
  15.             import mx.controls.Image;
  16.             import mx.controls.listClasses.IListItemRenderer;
  17.            
  18.             private function initMask():void
  19.             {
  20.                 var bitmapData:BitmapData = new BitmapData(picture.width,picture.height);
  21.                 bitmapData.floodFill(bitmapData.width/2,bitmapData.height/2,0xFF000000);               
  22.                 maskImage.source = new Bitmap(bitmapData);
  23.             }           
  24.            
  25.             private function getMaskImage(data:Object):Bitmap
  26.             {
  27.                 var itemRenderer:IListItemRenderer = maskList.itemToItemRenderer(data);
  28.                 var bitmap:Bitmap;
  29.                 var bitmapData:BitmapData;           
  30.                
  31.                 bitmapData = Bitmap(Image(itemRenderer).content).bitmapData.clone();               
  32.  
  33.                 var pixel:uint = bitmapData.getPixel32(int(bitmapData.width/2),int(bitmapData.height/2));                       
  34.                 // extract the alpha value from the given ARGB value.
  35.                 var alpha:uint = pixel >> 24;
  36.                
  37.                 // if the center pixel is transparent, suppose the mask is a png
  38.                 // image consist of a closed shape, this will fill the inner of
  39.                 // the closed shape with the RGB color 0x000000 inorder to make
  40.                 // the image area below the inner visible.
  41.                 if(alpha == 0x00)                                    
  42.                     bitmapData.floodFill(bitmapData.width/2,bitmapData.height/2,0xFF000000);                           
  43.                
  44.                 bitmap = new Bitmap(bitmapData);
  45.                 return bitmap;   
  46.             }
  47.            
  48.             private function startDragging():void
  49.             {
  50.                 oldMouseX = maskImage.mouseX;
  51.                 oldMouseY = maskImage.mouseY;
  52.                 maskImage.addEventListener(Event.ENTER_FRAME,doDrag);
  53.             }
  54.            
  55.             private function endDragging():void
  56.             {
  57.                 maskImage.removeEventListener(Event.ENTER_FRAME,doDrag);
  58.             }
  59.            
  60.             private var oldMouseX:Number = 0;
  61.             private var oldMouseY:Number = 0;
  62.            
  63.             private function doDrag(event:Event):void
  64.             {                               
  65.                 var offsetX:Number = maskImage.mouseX - oldMouseX;
  66.                 var offsetY:Number = maskImage.mouseY - oldMouseY;
  67.                 maskImage.x += offsetX;
  68.                 maskImage.y += offsetY;
  69.             }
  70.         ]]>
  71.     </mx:Script>
  72.    
  73.     <mx:XML id="masksDataSource" 
  74.         source="assets/masks.xml"/>
  75.        
  76.     <mx:List id="maskList"
  77.         dataProvider="{masksDataSource.mask}" 
  78.         height="100%">
  79.         <mx:itemRenderer>
  80.             <mx:Component>
  81.                 <mx:Image 
  82.                     source="{data.@path}"
  83.                     height="80"/>
  84.             </mx:Component>
  85.         </mx:itemRenderer>           
  86.     </mx:List>
  87.    
  88.     <mx:Canvas
  89.         width="100%"
  90.         height="100%">
  91.         <mx:Image id="picture"
  92.             source="assets/picture.jpg"
  93.             mask="{maskImage}"
  94.             cacheAsBitmap="true"
  95.             creationComplete="initMask()"
  96.             />
  97.            
  98.         <mx:Image id="maskImage"
  99.             source="{getMaskImage(maskList.selectedItem)}"
  100.             cacheAsBitmap="true"
  101.             buttonMode="true"
  102.             mouseChildren="false"
  103.             mouseDown="startDragging();"
  104.             mouseUp="endDragging();"/>
  105.     </mx:Canvas>
  106. </mx:Application>
Share and Enjoy:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • Reddit
  • Technorati
  • StumbleUpon
  • Twitter
RSS Enjoy this Post? Subscribe to Ntt.cc

RSS Feed   RSS Feed     Email Feed  Email Feed Follow us Follow us
You can leave a response, or trackback from your own site.

3 Responses to “A Trick of Using PNGs to Mask Images”

  1. [...] Summery: Continue the sample posted before A Trick of Using PNGs to Mask Images, When you browse a web page rendered in HTML with fire fox, IE, etc., click the right button of [...]

  2. raja says:

    How can we rotate and resize mask dynamically like in editors?

  3. ilias says:

    I have an image and a frame ( .png ) , how i can set the frame as a frame of my image? Please answer me , urgent!!!

Leave a Reply