package { import flash.display.*; import flash.filters.*; import flash.geom.*; import flash.events.*; import flash.utils.getTimer; [SWF(width='1000',height='500',backgroundColor='0xffffff',frameRate='255')] public class ImageResizing extends Sprite { [Embed(source='/assets/cop.jpg')] private static const PICTURE: Class; private static const origin: Point = new Point; private static const colorMatrix: ColorMatrixFilter = new ColorMatrixFilter( new Array( 0,0,0, 0, 0, 0, 0, 0, 0, 0, .2125, .7154, .0721, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) ); /* private static const convolution: ConvolutionFilter = new ConvolutionFilter( 3, 3, new Array( 0, -1, 0, -1, 4, -1, 0, -1, 0 ) ); private static const convolutionH: ConvolutionFilter = new ConvolutionFilter( 1, 3, new Array( -2, 4, -2 ) ); private static const convolutionV: ConvolutionFilter = new ConvolutionFilter( 3, 1, new Array( -2, 4, -2 ) ); */ private static const blur: BlurFilter = new BlurFilter( 4,4,1); private var screen: BitmapData; private var bitmapData: BitmapData; private var displaceMap:BitmapData; private var energyMap: BitmapData; private var grayscaleMap: BitmapData; private var blurMap: BitmapData; private var mode: Boolean = false; private var fillRect:Rectangle; private var filterRect:Rectangle; private var dmf:DisplacementMapFilter; private static const m1:Matrix = new Matrix(1,0,0,1,-2,-2); private static const m2:Matrix = new Matrix(1,0,0,1,2,2); public function ImageResizing() { stage.scaleMode = StageScaleMode.NO_SCALE; bitmapData = Bitmap( new PICTURE ).bitmapData; filterRect = bitmapData.rect.clone(); screen = bitmapData.clone(); energyMap = new BitmapData(bitmapData.width,bitmapData.height,false,0); grayscaleMap = bitmapData.clone(); blurMap = bitmapData.clone(); grayscaleMap.applyFilter( bitmapData, filterRect, origin, colorMatrix ); blurMap.applyFilter( grayscaleMap,filterRect,origin,blur); energyMap.draw(blurMap,m1); energyMap.draw(blurMap,m2,null,"difference"); //energyMap.applyFilter( grayscaleMap, filterRect, origin, convolution); displaceMap = new BitmapData( bitmapData.width+1, bitmapData.height+1, false,0x808080); fillRect = new Rectangle(); dmf = new DisplacementMapFilter(); dmf.mapPoint = origin; dmf.componentY = dmf.componentX = 4; dmf.mode = DisplacementMapFilterMode.COLOR dmf.alpha = 0; dmf.mapBitmap = displaceMap; addChild( new Bitmap( screen ) ); /* var bm:Bitmap = new Bitmap( displaceMap ); bm.x = 500; addChild( bm ); */ stage.addEventListener( KeyboardEvent.KEY_UP, onKeyUp ); stage.addEventListener( MouseEvent.CLICK, onClick ); stage.addEventListener( Event.ENTER_FRAME, onEnterFrame ); } private function onClick( event: MouseEvent ): void { bitmapData = Bitmap( new PICTURE ).bitmapData; filterRect = bitmapData.rect.clone(); } private function onKeyUp( event: KeyboardEvent ): void { mode = !mode; } private function onEnterFrame( event: Event ): void { ( mode ) ? stepX() : stepY(); screen.copyPixels( bitmapData, bitmapData.rect,origin); } private function stepX(): void { if ( filterRect.width == 1 ) return; //Die grayscale map braucht man nur am anfang zu bauen wenn man sie //mitverzerrt - die Frage ist nur, ob DisplacementMap schneller ist als colormatrix //energyMap.applyFilter( bitmapData, filterRect, origin, colorMatrix ); //Das ist zwar nicht 100% korrekt, aber wenn man die energy map mitverzerrt //und nicht neuberechnet sieht as gar nicht so schmlimm aus. Vielleicht //kann man das neuberechnen nur alle 20 oder 40 steps machen. //energyMap.applyFilter( grayscaleMap, filterRect, origin, convolutionH ); blurMap.applyFilter( grayscaleMap,filterRect,origin,blur); energyMap.draw(grayscaleMap,m1); energyMap.draw(grayscaleMap,m2,null,"difference"); var n: int = filterRect.width; var seamsV: Array = new Array(); var seam: Seam; var bestEnergy:Number = Number.MAX_VALUE; for ( var x: int = 0; x < n; ++x ) { seam = new Seam; seam.direction = SeamDirection.V; seam.start = x; seam.bake( energyMap, filterRect, bestEnergy ); if ( seam.energy < bestEnergy ){ bestEnergy = seam.energy; seamsV.push( seam ); } } seamsV.sortOn( 'energy', Array.NUMERIC ); var p: SeamPoint = Seam( seamsV[ 0 ] ).points; var w: int = filterRect.width; var h: int = filterRect.height; x = p.x; displaceMap.fillRect(displaceMap.rect,0x808080); for (var y:int = 0;yx) x = p.x; p = p.next; } if ( p.x > x ) x = p.x; while ( yy) y = p.y; p = p.next; } if ( p.y>y) y = p.y; while ( x 0 ? energyMap.getPixel( o - 1, p ) : 0x100 | energy; e1 = energyMap.getPixel( o, p ); e2 = o < endO ? energyMap.getPixel( o + 1, p ) : 0x100 | energy; d0 = energy ^ e0; d1 = energy ^ e1; d2 = energy ^ e2; if ( d0 < d1 ) { if ( d0 < d2 ) { o--; energy = e0; if ( o < 0 ) o = 0; min = d0; } else { o++; energy = e2; if ( o > endO ) o = endO ; min = d2; } } else { if ( d1 <= d2 ) { energy = e1; min = d1; } else { o++; energy = e2; if ( o > endO ) o = endO; min = d2; } } point.x = o; point.y = p; } else { e0 = o > 0 ? energyMap.getPixel( p, o - 1) : 0x100 | energy; e1 = energyMap.getPixel( p, o ); e2 = o < endO ? energyMap.getPixel( p, o + 1) : 0x100 | energy; d0 = energy ^ e0; d1 = energy ^ e1; d2 = energy ^ e2; if ( d0 < d1 ) { if ( d0 < d2 ) { o--; energy = e0; if ( o < 0 ) o = 0; min = d0; } else { o++; energy = e2; if ( o > endO ) o = endO ; min = d2; } } else { if ( d1 <= d2 ) { energy = e1; min = d1; } else { o++; energy = e2; if ( o > endO ) o = endO; min = d2; } } point.x = p; point.y = o; } _energy += min; if (_energy> bestEnergy) { _energy = Number.MAX_VALUE; return; } } } public function walk( func: Function ): void { var p: SeamPoint = _points; while ( p ) { func( p.x, p.y ); p = p.next; } } } class SeamPoint { public var x: int; public var y: int; public var next: SeamPoint; }