Flash在线拍摄用户头象

简介: 很多网站在上传用户头象时,除了传统方式上传外,都支持在线摄像头拍照并做简单编辑,完成之后再将图象数据提交到服务端(比如ASP.Net),这几天正好需要这个功能,研究了下,思路如下: 1、先获取摄像头视频 2、利用BitmapData.

很多网站在上传用户头象时,除了传统方式上传外,都支持在线摄像头拍照并做简单编辑,完成之后再将图象数据提交到服务端(比如ASP.Net),这几天正好需要这个功能,研究了下,思路如下:

1、先获取摄像头视频

2、利用BitmapData.draw来对视频截图

3、在截图上,放一个方块允许用户手动调整位置,同时允许截图做缩放

4、用户调整完成后,对指定区域的BitmapData做copyPixes处理(即拷贝指定区域的像素)

5、将上一步得到的新BitmapData进行Jpeg编码压缩,然后再转到base64字符串

6、将字符串发送到ASP.Net,然后还原成图片保存即可(即base64的解码)

 

flash端代码:(第6步省略了)

import flash.media.Camera;
import flash.text.TextField;
import flash.media.Video;
import flash.text.TextFormat;
import fl.controls.Button;
import flash.utils.Timer;
import flash.events.MouseEvent;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.geom.Rectangle;
import flash.events.Event;

var _cam:Camera;
var _txtInfo:TextField = txtInfo;
var _txtMsg:TextField = txtMsg;
var _btnGet:Button = btnGet;
var _btnSave:Button = btnSave;
var _video:Video = myVideo;
var _timer:Timer;
var _videoIsWorked:Boolean = false;
var _bmp:Bitmap;
var _bmpTest:Bitmap;
var _mask:Sprite;
var _slider:SimpleSlider;

init();

function init():void
{
	this._txtMsg.visible = false;
	this._btnGet.label = "拍 照";
	this._btnSave.label = "保 存";
	this._txtInfo.selectable = false;
	var style:TextFormat = new TextFormat();
	style.font = "宋体";
	style.size = 12;//字体大小
	style.color = 0x000000;//RGB色
	style.leading = 7;//行间距
	this._btnGet.setStyle("textFormat",style);
	this._btnSave.setStyle("textFormat",style);
	getCamera();
}

function getCamera():void
{

	this._btnGet.enabled = false;
	this._btnSave.enabled = false;

	this._cam = Camera.getCamera();
	if (_cam == null)
	{
		this._txtInfo.text = "未检测到摄像头设备!";
		return;
	}



	_cam.addEventListener(StatusEvent.STATUS, cameraStatusHandler);
	_cam.addEventListener(ActivityEvent.ACTIVITY, cameraActivityHandler);

	_cam.setQuality(0,0);
	this._video.attachCamera(this._cam);

}

//用户选择是否摄像头时触发 ;
function cameraStatusHandler(e:StatusEvent):void
{

	if (e.code == "Camera.Muted")
	{
		this._txtInfo.text = "您不允许使用摄像头!";
	}
	else if (e.code == "Camera.Unmuted")
	{
		this._txtInfo.text = "摄像头视频获取中...";
		_timer = new Timer(100,20);//每隔100ms检测摄像头状态,一共检测20次   
		cameraActivityHandler(null);
	}
}


//摄像头有活动时被触发 
function cameraActivityHandler(e:ActivityEvent):void
{
	if (! _videoIsWorked)
	{
		if (_timer != null)
		{
			_timer.addEventListener(TimerEvent.TIMER, checkCamera);
			_timer.addEventListener(TimerEvent.TIMER_COMPLETE, checkCameraComplete);
			_timer.start();
		}
	}
}


//timer回调函数,用于检测摄像头设备是否正确 
function checkCamera(e:TimerEvent):void
{
	this._txtInfo.text = "摄像头视频获取中...";
	if (this._cam.currentFPS > 0)
	{
		_timer.stop();
		_videoIsWorked = true;
		this._txtInfo.text = "";//摄像头工作正常

		this._txtInfo.text = "摄像头正常,请点击拍照";

		//trace("_cam.width=",_cam.width,",_cam.height=",_cam.height);

		this._btnGet.addEventListener(MouseEvent.CLICK,btnGet_Click);
		this._btnGet.enabled = true;

		this._video.width = 240;
		this._video.height = 180;

		//trace(this._video.width,this._video.height);

	}

}


function btnGet_Click(e:MouseEvent):void
{
	var bmd:BitmapData = new BitmapData(_cam.width,_cam.height);
	bmd.draw(_video);
	//trace(bmd.width,bmd.height);
	if (this._bmp == null)
	{
		this._bmp = new Bitmap(bmd);
		addChild(_bmp);
		_bmp.x = 260;
		_bmp.y = 10;
		_bmp.width = _video.width;
		_bmp.height = _video.height;

		if (this._mask == null)
		{
			this._mask = new Sprite();
			this._mask.graphics.beginFill(0xffffff,0.3);
			this._mask.graphics.drawRect(0,0,125,125);
			this._mask.graphics.endFill();
			this._mask.graphics.lineStyle(1,0xff0000,1);
			this._mask.graphics.lineTo(1,124);
			this._mask.graphics.lineTo(124,124);
			this._mask.graphics.lineTo(124,1);
			this._mask.graphics.lineTo(1,1);
			addChild(this._mask);
			this._mask.x = 260 + 57;
			this._mask.y = 10 + 27;
			this._mask.buttonMode = true;
			this._mask.addEventListener(MouseEvent.MOUSE_DOWN,mask_startDrag);
			this.stage.addEventListener(MouseEvent.MOUSE_UP,stage_endDrag);

			if (_slider == null)
			{
				_slider = new SimpleSlider(125,180,180);
				_slider.backWidth = 120;
				_slider.backHeight = 6;
				_slider.handleHeight = 16;
				_slider.addEventListener(Event.CHANGE,slider_Change);
				addChild(_slider);
				_slider.x = 320;
				_slider.y = 205;
				this._txtMsg.visible = true;
			}
		}
	}
	else
	{
		this._bmp.bitmapData = bmd;
	}
	this._btnSave.enabled = true;

	this._txtInfo.text = "拖动左侧方块可调整位置"
	;
	this._btnSave.addEventListener(MouseEvent.CLICK,btnSave_Click);
}


function btnSave_Click(e:Event):void
{
	//因为视频的大小跟摄像头原始像素的尺寸并不一致(即视频可能缩放过了,所以要用比例调整回最初始的状态)
	var ratio:Number = this._cam.width / this._bmp.width;

	var imgWidth:int = this._mask.width * ratio;
	var imgHeight:int = this._mask.height * ratio;
	//trace(ratio);

	var bmd:BitmapData = new BitmapData(imgWidth,imgHeight,false,0xffff99);
	bmd.copyPixels(this._bmp.bitmapData,new Rectangle((this._mask.x-260)*ratio,(this._mask.y - 10)*ratio,imgWidth,imgHeight),new Point());

	if (this._bmpTest == null)
	{
		this._bmpTest = new Bitmap(bmd);
		addChild(_bmpTest);
		_bmpTest.x = 375;
		_bmpTest.y = 230;

	}
	else
	{
		this._bmpTest.bitmapData = bmd;
	}

	_bmpTest.width = this._mask.width;
	_bmpTest.height = this._mask.height;
	trace("_bmpTest.width=",this._mask.width,",_bmpTest.height=",this._mask.height);

	var jpegEncoder:JPGEncoder = new JPGEncoder();
	var jpegArr:ByteArray = jpegEncoder.encode(bmd);//压缩成jpeg  
	
	trace(jpegArr.length);
	
	var base64string:String = Base64.encode(jpegArr);
	
	txtBase64.text = base64string;
	
	trace(base64string.length);

}

function slider_Change(e:Event):void
{
	//trace(e);
	this._bmp.height = this._slider.value;
	this._bmp.width = this._bmp.height * 4 / 3;
}

function mask_startDrag(e:MouseEvent):void
{
	this._mask.startDrag(false,new Rectangle(260,10,240-125,180-125));


}

function stage_endDrag(e:MouseEvent):void
{
	this._mask.stopDrag();
	//trace("x=",_mask.x);
	//trace("y=",_mask.y);
}

function checkCameraComplete(e:TimerEvent):void
{
	this._txtInfo.text = "设备无法使用!(有可能被占用)";
	_timer.removeEventListener(TimerEvent.TIMER, checkCamera);
	_timer.removeEventListener(TimerEvent.TIMER_COMPLETE, checkCameraComplete);
	_timer = null;
}

Flash在线演示(需要电脑上连接好摄像头)

C#端的处理示例:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;

namespace OnlinePhotoCapture
{
    /// <summary>
    /// 将图片base64字符串原还原为图片并调整尺寸后保存(by 菩提树下的杨过http://yjmyzz.cnblogs.com/)   
    /// </summary>    
    public class SavePhoto : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";

            string base64String = "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";

            Image bmp = null;
            MemoryStream ms = null;
            try
            {
                byte[] b = Convert.FromBase64String(base64String);
                ms = new MemoryStream(b);
                bmp = ImageResize(new Bitmap(ms),125,125);
                bmp.Save(context.Request.MapPath("logo.jpg"), ImageFormat.Jpeg);
                context.Response.Write("success");
            }
            catch (Exception ex)
            {
                context.Response.Write("failure:" + ex.Message.ToString());
            }
            finally
            {
                bmp.Dispose();
                ms.Dispose();
            }

        }

       

        /// <summary>
        /// 修改图片尺寸
        /// </summary>
        /// <param name="imgSrc"></param>
        /// <returns></returns>
        private Image ImageResize(Image imgSrc,int width,int height)
        {
            Image newImage = imgSrc.GetThumbnailImage(125, 125, null, new IntPtr());
            Graphics g = Graphics.FromImage(newImage);
            g.DrawImage(newImage, 0, 0, newImage.Width, newImage.Height);
            g.Dispose();
            return newImage;
        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

    }
}
目录
相关文章
|
11月前
【自媒体直播】手机摄像电脑控制OBS多平台推流解决方案
【自媒体直播】手机摄像电脑控制OBS多平台推流解决方案
279 0
|
存储 固态存储 前端开发
【SSD系列】五分钟,100余行代码,纯web技术一起实现摄像头和麦克风视频录制,并带历史记录功能
关于关于【SSD系列】: 前端一些有意思的内容,旨在3-10分钟里, 500-1500字,有所获,又不为所累。 如题,今天我们用纯web技术,实现摄像头+麦克风 视频的录制功能,代码约100余行
184 0
【SSD系列】五分钟,100余行代码,纯web技术一起实现摄像头和麦克风视频录制,并带历史记录功能
推荐15个在线多媒体(图片、音频、视频)编辑器,互联网营销
  在处理多媒体文件的时候,我们通常都是使用自己电脑上已安装好的桌面应用程序,如果某天我们在使用的公共电脑上没有我们需要的软件,更坏的情况是,这些公共电脑不允许安装软件,这时候就需要在线的编辑器了。最近几年,Web应用程序越来越受到关注,原因在于它的简单、方便和轻巧,只要你有一个连接到互联网的浏览器,就可以马上处理你的图片、音频和视频。
2538 0
|
Android开发 iOS开发
阿里云移动端播放器高级功能---截图和音频波形
如果用户对视频播放中的某一帧画面特别感兴趣,可以使用截图功能将这一帧视频保存起来。另外有一种场景想知道是否有声音,或者想感知声音的大小震动频率等,可以通过显示一个声音的波形来形象的表示。如下图所示:
8257 0
|
编解码 C# C++
编程实战——电影管理器之利用MediaInfo获取高清视频文件的相关信息
随着高速(20M)宽带、HTPC、大容量硬盘(3T)的普及,下载高清片并利用大屏幕观看也成为普通的事情。 随着下载影片的增多,管理就有了问题,有时在茫茫文件夹下找寻一个影片也是一件费时费力的事。 于是萌生了自己编写电影管理器的想法,并逐步逐步在实现。
2178 0