package { import aether.utils.Adjustments; import aether.utils.ImageUtil; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.BlendMode; import flash.display.Sprite; import flash.filters.BlurFilter; import flash.filters.DisplacementMapFilter; import flash.filters.DisplacementMapFilterMode; import flash.geom.ColorTransform; import flash.geom.Matrix; import flash.geom.Point; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; [SWF(width=550, height=150, backgroundColor=0xCCCCCC)] /** * Demonstrates different techniques for distressing an image or, in this case in particular, text, * by using noise, displacement maps, adjustments and blurs. */ public class graphic_flex_image_effects_09_Flex_DistressedText extends Sprite { /** * Constructor. Creates textfield, draws it into bitmap data and distresses it. */ public function graphic_flex_image_effects_09_Flex_DistressedText() { var field:TextField = createField(); var bitmapData:BitmapData = ImageUtil.getBitmapData(field); distressImage(bitmapData, 5); // rotate the image to apply same distortion in opposite directions rotateImage(bitmapData); distressImage(bitmapData, 5); // rotate image back right side up rotateImage(bitmapData); // add distorted image below the textfield var bitmap:Bitmap = new Bitmap(bitmapData); bitmap.x = field.x; bitmap.y = stage.stageHeight - bitmap.height; addChild(bitmap); } /** * Creates a textfield. * * @return The textfield created. */ private function createField():TextField { var field:TextField = new TextField(); field.selectable = false; // make sure you have Impact installed field.defaultTextFormat = new TextFormat("Impact", 60); field.autoSize = TextFieldAutoSize.LEFT; field.text = "I'M DISTRESSED!"; field.x = (stage.stageWidth - field.width)/2; addChild(field); return field; } /** * Draws a copy of the image, rotated 180 degrees, into the original image. * * @param bitmapData The image to rotate. */ private function rotateImage(bitmapData:BitmapData):void { var matrix:Matrix = new Matrix(); // PI radians == 180 degress matrix.rotate(Math.PI); matrix.translate(bitmapData.width, bitmapData.height); var rotatedBitmap:BitmapData = new BitmapData(bitmapData.width, bitmapData.height, true, 0x00000000); rotatedBitmap.draw(bitmapData, matrix); // copy rotated data into original bitmap data bitmapData.copyPixels(rotatedBitmap, bitmapData.rect, new Point()); } /** * Applies distress effects to the specified image at the specified amount. * * @param bitmapData The image to distress * @param amount The amount to distress the image. This should be somethig between 0 and 20, ideally. */ private function distressImage(bitmapData:BitmapData, amount:Number):void { // Perlin noise that will be used for displacement var perlin:BitmapData = new BitmapData(bitmapData.width, bitmapData.height); perlin.perlinNoise( 10, 10, 5, Math.random(), true, true, BitmapDataChannel.RED ); // create more light than dark in the noise Adjustments.setLevels(perlin, 0, 50, 100); var displaceX:Number = amount; // displacing more vertically works better for maintaining text legibility var displaceY:Number = amount*3; ImageUtil.applyFilter( bitmapData, new DisplacementMapFilter( perlin, new Point(), BitmapDataChannel.RED, BitmapDataChannel.RED, displaceX, displaceY, DisplacementMapFilterMode.WRAP ) ); // this noise will be used to alter opacity of distressed image with transparent speckles var noise:BitmapData = new BitmapData(bitmapData.width, bitmapData.height); noise.noise(Math.random(), 0, 255, BitmapDataChannel.RED, true); // apply blur to noise ImageUtil.applyFilter(noise, new BlurFilter(displaceX, displaceY)); // really reduce contrast of noise Adjustments.setLevels(noise, 105, 107, 109); // draw a grayscale image of the distressed image's alpha channel var alpha:BitmapData = ImageUtil.getChannelData( bitmapData, BitmapDataChannel.ALPHA ); // apply the noise to the grayscale alpha channel image using multiply alpha.draw( noise, null, new ColorTransform( 1, 1, 1, Math.min(1, amount*.2) ), BlendMode.MULTIPLY ); // copy the altered grayscale image into the alpha channel of the distressed image bitmapData.copyChannel( alpha, alpha.rect, new Point(), BitmapDataChannel.RED, BitmapDataChannel.ALPHA ); } } }