忍者ブログ
[29]  [28]  [27]  [26]  [25]  [24]  [23]  [22]  [21]  [20]  [19
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

まず、コードが見づらいので google-code-prettify を導入。

ちょっと長くなります。
まずオリジナルのJPGEncoderから。ソースはここから引用。

// Encode 8x8 macroblocks
var DCY:Number=0;
var DCU:Number=0;
var DCV:Number=0;
bytenew=0;
bytepos=7;
for (var ypos:int=0; ypos<image.height; ypos+=8) {
	for (var xpos:int=0; xpos<image.width; xpos+=8) {
		RGB2YUV(image, xpos, ypos);
		DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
		DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
		DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
	}
}
この部分がどうやらencode()で一番時間を喰っているらし。全画素を8x8のブロックに分割して、まあ離散フーリエか何かの変換処理をしているらしい。
なので、この処理をencode()から追い出して、タイマイベント内でループさせることにしました。まずあ、新しいエンコーダクラスにはIEventDispatcherを実装させます。一定回数ループを回したら、一旦タイマイベントを終了させてProgressEventをDispatchさせるようにしたいと思います。 まず上のforループの代わりにencodeは変数を初期化、タイマーを起動して自身は終了させます。
_progress=0;
_pw = int(_image.width +7) >>> 3 ; //x方向のブロック数
_ph = int(_image.height +7) >>> 3 ; //y方向の同
_total=_pw * _ph; //8x8のブロックがいくつあるか
_period = 1 << int(Math.log(_total) / Math.LN2); //_totalを超えない最大の2の冪乗を求め
_period = _period > 0xff ? ( _period >>> 8) - 1 : 0; //256で割って1引く → 2進表現で全て1に
//ここでタイマーを開始する
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
_periodは進捗イベントの条件式に使用する値で、条件文をビット演算で行うために(ループ毎に実行されるため)上記のような妙な値を入れています。 次にタイマイベント。
// Encode 8x8 macroblocks
private function timerHandler(e:TimerEvent):void{
	var ypos:int = int(_progress / _pw) << 3;
	var xpos:int = (_progress % _pw) << 3;
	while (true) {
		RGB2YUV(_image, xpos, ypos);
		_DCY = processDU(YDU, fdtbl_Y, _DCY, YDC_HT, YAC_HT);
		_DCU = processDU(UDU, fdtbl_UV, _DCU, UVDC_HT, UVAC_HT);
		_DCV = processDU(VDU, fdtbl_UV, _DCV, UVDC_HT, UVAC_HT);
		_progress++;
		//x位置移動
		xpos =  int(_progress % _pw) << 3;
		//xが一周したらy位置移動
		if (xpos==0) ypos =  int(_progress / _pw) <<3;
		
		//最後までいったら
		if(_progress == _total){
			//タイマーを停止させて
			timer.stop();
			timer.removeEventListener(TimerEvent.TIMER, timerHandler);
			//completeイベント送って
			dispatcher.dispatchEvent(new Event(Event.COMPLETE));
			// Do the bit alignment of the EOI marker
			if ( bytepos >= 0 ) {
					var fillbits:BitString = new BitString();
					fillbits.len = bytepos+1;
					fillbits.val = (1<<(bytepos+1))-1;
					writeBits(fillbits);
			}
			writeWord(0xFFD9); //EOI
			break;
		} else if ( (_progress & _period) == 0) { //一定の回数ループさせたら 
			//progressイベントを送って
			dispatcher.dispatchEvent(
				new ProgressEvent(
					ProgressEvent.PROGRESS, false, false, _progress, _total
			));
			//次回のタイマーイベントに続く
			break;
		}
	}
}
こんな感じで、めでたく進捗を取得出来るようになりました。encode()自体はByteArrayを返さなくなるので、呼び出し側のクラス内でコンプリートイベントのメソッド内でByteArrayを取得する必要があります。なのでゲッタも追加しました。
//コンプリートを確認したらゲッタからbyteArrayを取得する
public function get byteArray():ByteArray { 
	return byteout;
}
PR
この記事にコメントする
お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字
この記事へのトラックバック
この記事にトラックバックする:
26歳のハローワールド
カレンダー
06 2025/07 08
S M T W T F S
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
最新コメント
[11/27 gyzwviyehl]
[11/18 Tepexaxyonelo]
[09/12 gomFolley]
[08/16 CypeBachCoece]
[06/02 gb]
[03/06 kishima]
[01/18 KNDY]
[01/16 kage]
[12/23 KNDY]
[12/23 kage]
最新トラックバック
ブログ内検索
アクセス解析
プロフィール
HN:
knd
HP:
自己紹介:
絶賛迷走中。
UNIQLO CALENDAR
忍者ブログ [PR]