Flex3 バイキュービック法 解説編

バイキュービック法の解説編


この記事の続きです


Blogのフォーマットがあんまりよくないですね。
領域がせまくてソースコードが綺麗に表示できないzzz


重み付けの関数


まずは重みつけの関数から解説です。


関数名:bicubicWeightCalc


引数:distance:Number


目的:引数に応じた重みを計算する


下の画像の青い点が
var targetX:Number = Number(x) / changeScaleX
var targetY:Number = Number(y) / changeScaleY
の結果である拡縮前画像の位置です。
この青い点からどれくらい離れているのかが引数distanceになります。
blog-56-01.png


一番左側のX座標を0とし、青い点のX座標をtargetXとして、仮に1.3という数値とすると
距離distanceは| 1.3 - 0 | = 1.3になります。


距離が2以上離れている場合には、重み付けは0となり、変換後の色には反映されません。


今回は距離が1以上2未満なので、距離に応じた重み付けがされます


具体的には以下のような重みつけです。



// 距離が0以上1.0未満の場合の重み計算
if ( distance < 1.0 )
{
weight = 1 + ( a + 1.0 ) * d3p - ( a + 3.0 ) * d2p;
}// 距離が1.0以上2.0未満の場合の重み計算
else if ( distance < 2.0 )
{
weight = a * d3p - 5.0 * a * d2p + 8.0 * a * distance - 4.0 * a;
}
else
weight = 0.0;

ここで、d3pはdistanceの3乗を示し、d2pはdistanceの2乗を示しています。
また、aは定数項で、今回はよく使用される-1を設定してあります。
綺麗にいかない場合などはここをいじればどうにかなるかもしれません。


バイキュービック法の本体


関数名:bicubic


引数:targetBitmapData


widthSize


heightSize


isCalcAlpha


目的:バイキュービック法でtargetBitmapDataをwidthSize*heightSizeのBitmapDataオブジェクトに変換する


変換元となる画像はBitmapData型として渡します。
※JavaではBufferedImage型とかかな?


変換後の縦サイズはheightSize、横サイズはwidthSizeとします。


isCalcAlphaは未実装ですw
PNG画像を持ってきた際に、アルファ値も計算できるようにつけてあるだけです。
いれたら、処理が重くなったので、アルファ値計算しないようにしました。


処理フロー



  • 中身が空であるwidthSize*heightSizeのBitmapDataオブジェクトを作成します。

  • このBitmapDataオブジェクトの全てのピクセルに色を設定します
    ※for(var y...)とfor(var x...)の部分

  • ある箇所(x,y)の座標に色を設定する際には、元画像と変換後画像との比率から中心となる元画像の座標を計算します。



// 比率の計算箇所
var changeScaleX:Number = widthSize / targetBitmapData.width;
var changeScaleY:Number = heightSize / targetBitmapData.height;

... 省略 ...
// 変換後の画素位置に対応する元画像の位置の計算箇所
var targetX:Number = Number(x) / changeScaleX;
var targetY:Number = Number(y) / changeScaleY;

ixとiyを使用しているfor文が周囲の画素を調べている箇所です。
ix,iyのループの初期値はint(targetX[Y]) - 1です。
つまり、元画像の計算の中心となる箇所の1マス左側から調べ始めます。


もし、調査する範囲を4×4より広くしたければ、このfor文のint(targetX -1)の[-1]を変化させてください。(終了条件のint(targetX) + 2のところでも可)


あとは先程の重み付けの計算をする関数で重みを計算し、(ix,iy)の画素データの各色に重みを掛けてあげて、16ピクセル全てを合計します。


最後に合計してできた各色のデータを重みの合計で割ってあげれば、埋め込む色データの感性です。
該当箇所は以下のところです。



// 各色に重みを掛けている箇所
red += ( Number( color & 0x00ff0000 ) >> 16 ) * weight;
green += ( Number( color & 0x0000ff00 ) >> 8 ) * weight;
blue += ( Number( color & 0x000000ff ) ) * weight;

// できた色を重みの合計で割っている箇所
red /= totalWeight;
green /= totalWeight;
blue /= totalWeight;

ここで、colorは変換前の画像の(ix,iy)の位置の画素データです。
マスクを掛けた後にビットシフトして重みを掛けています


また、weightはX方向重みweightXとY方向重みweightYの積です。


こんなとこかなぁ…
処理速度が遅いのはまたなんとかしよう...

スポンサーサイト

Flex3 バイキュービック法の実装

バイキュービック法の実装


バイキュービック法を作ってみようと思ったので作ってみた。
正直、遅いしあんまきれいにいかない。
とりあえず、今回はソースコードだけ


正直長い...
簡単に解説すると、元画像の周囲16ピクセルを重みをつけて平均しちゃおう方式です。
変換後画像1ピクセルにつき16ピクセルの計算が必要になるため、単純計算で幅×高さ×16回の計算が必要になります。
速度を向上させるにはどれだけ少ない計算回数にできるか、浮動小数点計算を減らせるかが鍵です。詳しい解説はまた今度!


ソースのダウンロードは下から(utf8エンコード)です
バイキュービック法(txtファイルです)


久しぶりのまともな更新(・w・


bicubicのソースコード(AS3版)


public static function bicubic(targetBitmapData:BitmapData, widthSize:int,heightSize:int,isCalcAlpha:Boolean = false):BitmapData 
{
// 変更後のオブジェクトの生成
var newBitmapData:BitmapData = new BitmapData(widthSize, heightSize);

/**
* バイキュービック法で拡大・縮小を行う
*/
// 色の計算用
var alpha:Number;
var red:Number;
var green:Number;
var blue:Number;

// 重みの和を保持する変数
var totalWeight:Number;

// 高さ・幅の比率を取得
var changeScaleX:Number = widthSize / targetBitmapData.width;
var changeScaleY:Number = heightSize / targetBitmapData.height;
//trace("ScaleX : " + changeScaleX + " ScaleY : " + changeScaleY );

// 作成した新たなBitmapDataの全てのピクセルを
// 元データからピクセルを取り出して埋める
for (var y:int = 0; y < heightSize; y++) // Heightのループ
{
for (var x:int = 0; x < widthSize; x++) // Widthのループ
{
// init
// 各種変数の初期化
totalWeight = 0.0;
alpha = red = green = blue = 0.0;

if (!isCalcAlpha) alpha = 0xff000000;
// 設置したいピクセル(x,y)に対応する元画像の座標を計算する
// ※この時点では、存在しない座標
var targetX:Number = Number(x) / changeScaleX;
var targetY:Number = Number(y) / changeScaleY;

// 元画像の周囲の画素を調べる
// ix:targetXの周囲のX座標(このixは存在する座標になる)
// iy:targetYの周囲のY座標(このiyは存在する座標になる)
for (var iy:int = int(targetY) - 1; iy <= int(targetY) + 2; iy++)
{
for ( var ix:int = int(targetX) - 1; ix <= int(targetX) + 2; ix++)
{
// ixとiyが元画像の外枠からはみ出ていない場合に処理をする
if (ix >= 0 && iy >= 0 &&
ix < targetBitmapData.width &&
iy < targetBitmapData.height)
{
// 重みの計算
var weightX:Number = bicubicWeightCalc( ix - targetX );
var weightY:Number = bicubicWeightCalc( iy - targetY );
var weight:Number = weightX * weightY;

// totalWeightに加算
totalWeight += weight;

// RGB各色に重みを掛けて加算する
var color:uint = targetBitmapData.getPixel32(ix, iy);
// RGBマスクを掛けて色を取り出し、重みを掛ける
//if (isCalcAlpha)
//alpha += ( Number( color & 0xff000000 ) >> 24 ) * weight;
red += ( Number( color & 0x00ff0000 ) >> 16 ) * weight;
green += ( Number( color & 0x0000ff00 ) >> 8 ) * weight;
blue += ( Number( color & 0x000000ff ) ) * weight;
}
}
}

//if (isCalcAlpha)
//alpha /= totalWeight;

red /= totalWeight;
green /= totalWeight;
blue /= totalWeight;

// 埋め込む色の作成
// ARGBそれぞれをbitシフト後にマスクを掛けて加算して作成
var setColor:uint;

//if (isCalcAlpha) setColor = (uint(alpha) << 24) & 0xff000000;
//else setColor = 0xff000000;
setColor = ( uint(red ) & 0x000000ff ) << 16;
setColor += ( uint(green) & 0x000000ff ) << 8;
setColor += ( uint(blue ) & 0x000000ff );

// 色を埋め込む
newBitmapData.setPixel( x, y, setColor);
}
}

return newBitmapData;

}

関数名:bicubicWeightCalc(重み計算関数)


private static function bicubicWeightCalc(distance:Number):Number 
{
var weight:Number; // 重み
var a:Number = -1; // 重み定数 必要に応じて変化させてください

var d3p:Number = Math.pow(distance, 3.0);
var d2p:Number = Math.pow(distance, 2.0);

// 引数distanceが負ならば、正にする
if ( distance < 0 ) distance *= -1;

if ( distance < 1.0 ) // 距離が0以上1.0未満の場合の重み計算
weight = 1 + ( a + 1.0 ) * d3p - ( a + 3.0 ) * d2p;
else if ( distance < 2.0 ) // 距離が1.0以上2.0未満の場合の重み計算
weight = a * d3p - 5.0 * a * d2p + 8.0 * a * distance - 4.0 * a;
else
weight = 0.0;

return weight;
}

Flex3 Flash画像表示ソフト その1

Flex3で作る画像表示ソフト


よくあるソフトです。
XMLに画像のパスやタイトルを設定し、その画像を1枚ずつ読み込むソフトです。


動作はこちらからどうぞ→Flash置き場
なお、ソースコード、設定用XMLファイル、SWF本体全て落とせます。


※本ソフトにおいて生じたいかなる損害も補償しません。


目指すもの


自分もたまに見るのですが、Web漫画など画像をそのままおいてあるサイトを良く見かけます。
画面の更新をすると次のページを見ることが出来るのですが、画面全体を更新することになるので、
読込時間が長くてちょっとイライラしましたので、フリーで画像を表示できるソフトを作ってみようかなと思って作ってみました。


まだ、未対応ですが、configにあるように、アプリケーションのスタイル設定や、許可した画像をローカルに保存する機能とかをつけてみようかなと思っています。


他にも何か要望があれば、可能な限りつけてみますので、是非コメント欄でお知らせ下さい。


現在のバグ


横向き画像はちゃんとフィットして表示できるが、縦向きの画像がはみ出る。


画像の切り替えのときに連打するとエラーがでる


使い方


FlashVarsとしてConfigファイルへのパスを設定してからFlashを埋め込む


私は設定がめんどくさいので今回はswfobject.js(ver2.1)を利用しました
GoogleCodeから落とせます



<script src="js/swfobject.js" type="text/javascript">
<script type="text/javascript">
var flashvars = {
target: "http://namakesugi.web.fc2.com/swf/PictureViewer/PictureViewer-config"
};
var params = {
menu: "false",
scale: "noScale",
allowFullscreen: "true",
allowScriptAccess: "always",
bgcolor: "#FFFFFF"
};
var attributes = {
id:"PictureViewer"
};
swfobject.embedSWF("../swf/PictureViewer/PictureViewer_01.swf",
"altContent", "100%", "100%", "9.0.0", "expressInstall.swf", flashvars, params, attributes);
</script>
</head>
<body>
<!-- その他色々 -->
<div id="altContents">
</div>

head上で埋め込むFlashの設定をして、body内のid=altContentsに表示させます
altContentsはembedSWF()の第2引数に指定した値と一致していればいいので、違うのでも大丈夫です。
また、flashvarsの中にtargetという変数名で、configファイルへのパスを入力すれば、そのファイルを読みに行きます


かなり適当な説明ですが、勘弁してください。


実装されている機能


  • 読込対象の画像パスが指定されたconfigファイルをFlashVarsで切り替えることが出来る
    SWF1つでconfigファイルを複数用意することで、様々なパターンの画像を表示することができる

  • 画像を初期化時に全て読み込むのではなく、必要なときに読み込む
    ただし、既に読み込まれている場合には再度読み込まない

  • 表示されている画像の切り替えは画像横のスペースにマウスをポイントする
    移動することができれば、三角が表示される
    ※一応三角の色は自由に設定できるように作成してある

最後に


中途半端、リファクタリングしていない状態での公開となります
参考までにどうぞ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。