Skip to content

Instantly share code, notes, and snippets.

@JesterXL
Created March 23, 2012 18:24
Show Gist options
  • Save JesterXL/2173475 to your computer and use it in GitHub Desktop.
Save JesterXL/2173475 to your computer and use it in GitHub Desktop.
class used to magnify a portion of Strobe video
package com.thirdiris.viaasplayer.components
{
import com.bit101.components.Component;
import com.thirdiris.viaasplayer.events.view.VideoMagnifierEvent;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.DisplayObjectContainer;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Video;
import flash.text.TextField;
import flash.text.TextFormat;
import org.osmf.media.videoClasses.VideoSurface;
import spark.primitives.Rect;
[Event(name="closeClicked", type="com.thirdiris.viaasplayer.events.view.VideoMagnifierEvent")]
public class VideoMagnifier extends Component
{
private static const BITMAP_WIDTH:Number = 201;
private static const BITMAP_HEIGHT:Number = 134;
[Embed(source="/assets/viaasimages/magnifier-background.png")]
private var MagnifierBackground:Class;
[Embed(source="/assets/viaasimages/button-close.png")]
private var ButtonClose:Class;
private var _videoSurface:VideoSurface;
private var videoSurfaceDirty:Boolean = false;
private var ticker:Sprite;
private var backgroundImage:Bitmap;
private var background:Sprite;
private var bitmap:Bitmap;
private var bitmapData:BitmapData;
private var originalBitmapData:BitmapData;
private var maskShape:Shape;
private var closeButton:Sprite;
private var titleField:TextField;
private var zoomLabel:TextField;
private var zoomSlider:Slider;
private var debugTicker:Sprite;
private var centerPoint:Point = new Point();
private var zoomRectangle:Rectangle = new Rectangle();
private var targetPoint:Point = new Point(0, 0);
private var dragging:Boolean = false;
private var scaleMatrix:Matrix;
private var magnification:Number = 2;
private var videoIsTooSmall:Boolean = false;
//private var video:Video;
public function get videoSurface():VideoSurface { return _videoSurface; }
public function set videoSurface(value:VideoSurface):void
{
if(value !== _videoSurface)
{
_videoSurface = value;
videoSurfaceDirty = true;
// [jwarden 3.2.2012] KLUDGE: I love Strobe.
//video = _videoSurface.getChildAt(0) as Video;
invalidateProperties();
}
}
public function VideoMagnifier(parent:DisplayObjectContainer=null, xpos:Number=0, ypos:Number=0)
{
super(parent, xpos, ypos);
addEventListener(Event.ADDED_TO_STAGE, onAdded);
addEventListener(Event.REMOVED_FROM_STAGE, onRemoved);
}
private function onAdded(event:Event):void
{
if(debugTicker == null)
{
debugTicker = new Sprite();
stage.addChild(debugTicker);
debugTicker.addEventListener(Event.ENTER_FRAME, onDebugDraw);
}
}
private function onRemoved(event:Event):void
{
if(debugTicker)
{
stage.removeChild(debugTicker);
debugTicker.removeEventListener(Event.ENTER_FRAME, onDebugDraw);
debugTicker = null;
}
}
public function destroy():void
{
stopDrag();
_videoSurface = null;
stopDrawing();
removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
if(stage)
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
}
if(bitmapData)
{
bitmapData.dispose();
bitmapData = null;
}
if(bitmap)
bitmap = null;
if(originalBitmapData)
{
originalBitmapData.dispose();
originalBitmapData = null;
}
}
protected override function init():void
{
//width = 223;
//height = 225;
width = BITMAP_WIDTH;
height = BITMAP_HEIGHT;
tabEnabled = false;
buttonMode = useHandCursor = true;
name = "VideoMagnifier";
super.init();
}
protected override function addChildren():void
{
super.addChildren();
ticker = new Sprite();
background = new Sprite();
addChild(background);
//background.blendMode = BlendMode.INVERT;
background.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
background.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
backgroundImage = new MagnifierBackground() as Bitmap;
addChild(backgroundImage);
backgroundImage.x = 1;
backgroundImage.y = 6;
maskShape = new Shape();
addChild(maskShape);
maskShape.x = 8;
maskShape.y = 30;
closeButton = new Sprite();
addChild(closeButton);
closeButton.tabChildren = closeButton.mouseChildren = false;
closeButton.buttonMode = closeButton.useHandCursor = true;
closeButton.addChild(new ButtonClose());
closeButton.addEventListener(MouseEvent.CLICK, onCloseButtonClicked);
closeButton.x = 208;
closeButton.y = 1;
titleField = new TextField();
addChild(titleField);
titleField.selectable = false;
titleField.tabEnabled = titleField.mouseEnabled = titleField.mouseWheelEnabled = false;
var headerFMT:TextFormat = new TextFormat();
headerFMT.font = "Helvetica Neue";
headerFMT.size = 14;
headerFMT.color = 0x333333;
titleField.defaultTextFormat = headerFMT;
titleField.text = "Magnifier";
titleField.x = (backgroundImage.width / 2) - ((titleField.textWidth + 4) / 2);
titleField.y = 9;
zoomLabel = new TextField();
addChild(zoomLabel);
zoomLabel.selectable = false;
zoomLabel.tabEnabled = zoomLabel.mouseEnabled = zoomLabel.mouseWheelEnabled = false;
var zoomFormat:TextFormat = new TextFormat();
zoomFormat.size = 11;
zoomFormat.color = 0x333333;
zoomFormat.font = "Helvetica Neue";
zoomLabel.defaultTextFormat = zoomFormat;
zoomLabel.text = "Zoom:";
zoomLabel.x = 12;
zoomLabel.y = 199;
zoomSlider = new Slider(this);
addChild(zoomSlider);
zoomSlider.initialize(2, 1, 10);
zoomSlider.addEventListener(Event.CHANGE, onZoomChange);
zoomSlider.x = 52;
zoomSlider.y = 198;
}
protected override function commitProperties():void
{
super.commitProperties();
if(videoSurfaceDirty)
{
videoSurfaceDirty = false;
if(videoSurface)
{
createBitmap();
startDrawing();
}
else
{
stopDrawing();
}
}
}
public override function draw():void
{
super.draw();
var g:Graphics = background.graphics;
g.clear();
//g.beginFill(0x333333, .7);
//g.drawRoundRect(-10, -10, width + 20, height + 20, 12, 12);
g.lineStyle(2, 0xFF0000);
g.beginFill(0x000000, 0);
g.drawRect(0, 0, width, height);
g.endFill();
g = maskShape.graphics;
g.clear();
g.beginFill(0x00FF00, .5);
g.drawRect(0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
g.endFill();
createBitmap();
}
private function createBitmap():void
{
if(bitmapData)
bitmapData.dispose();
if(originalBitmapData)
originalBitmapData.dispose();
if(videoSurface.videoWidth > 0 && videoSurface.videoHeight > 0)
{
videoIsTooSmall = false;
}
else
{
videoIsTooSmall = true;
return;
}
bitmapData = new BitmapData(BITMAP_WIDTH, BITMAP_HEIGHT, false, 0);
//originalBitmapData = new BitmapData(videoSurface.videoWidth, videoSurface.videoHeight, false, 0);
originalBitmapData = new BitmapData(2880, 2880, false, 0);
if(bitmap == null)
{
bitmap = new Bitmap(bitmapData, "auto", true);
//addChildAt(bitmap, 0);
//bitmap.mask = maskShape;
addChild(bitmap);
}
else
{
bitmap.bitmapData = bitmapData;
}
}
private function startDrawing():void
{
stopDrawing();
ticker.addEventListener(Event.ENTER_FRAME, onTick);
}
private function stopDrawing():void
{
ticker.removeEventListener(Event.ENTER_FRAME, onTick);
}
private function onTick(event:Event):void
{
if(videoIsTooSmall)
{
if(videoSurface.videoWidth > 0 && videoSurface.videoHeight > 0)
{
videoIsTooSmall = false;
createBitmap();
}
else
{
return;
}
}
var video:Video = videoSurface.getChildAt(0) as Video;
if(video)
{
// jwarden's algorithm
/*
originalBitmapData.draw(video, video.transform.matrix);
centerPoint.x = x;
centerPoint.y = y;
centerPoint = parent.localToGlobal(centerPoint);
centerPoint = video.parent.globalToLocal(centerPoint);
zoomRectangle.x = centerPoint.x;
zoomRectangle.y = centerPoint.y;
zoomRectangle.width = width;
zoomRectangle.height = height;
bitmapData.copyPixels(originalBitmapData, zoomRectangle, targetPoint);
bitmap.width = width * magnification;
bitmap.height = height * magnification;
bitmap.x = (width / 2) - (bitmap.width / 2) + maskShape.x;
bitmap.y = (height / 2) - (bitmap.height / 2) + maskShape.y;
*/
// jwarden's 2nd algo
originalBitmapData.draw(video, video.transform.matrix);
/*
xPos: 0, yPos: 300, zoomArea: (x=0, y=300, w=280, h=180), zoomControl.currentWidth: 300, zoomControl.currentHeight: 200, zoomControl.imageCanvas.width: 280, zoomControl.imageCanvas.height: 180
zoomControl.zoomImage.x: 0, zoomControl.zoomImage.y: 0, zoomControl.zoomImage.width: 280, zoomControl.zoomImage.height: 180
*/
var point:Point = new Point(x, y);
point = localToGlobal(point);
point = videoSurface.globalToLocal(point);
var xPos:Number = point.x - videoSurface.x;
var yPos:Number = point.y - videoSurface.y;
var zoomArea:Rectangle = new Rectangle(xPos, yPos, BITMAP_WIDTH, BITMAP_HEIGHT);
bitmapData.copyPixels(originalBitmapData, zoomArea, targetPoint);
bitmap.width = width * magnification;
bitmap.height = height * magnification;
bitmap.x = (BITMAP_WIDTH - bitmap.width) * (xPos / (videoSurface.videoWidth - BITMAP_WIDTH));
bitmap.y = (BITMAP_HEIGHT - bitmap.height) * (yPos / (videoSurface.videoHeight - BITMAP_HEIGHT));
/*
bitmap.width = width * magnification;
bitmap.height = height * magnification;
bitmap.x = (width / 2) - (bitmap.width / 2) + maskShape.x;
bitmap.y = (height / 2) - (bitmap.height / 2) + maskShape.y;
*/
// jmiranda's algo from Loki
/*
bmd = new BitmapData(720,480,true,0);
clipMatrix = new Matrix();
clipMatrix.tx = -32;
clipMatrix.ty = -45;
bmd.draw(controlState, clipMatrix);
// Based off the zoom control
var xPos:Number = zoomControl.currentX;
var yPos:Number = zoomControl.currentY;
var zoomArea:Rectangle = new Rectangle(xPos, yPos, zoomControl.currentWidth - 20, zoomControl.currentHeight - 20);
var finalBMD:BitmapData = new BitmapData(zoomControl.currentWidth - 20, zoomControl.currentHeight - 20,false,0);
finalBMD.copyPixels(bmd, zoomArea, new Point(0,0));
zoomBitmap = new Bitmap(finalBMD,"auto",true);
zoomControl.zoomImage.width = (zoomControl.currentWidth - 20) * zoomControl.zoom.value;
zoomControl.zoomImage.height = (zoomControl.currentHeight - 20) * zoomControl.zoom.value;
zoomControl.zoomImage.x = (zoomControl.imageCanvas.width - zoomControl.zoomImage.width) * (zoomControl.currentX / (740 - zoomControl.currentWidth));
zoomControl.zoomImage.y = (zoomControl.imageCanvas.height - zoomControl.zoomImage.height) * (zoomControl.currentY / (500 - zoomControl.currentHeight));
*/
}
}
private function onDebugDraw(event:Event):void
{
var g:Graphics = debugTicker.graphics;
g.clear();
if(videoSurface && originalBitmapData && centerPoint && zoomRectangle && bitmap)
{
var video:Video = videoSurface.getChildAt(0) as Video;
if(video)
{
g.lineStyle(0, 0xFFFFFF);
g.moveTo(videoSurface.x, videoSurface.y);
g.drawRect(videoSurface.x, videoSurface.y, videoSurface.width, videoSurface.height);
g.lineStyle(2, 0xFF0000);
g.moveTo(video.x, video.y);
g.drawRect(video.x, video.y, video.videoWidth, video.videoHeight);
g.lineStyle(2, 0x0000FF);
g.moveTo(zoomRectangle.x, zoomRectangle.y);
g.drawRect(zoomRectangle.x, zoomRectangle.y, zoomRectangle.width, zoomRectangle.height);
g.endFill();
}
}
}
/*
private function drawZoom(event:Event):void {
bmd = new BitmapData(720,480,true,0);
clipMatrix = new Matrix();
clipMatrix.tx = -32;
clipMatrix.ty = -45;
bmd.draw(controlState, clipMatrix);
// Based off the zoom control
var xPos:Number = zoomControl.currentX;
var yPos:Number = zoomControl.currentY;
var zoomArea:Rectangle = new Rectangle(xPos, yPos, zoomControl.currentWidth - 20, zoomControl.currentHeight - 20);
var finalBMD:BitmapData = new BitmapData(zoomControl.currentWidth - 20, zoomControl.currentHeight - 20,false,0);
finalBMD.copyPixels(bmd, zoomArea, new Point(0,0));
zoomBitmap = new Bitmap(finalBMD,"auto",true);
zoomControl.zoomImage.width = (zoomControl.currentWidth - 20) * zoomControl.zoom.value;
zoomControl.zoomImage.height = (zoomControl.currentHeight - 20) * zoomControl.zoom.value;
zoomControl.zoomImage.x = (zoomControl.imageCanvas.width - zoomControl.zoomImage.width) * (zoomControl.currentX / (740 - zoomControl.currentWidth));
zoomControl.zoomImage.y = (zoomControl.imageCanvas.height - zoomControl.zoomImage.height) * (zoomControl.currentY / (500 - zoomControl.currentHeight));
}
*/
private function onMouseDown(event:MouseEvent):void
{
if(dragging == false)
{
dragging = true;
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove, false, 0, true);
var bounds:Rectangle = new Rectangle(videoSurface.x, videoSurface.y, videoSurface.width - width, videoSurface.height - height);
startDrag(false, bounds);
}
}
private function onMouseMove(event:MouseEvent):void
{
event.updateAfterEvent();
}
private function onMouseUp(event:MouseEvent):void
{
if(dragging)
{
dragging = false;
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
stopDrag();
}
}
private function onCloseButtonClicked(event:MouseEvent):void
{
dispatchEvent(new VideoMagnifierEvent(VideoMagnifierEvent.CLOSE_CLICKED));
}
private function onZoomChange(event:Event):void
{
magnification = zoomSlider.value;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment