views:

37

answers:

2

Hi all - this is (I think) a relatively simple math question but I've spent a day banging my head against it and have only the dents and no solution...

I'm coding in actionscript 3 - the functionality is:

  1. large image loaded at runtime. The bitmapData is stored and a smaller version is created to display on the available screen area (I may end up just scaling the large image since it is in memory anyway).

  2. The user can create a rectangle hotspot on the smaller image (the functionality will be more complex: multiple rects with transparency: example a donut shape with hole, etc)

3 When the user clicks on the hotspot, the rect of the hotspot is mapped to the larger image and a new bitmap "callout" is created, using the larger bitmap data. The reason for this is so the "callout" will be better quality than just scaling up the area of the hotspot.

The image below shows where I am at so far- the blue rect is the clicked hotspot. In the upper left is the "callout" - copied from the larger image. I have the aspect ratio right but I am not mapping to the larger image correctly.

Ugly code below... Sorry this post is so long - I just figured I ought to provide as much info as possible. Thanks for any tips!

--trace of my data values

*source BitmapDada 1152 864

scaled to rect 800 600

scaled BitmapData 800 600

selection BitmapData 58 56

scaled selection 83 80

ratio 1.44

before (x=544, y=237, w=58, h=56)

(x=544, y=237, w=225.04, h=217.28) *

Image here: http://i795.photobucket.com/albums/yy237/skinnyTOD/exampleST.jpg

public function onExpandCallout(event:MouseEvent):void{
    if (maskBitmapData.getPixel32(event.localX, event.localY) != 0){
        var maskClone:BitmapData = maskBitmapData.clone();

        //amount to scale callout - this will vary/can be changed by user
        var  scale:Number =150 //scale percentage
        var normalizedScale :Number = scale/=100;

        var w:Number = maskBitmapData.width*normalizedScale;
        var h:Number = maskBitmapData.height*normalizedScale;

        var ratio:Number =  (sourceBD.width /targetRect.width);

        //creat bmpd of the scaled size to copy source into
       var scaledBitmapData:BitmapData = new BitmapData(maskBitmapData.width * ratio, maskBitmapData.height * ratio, true, 0xFFFFFFFF);

       trace("source BitmapDada " + sourceBD.width, sourceBD.height);
       trace("scaled to rect " + targetRect.width, targetRect.height);
       trace("scaled BitmapData", bkgnImageSprite.width, bkgnImageSprite.height);
       trace("selection BitmapData", maskBitmapData.width, maskBitmapData.height);
       trace("scaled selection", scaledBitmapData.width, scaledBitmapData.height);
       trace("ratio", ratio);

       var scaledBitmap:Bitmap = new Bitmap(scaledBitmapData);

       var scaleW:Number = sourceBD.width / scaledBitmapData.width;
       var scaleH:Number = sourceBD.height / scaledBitmapData.height;

       var scaleMatrix:Matrix = new Matrix();   
       scaleMatrix.scale(ratio,ratio);

       var sRect:Rectangle = maskSprite.getBounds(bkgnImageSprite);
       var sR:Rectangle = sRect.clone();
       var ss:Sprite = new Sprite();
       ss.graphics.lineStyle(8, 0x0000FF);
       //ss.graphics.beginFill(0x000000, 1);
       ss.graphics.drawRect(sRect.x, sRect.y, sRect.width, sRect.height);
       //ss.graphics.endFill();
       this.addChild(ss);

       trace("before " + sRect);

       w = uint(sRect.width * scaleW);
       h = uint(sRect.height  * scaleH);

       sRect.inflate(maskBitmapData.width * ratio, maskBitmapData.height * ratio);
       sRect.offset(maskBitmapData.width * ratio, maskBitmapData.height * ratio);

       trace(sRect);

       scaledBitmapData.copyPixels(sourceBD, sRect, new Point());
       addChild(scaledBitmap);
       scaledBitmap.x = offsetPt.x;
       scaledBitmap.y = offsetPt.y;
    }
}
A: 

Try doing the following:

Grab an image that is the same ratio as your stage... add a class to the image called CatBMP, then try this code as your document class

package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;

    public class TestExpand extends Sprite {

        var src:BitmapData;
        var scaledCat:Bitmap;
        var scale:Number;
        var selection:Sprite;
        var interactiveCat:Sprite;
        var expanded:Sprite;

        public function TestExpand() {
            selection = new Sprite();
            expanded = new Sprite();
            interactiveCat = new Sprite();
            src = new CatBMP(0, 0);
            scale = stage.stageWidth / src.width;
            var scaledSrc:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight);
            var matrix:Matrix = new Matrix();
            matrix.scale(scale, scale);
            scaledSrc.draw(src, matrix); 
            scaledCat = new Bitmap(scaledSrc);
            interactiveCat.addChild(scaledCat);
            addChild(interactiveCat);
            interactiveCat.addEventListener(MouseEvent.CLICK, __onClicked);
        }

        private function __onClicked($evt:MouseEvent):void {
            addChild(selection);
            selection.graphics.clear();
            selection.graphics.lineStyle(1, 0x0000ff);
            selection.graphics.beginFill(0x00ff00, .5);
            selection.graphics.drawRect(0, 0, 50, 50);
            selection.graphics.endFill();
            selection.x = $evt.localX - selection.width / 2;
            selection.y = $evt.localY - selection.height / 2;
            __generateView();
        }

        private function __generateView():void {
            var expandedBMD:BitmapData = new BitmapData(selection.width / scale, selection.height / scale);
            var rect:Rectangle = new Rectangle(selection.x / scale, selection.y / scale, selection.width / scale, selection.height / scale);
            expandedBMD.copyPixels(src, rect, new Point(0, 0));
            expanded.addChild(new Bitmap(expandedBMD));
            addChild(expanded);
        }

    }

}

Or here is a ZIP Archive of a sample.

sberry2A
A: 

Thanks!

public function onExpandCallout(event:MouseEvent):void{
// TODO: build this on startup or only on click? Speed vs memory

if (calloutState == true) return;

if (maskBitmapData.getPixel32(event.localX, event.localY) != 0){

    calloutState = true;

    //create bitmap from source using scaled selection rect
    var ratio:Number =  (sourceBMD.width /targetRect.width);
    var sRect:Rectangle = hotSpotSprite.getBounds(bkgnImageSprite);
    var destRect:Rectangle = new Rectangle(sRect.x * ratio, sRect.y * ratio, sRect.width * ratio, sRect.height * ratio);
    calloutBitmapData = new BitmapData(destRect.width, destRect.height, true, 0xFFFFFFFF);
    calloutBitmap = new Bitmap(calloutBitmapData);

    //-- scale alpha mask
    var scaledMaskBitmapData:BitmapData =  new BitmapData(destRect.width, destRect.height, true, 0x00000000);
    var maskScale:Number = scaledMaskBitmapData.width / maskBitmapData.width;
    var mMatrix:Matrix = new Matrix(maskScale, 0, 0, maskScale);
    scaledMaskBitmapData.draw(maskBitmapData,mMatrix,null,null,null, false);

    // copy source with scaled alpha  
    calloutBitmapData.copyPixels(sourceBMD, destRect, new Point(), scaledMaskBitmapData, new Point());

    scaledMaskBitmapData = null;

    // apply filter to bitmap
    var myDropShadowFilter:DropShadowFilter = new DropShadowFilter();
    myDropShadowFilter.distance = 12;
    myDropShadowFilter.alpha = .3
    myDropShadowFilter.strength = 1;
    myDropShadowFilter.blurX = 8;
    myDropShadowFilter.blurY = 8;
    calloutBitmap.filters = [myDropShadowFilter];

    //place on screen
    calloutSprite = new Sprite();
    calloutSprite.addChild(calloutBitmap)
    calloutSprite.x = offsetPt.x;
    calloutSprite.y = offsetPt.y;
    // ADD TO PARENT DisplayContainer
    calloutLayer.addChild(calloutSprite);

    //              calloutSprite.scaleX = 2;
    //              calloutSprite.scaleY = 2;
    calloutSprite.doubleClickEnabled = true;

    calloutSprite.addEventListener(MouseEvent.DOUBLE_CLICK, onCollapseCallout); 
    calloutSprite.addEventListener(MouseEvent.MOUSE_DOWN, onStartDrag); 
    calloutSprite.addEventListener(MouseEvent.MOUSE_UP, onStopDrag);    
}

}

skinnyTOD