2008-1-2日提供源码下载:http://www.swordyang.cn/file/flashcamera.rar
我记得要毕业那时候,很多同学都在街上拍大头贴,后来老班还特地搞了个软件,自己给学生拍着玩,随着FLASH功能越来越强大,在线大头贴也出现在人们的 视线之中,那么这样的在线大头贴系统又是如何开发的。虽然网络上存在着很多源码,但由于代码艰涩难懂,又没有系统的讲解过程,很多初学者只好望而生畏。今 天懒羊以一个初学者的角度,分别通过asp与asp.net和大家一起开发一个简单的大头贴系统。
根据懒羊的一贯作风,我们还是从最基本的原理开始,本次与以往不同的是,懒羊将会分步的给出代码示范,而不是在最后一下子把代码全部扔给大家,大家如果有什么问题,可以直接通过QQ:64692463与我联系。
准备工作:摄像头 Jpge组件(asp)
原理:
我们知道位图是由象素点构成,例如一张160*120的位图,我们可以看成由19200(160×120)个象素点构成,然后设置每个点的颜色值,这样 我们就可以轻松的绘制出一张图片,当然这个给象素点设置颜色的事就可以交给计算机完成,值得注意的是图片尺寸越大速度越慢。
首先我们通过flash中的Camera对象通过摄像头捕抓图像,存入变量中,然后传递给服务器端(asp.net或asp),服务器端再通过一定的算法对图像每个象素点进行颜色设置,最终还原出Flash抓取的图片。
一、 Flash部分
1、 捕获视频
1) Cmaera.get() 返回对用于捕获视频的 Camera 对象的引用。若要实际开始捕获视频,必须将 Camera 对象附加到 Video 对象
2) Video.attachVideo(source) 指定将在舞台上的 Video 对象的边界内显示的视频流
参数Source: 正在捕获视频数据的 Camera 对象,或 NetStream 对象。要切断与该 Video 对象的连接,请为 source 传递 null.
操作:根据以上两点,我们先来看一个示例:
新建一个新文件myCmaera.fla,在库中右击新建视频,按下图设置
从库中将my_video拖入到场景中,设置其属性名为my_video,在场景第一帧输入以下代码:
myCamera=Camera.get();//捕获系统摄像头视频
my_video.attachVideo(myCamera);//将视频添加到Video对象中播放
有时我们为了检测视频的存在,往往通过以下代码进行判断
if(Camera.names.length>0){}
备注:Camera.names.length 获得当前系统摄像头的个数
2、 抓取图象
1) BitmapData(width, height, [transparent], [fillColor])
含义:创建一个具有指定的宽度和高度的 BitmapData 对象
参数:Width 位图图像宽度,以象素点为单位
Height 位图图像高度,以象素点为单位
Transparent 位图的第个象素点是否支持透明,默认为True.如果为True,则fillColor值设置为0Xaarrggbb(32位ARGB颜色值)
fillColor用于填充位图图像区域的 32 位 ARGB 颜色值
2) BitmapData .draw(source, [matrix], [colorTransform], [blendMode], [clipRect], [smooth])
含义:使用 Flash Player 矢量呈现器在目标图像上绘制源图像或影片剪辑
参数: Source要绘制的 BitmapData 对象,程序中为捕获的视频源my_video,当然也可以为其它的影片剪辑
Matrix 一个 Matrix 对象,用于缩放、旋转或转换位图的坐标
colorTransform一个 ColorTransform 对象,用于调整位图的颜色值
blendMode 一个 BlendMode 对象
clipRect 一个 Rectangle 对象,用于截切
smooth 确定缩放时是否要对 BitmapData 对象进行平滑处理
3) MoveClip.attachBitmap(bmp, depth, [pixelSnapping], [smoothing])
含义:将位图图像附加到影片剪辑
参数:bmp 透明的或不透明的位图图像
Depth 一个整数,它指定应该放置位图图像的影艏诘纳疃燃侗?/P>
picelSnapping 像素对齐模式包括 auto、always 和 never.默认模式为 auto
auto: 只要位图没有被拉伸或旋转,它就执行像素对齐
always:始终执行像素对齐,而不管是否拉伸和旋转
nerver:关闭影片剪辑的像素对齐
smoothing:平滑处理模式为 true(表示启用)或 false(表示禁用)。默认模式为禁用
操作:现在我们对刚刚做好的示例再稍做修改
新建一个空影片剪辑,将它从库中拖到场影中,命名为photo,并创建一个按钮,在按钮中添加如下代码:
on (release) { myBitmap = new flash.display.BitmapData(160, 120); //创建位图对象 myBitmap.draw(my_video); //绘制my_video photo.attachBitmap(myBitmap, 1, "always", true); //添加到photo影片剪加中 } |
效果如下:
3、 建立边框
通过以上的步骤我们已经实现简单的抓图功能了,但是我们会发现在网站中的大头贴除了能拍照外还有很多可供选择的漂亮边框,那么这些又是如何实现的呢?其 实原理还是一样,我们还是通过BitmapData .draw这个函数,只是对my_video这个Video对象做点手术。
操作:我们回到场景中选择my_video,点取菜单中的修改(F8)将my_video转换为影片剪辑。如图
现在我们重新给转换成的影片剪辑命名:video 如图
然后进入video影片剪辑里,新建图2,从库中将前面建立的空影片剪辑拉到场影中,所在位置与my_video相同,并命名为img.我们现在理解一下整个场景中影片剪辑的层次结构。如图
操作:根据结构我们调整一下代码:
将主场景中第一帧中my_video.attachVideo(myCamera);改为video.my_video.attachVideo(myCamera);运行后视频可以正常捕获
将抓取按钮中的myBitmap.draw(my_video);改为myBitmap.draw(video);运行后抓取图像正常
接下来我们就开始完成边框的构建。然后在主场景下建立一个输入文本,并将其命名imgs,然后创建一个按钮,并输入以下代码:
on (release) { video.img.loadMovie(imgs.text); } |
现在我们来测试一下:
测试时只需在边框地址栏处输入相对的路径即可变换边框。这里只是一个简单的换取边框,大家如果有兴趣可以做一个动态的边框系统。
备注:为了方便大家测试,边框下载地址为:http://www.yuso.cn/dtt/frame.rar.4、4、传递颜色参数
1) loadVars
含义:loadVars类可以将对象中所有变量发送到指定的 URL 中,并且可以将指定 URL 中的所有变量加载到某个对象中
对象的变量表现方式通过“。”实现,例如LoadVars.myName=“lanyang”;
2) loadVars.send(url, target, [method])
含义:将 loadVars对象中的变量发送到指定的 URL
参数:url 上载变量的目标地址
Target 将在其中出现任何响应的浏览器窗口或帧。您可输入特定窗口的名称,或从下面的保留目标名称中选择
_self: 指定当前窗口中的当前帧。
_blank:指定一个新窗口。
_parent:指定当前帧的父级。
_top:指定当前窗口中的*帧
Method HTTP 协议的 GET 或 POST 方法。默认值为 POST
2) BitmapData.getPixel(x, y)
含义:它表示特定点 (x, y) 上的 BitmapData 对象的 RGB 像素值
参数: x 像素x的位置
Y 像素y的位置
Flash在传递参数值是主要通过BitmapData创建一个位图,然后获取每个像素点的RGB值,并且存入loadVars对象中,传递给服务器。
操作:我们继续回到myCamera.fla文件中:
新建一个按钮用于传递变量,并在其中输入代码:
on (release) { var my_lv:LoadVars = new LoadVars();//创建loadVars对象 my_lv.pix="";//存储颜色值 my_lv.w=160;//存储宽度 my_lv.h=120;//存储高度 myBitmap = new flash.display.BitmapData(160,120); //创建BitmapData对象 myBitmap.draw(photo); //绘制photo for(j=0;j<120;j++) //获得每个象素点RGB值 { for(i=0;i<160;i++) { m=i*j; temp=myBitmap.getPixel(i, j).toString(16); //转换成16进制 my_lv.pix+=temp+","; } } my_lv.send("showpic.asp", "_blank", "POST"); } |
最后界面如下图;
二、 asp.net部分
这一部分主要针对asp.net的朋友,如果你对asp.net不感兴趣,可以直接跳过阅读下面的asp部分。
原理:通过Bitmap类根据接收过来的颜色值重新绘制成图片
1)Bitmap.setPixel(int x, int y, Color color)
含义:设置Bitmap中指定象素点的颜色
命名空间:System.drawing
参数: x 要设置的像素的 x 坐标。
y 要设置的像素的 y 坐标。
color Color 结构,它表示要分配给指定像素的颜色
2) Color.FromArgb(int argb)
含义:从一个 32 位 ARGB 值创建 Color 结构。
命名空间:System.drawing
参数:argb 指定 32 位 ARGB 值的值。
3) Convert.ToInt32(String value, Int32 fromBase)
含义:进制转换
命名空间:System
参数:value 包含数字的 String.
fromBase value 中数字的基数,它必须是 2、8、10 或 16.如果为16则value前可以加上"0x"或"0X"
备注:实现进制转换,value为包含数字的字符串,后面则为进制类型
4) Bitmap.Save (String filename, ImageFormat format)
含义:将此Bitmap以指定格式保存到指定文件。
命名空间:System.drawing
参数:filename 保存文件的文件名
Format 图像的图像格式,这里采用jpeg(ImageFormat.Jpeg)
根据以上各类方法的定义,我们采用setPixel设定Bitmap每象素点的颜色值,然后通过sava存为图片。下面请看代码:
建立showpic.aspx,在其cs文件中添加如下代码:
using System.Drawing; using System.Drawing.Imaging; public partial class showpic : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { int w = Convert.ToInt32(Request["w"]); //获得宽度 int h = Convert.ToInt32(Request["h"]); //获得高度 Bitmap myBitmap = new Bitmap(w,h); string cs = Request["pix"]; //获得颜色值 string[] c = cs.Split(','); for (int Ycount = 0; Ycount <h; Ycount++) { for (int Xcount = 0; Xcount < w; Xcount++) { myBitmap.SetPixel(Xcount,Ycount,Color.FromArgb(Convert.ToInt32("0X00"+c[Ycount *w + Xcount],16))); //设置象素点颜色 } } myBitmap.Save(Server.MapPath("s.jpg"), ImageFormat.Jpeg); //保存图片 Response.Write("<img src='s.jpg'>"); //显示图片 } } |
这样我们就可以将图片保存在服务器当前目录下,并且通过<img src=“……”>进行调用。
三、 Asp部分
Asp生成图片相对于asp.net比较复杂一点,由于没有现成的类或者函数调用,因此我们不得不先对BMP位图的结构作一个简单的介绍。以下BMP位图结构介绍来源于网络。
BMP位图由文件头、位图信息头、颜色信息和图形数据四部分组成。
1.文件头信息块0000-0001:文件标识,为字母ASCII码“BM”。
0002-0005:文件大小。
0006-0009:保留,每字节以“00”填写。
000A-000D:记录图像数据区的起始位置。各字节的信息依次含义为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。
2.图像描述信息块000E-0011:图像描述信息块的大小,常为28H. 0012-0015:图像宽度。
0016-0019:图像高度。
001A-001B:图像的plane总数(恒为1)。
001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。
001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)。
0022-0025:图像区数据的大小。
0026-0029:水平每米有多少像素,在设备无关位图(。DIB)中,每字节以00H填写。
002A-002D:垂直每米有多少像素,在设备无关位图(。DIB)中,每字节以00H填写。
002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。
3.颜色表
颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B (蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此 类推。
4.图像数据区颜色表
接下来位为位图文件的图像数据区,在此部分记录着每 点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1 字节);真彩色图像每点占24位(3字节)。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图 像高度*记录像素的位数)/8.然而,未压缩的图像信息区的大小。除了真彩色模式外,其余的均大于或等于数据信息的大小。这是为什么呢?原因有两个: 1.BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,设显示模式位16色,在每个字节 分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信 息。
2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。如果显示模式为16色,当图 像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽 为19时,每行也要补充4-19%4=1个字节。
还有一点我要申明,当屏幕初始化为16或256色模式时,一定要设置调色板或修正颜色值,否则无法得到正确的图像颜色。
源码如下:
<% w=request("w") '获得图像宽度 h=request("h") '获得图像高度 pix=request("pix") '获得颜色值 cs=split(pix,",") Function To3(nums) '将接收的16进制RGB格式转换并添加到图象数据区 Dim myArray() Dim iii, tmp For iii=1 To 3 tmp=Mid(nums,iii*2-1,2) Redim Preserve myArray(iii) myArray(iii) =chn10(tmp) Next To3 = ChrB(myArray(3))&ChrB(myArray(2))&ChrB(myArray(1)) End Function Function chn10(nums) '将16进制转换为10进制 Dim tmp, tmpstr, intLoop4 nums_len=Len(nums) For intLoop4=1 To nums_len tmp=Mid(nums,intLoop4,1) If IsNumeric(tmp) Then tmp=tmp * 16 * (16^(nums_len-intLoop4-1)) Else tmp=(ASC(UCase(tmp))-55) * (16^(nums_len-intLoop4)) End If tmpstr=tmpstr+tmp Next chn10 = tmpstr End Function Response.Expires = -9999 Response.AddHeader "cache-control","no-cache" '文件头开始 strHeadData=ChrB(66) & ChrB(77) '文件标识 strHeadData=strHeadData&ChrB(230) & ChrB(4) & ChrB(0) & ChrB(0) '文件大小 strHeadData=strHeadData & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) '保留,每字节以“00”填写 strHeadData=strHeadData&ChrB(54) & ChrB(0) & ChrB(0) & ChrB(0) '记录图像数据区的起始位置 strHeadData=strHeadData & ChrB(40) & ChrB(0) &ChrB(0) & ChrB(0) '图像描述信息块的大小 strHeadData =strHeadData &ChrB(w) & ChrB(0) & ChrB(0) & ChrB(0) '宽度 strHeadData =strHeadData & ChrB(h) & ChrB(0) & ChrB(0) & ChrB(0) '高度 strHeadData =strHeadData & ChrB(1) & ChrB(0) '图像的plane总数 strHeadData =strHeadData &ChrB(24) & ChrB(0) '图像的位数 strHeadData =strHeadData & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) '数据压缩方式 strHeadData =strHeadData &ChrB(176) & ChrB(4) & ChrB(0) & ChrB(0) '图像区数据的大小 strHeadData =strHeadData & ChrB(18) & ChrB(11) & ChrB(0) & ChrB(0) '水平每米有多少像素 strHeadData =strHeadData & ChrB(0) & ChrB(0) &ChrB(0) & ChrB(0) '垂直每米有多少像素 strHeadData =strHeadData & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) '此图像所用的颜色数 strHeadData =strHeadData & ChrB(0) & ChrB(0) & ChrB(0) & ChrB(0) '颜色表 '文件头结束 strMainData="" '数据区 for k=h-1 to 0 step -1 for j=0 to w-1 strMainData=strMainData&to3(cs(k*w+j)) next next strSaveData=strHeadData+strMainData Set Jpeg = Server.CreateObject("Persits.Jpeg") Jpeg.OpenBinary strSaveData Jpeg.Width = Jpeg.OriginalWidth Jpeg.Height = Jpeg.OriginalHeight Jpeg.Save Server.MapPath("aspimg.jpg") ' 保存缩略图到指定文件夹下 Set Jpeg = Nothing ' 注销实例 response.write("<img src='aspimg.jpg'>") %> |
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1828045