這次來幫一個常用的功能需求做一下作法筆記,就是「擷取 Flash 畫面上的某一區塊為圖檔」。
使用 ActionScript 3.0,後端程式本例做了兩種版本 PHP 與 C#.Net。
- 如範例檔,在畫面上安排兩個元件,用來放置欲擷取區塊的 previewMC,以及擷取鈕 capture_btn。
- previewMC 元件的影格配置如下:
as 其實只有擺 stop(); ,圖層 3 放了手寫的 “Hello World”,圖層 1 放了四張不同底色的色塊。
- 再來是最主要的部份,主場景上的 ActionScript:
stop();
import com.adobe.images.JPGEncoder;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.text.TextField;
import flash.utils.ByteArray;
// 網站URL
var siteaddress:String = "http://www.yoursite.com.tw/";
var uploadimage:String = "";
// ==========================================================================
// 擷取鈕 [開始]
// ==========================================================================
capture_btn.buttonMode = true;
capture_btn.addEventListener(MouseEvent.CLICK, previewPic);
function previewPic(e:MouseEvent) {
// 處理縮圖、儲存圖檔的伺服器端程式
var _uploadPath:String = MovieClip(root).siteaddress + "_Process/capture.ashx?cachebuster="+ new Date().getTime();
// 圖的長寬
var image:BitmapData=new BitmapData(180,180);
// Draw the button into the BitmapData
// 將 previewMC 的範圍擷取下來
image.draw(previewMC);
// Encode the BitmapData into a ByteArray
var enc:JPGEncoder=new JPGEncoder(100);
var bytes:ByteArray=enc.encode(image);
// and convert the ByteArray to a Base64 encoded string
var base64Bytes:String=Base64.encodeByteArray(bytes);
// Add the string to a URLVariables object
var vars:URLVariables = new URLVariables();
vars.imageData=base64Bytes;
// and send it over the wire via HTTP POST
var url:URLRequest=new URLRequest(_uploadPath);
url.data=vars;
url.method=URLRequestMethod.POST;
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, upload_completeHandler);
loader.addEventListener(IOErrorEvent.IO_ERROR, upload_errorHandler);
loader.load(url);
}
function upload_completeHandler(e:Event):void {
trace("上傳成功");
trace(e.target.data);
}
function upload_errorHandler(e:Event):void {
trace("error.....");
}
// ==========================================================================
// 擷取鈕 [結束]
// ==========================================================================
// 點擊 previewMC 會循環變色
previewMC.buttonMode = true;
previewMC.addEventListener(MouseEvent.CLICK, changeColor);
function changeColor(e:MouseEvent):void {
if(previewMC.currentFrame==4){
previewMC.gotoAndStop(1);
} else {
if(previewMC.currentFrame<5){
previewMC.nextFrame();
}
}
};
在這邊會用上 adobe 函式庫 的 JPGEncoder,可在這邊下載 as3corelib。
另外,在此我們會使用 Base64 方式將圖片編碼,而 Base64.as 可以自 as3crypto 的 Google Code 專案中取得。
其中請自行設定網址URL,以及處理擷取畫面的後端程式檔案名稱喔。
- 再來後端部分,先貼 C#.Net 部分。
<%@ WebHandler Language="C#" Class="upload" %>
using System;
using System.Web;
using System.IO;
using System.Drawing;
public class upload : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
string b64 = (string.Empty + System.Web.HttpContext.Current.Request["imageData"]).Trim();
Image img = Base64ToImage(b64);
string _saveMapPath;
// 縮圖放置的路徑
_saveMapPath = context.Server.MapPath("~/original");
string _extensionName = ".jpg";
string _newFileName = getTimeToString() + _extensionName;
do
{
if (FileExists(_saveMapPath + "/" + _newFileName))
{
_newFileName = getTimeToString() + _extensionName;
}
else
{
break;
}
} while (true);
UploadImage(img, 180, 180, _saveMapPath + "/" + _newFileName);
context.Response.Write(_newFileName);
context.Response.End();
}
public Image Base64ToImage(string base64String)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
MemoryStream ms = new MemoryStream(imageBytes, 0,
imageBytes.Length);
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
Image image = Image.FromStream(ms, true);
return image;
}
private string getTimeToString() {
DateTime _d = DateTime.Now;
return _d.Year + "_" + _d.Month + "_" + _d.Day + "_" + _d.Hour + "_" + _d.Minute + "_" + _d.Second + "_" + _d.Millisecond;
}
public bool FileExists(string FileFullPath)
{
FileInfo f = new FileInfo(FileFullPath);
return f.Exists;
}
public bool IsReusable {
get {
return false;
}
}
#region 固定模版裁剪並縮放
///
/// 上傳圖片(以Post方式獲取源文件)
/// 按模版比例最大範圍的裁剪圖片並縮放至模版尺寸
///
/// 原圖HttpPostedFile對象
/// 模版寬(單位:px)
/// 模版高(單位:px)
/// 保存路徑
public static void UploadImage(System.Drawing.Image img, int templateWidth, int templateHeight, string fileSaveUrl)
{
//從文件獲取原始圖片,並使用流中嵌入的顏色管理信息
//System.Drawing.Image initImage = System.Drawing.Image.FromStream(postedFile.InputStream, true);
System.Drawing.Image initImage = img;
//原圖寬高均小於模版,不作處理,直接保存
if (initImage.Width <= templateWidth && initImage.Height <= templateHeight)
{
initImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg);
}
else
{
//模版的寬高比例
double templateRate = double.Parse(templateWidth.ToString()) / templateHeight;
//原圖片的寬高比例
double initRate = double.Parse(initImage.Width.ToString()) / initImage.Height;
//原圖與模版比例相等,直接縮放
if (templateRate == initRate)
{
//按模版大小生成最終圖片
System.Drawing.Image templateImage = new System.Drawing.Bitmap(templateWidth, templateHeight);
System.Drawing.Graphics templateG = System.Drawing.Graphics.FromImage(templateImage);
templateG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
templateG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
templateG.Clear(Color.White);
templateG.DrawImage(initImage, new System.Drawing.Rectangle(0, 0, templateWidth, templateHeight), new System.Drawing.Rectangle(0, 0, initImage.Width, initImage.Height), System.Drawing.GraphicsUnit.Pixel);
templateImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg);
}
//原圖與模版比例不等,裁剪後縮放
else
{
//裁剪對象
System.Drawing.Image pickedImage = null;
System.Drawing.Graphics pickedG = null;
//定位
Rectangle fromR = new Rectangle(0, 0, 0, 0);//原圖裁剪定位
Rectangle toR = new Rectangle(0, 0, 0, 0);//目標定位
//寬為標準進行裁剪
if (templateRate > initRate)
{
//裁剪對象實例化
pickedImage = new System.Drawing.Bitmap(initImage.Width, int.Parse(Math.Floor(initImage.Width / templateRate).ToString()));
pickedG = System.Drawing.Graphics.FromImage(pickedImage);
//裁剪源定位
fromR.X = 0;
fromR.Y = int.Parse(Math.Floor((initImage.Height - initImage.Width / templateRate) / 2).ToString());
fromR.Width = initImage.Width;
fromR.Height = int.Parse(Math.Floor(initImage.Width / templateRate).ToString());
//裁剪目標定位
toR.X = 0;
toR.Y = 0;
toR.Width = initImage.Width;
toR.Height = int.Parse(Math.Floor(initImage.Width / templateRate).ToString());
}
//高為標準進行裁剪
else
{
pickedImage = new System.Drawing.Bitmap(int.Parse(Math.Floor(initImage.Height * templateRate).ToString()), initImage.Height);
pickedG = System.Drawing.Graphics.FromImage(pickedImage);
fromR.X = int.Parse(Math.Floor((initImage.Width - initImage.Height * templateRate) / 2).ToString());
fromR.Y = 0;
fromR.Width = int.Parse(Math.Floor(initImage.Height * templateRate).ToString());
fromR.Height = initImage.Height;
toR.X = 0;
toR.Y = 0;
toR.Width = int.Parse(Math.Floor(initImage.Height * templateRate).ToString());
toR.Height = initImage.Height;
}
//設置質量
pickedG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
pickedG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//裁剪
pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel);
//按模版大小生成最終圖片
System.Drawing.Image templateImage = new System.Drawing.Bitmap(templateWidth, templateHeight);
System.Drawing.Graphics templateG = System.Drawing.Graphics.FromImage(templateImage);
templateG.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
templateG.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
templateG.Clear(Color.White);
templateG.DrawImage(pickedImage, new System.Drawing.Rectangle(0, 0, templateWidth, templateHeight), new System.Drawing.Rectangle(0, 0, pickedImage.Width, pickedImage.Height), System.Drawing.GraphicsUnit.Pixel);
templateImage.Save(fileSaveUrl, System.Drawing.Imaging.ImageFormat.Jpeg);
//釋放資源
templateG.Dispose();
templateImage.Dispose();
pickedG.Dispose();
pickedImage.Dispose();
}
}
//釋放資源
initImage.Dispose();
}
#endregion
}
- 再來是 PHP 版本,這個就沒做縮圖了。
<?php
require_once("JSON.php");
$errors = "";
$imageData = @$_POST['imageData'];
function base64_to_jpeg( $inputfile, $outputfile ) {
/* encode & write data (binary) */
$ifp = fopen( 'original/' . $outputfile, "wb" );
fwrite( $ifp, base64_decode( $inputfile ) );
fclose( $ifp );
/* return output filename */
return( $outputfile );
}
function getRandomFileName() {
return date('ymdhis').rand(100, 999) . '.' . 'jpg';
}
if( $imageData != "" ) {
$data = array(
'result' => 'Y',
'thumb' => base64_to_jpeg($imageData, getRandomFileName())
);
$json = new Services_JSON();
echo $json->encode($data);
exit();
} else {
$data = array(
'result' => 'Y',
'error' => 'no file'
);
$json = new Services_JSON();
echo $json->encode($data);
exit();
}
?>
大致就是醬子啦。
我的環境是 AS 2.0 ,後端是 ASP ,
如此舊的組合,有辦法達到相同的功能嗎?
如果無法從flash 內部來啟動這個擷圖,
是否其它solution ?
謝謝您!
我曾看過一個 AS 2.0 搭配 PHP 的截圖範例,您可參考看看:
http://sephiroth.it/tutorials/flashPHP/print_screen/index.php
您好,
我依您的方式製作,使用的是PHP做後端,但不成功。
您的範例檔連結已失效,可否更新,讓後進可以學習。
感恩。
補檔於此
https://nofile.io/f/4fScXzDb21h/AS3_capture.zip