画像変形処理の練習
/**
* Copyright termat ( http://wonderfl.net/user/termat )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xGI8
*/
package
{
import flash.display.Sprite;
import flash.events.Event;
import com.bit101.components.*;
[SWF(width = "480", height = "480", backgroundColor = "0xffffff",frameRate="60")]
public class Practice53 extends Sprite {
private var canvas:Canvas;
public function Practice53() {
canvas = new Canvas();
canvas.x = 40;
canvas.y = 40;
addChild(canvas);
var prob1 : RadioButton = new RadioButton(this, 10, 5, "Source", true, function(e:Event):void { canvas.setSource(); } );
var prob2 : RadioButton = new RadioButton(this, 70, 5, "Corn", false, function(e:Event):void { canvas.setCorn(); } );
var prob3 : RadioButton = new RadioButton(this, 130, 5, "Sphere", false, function(e:Event):void { canvas.setSphere(); } );
var prob4 : RadioButton = new RadioButton(this, 190, 5, "Cyrinder", false, function(e:Event):void { canvas.setCyrinder(); } );
var prob5 : RadioButton = new RadioButton(this, 250, 5, "Fan", false, function(e:Event):void { canvas.setFan(); } );
}
}
}
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.MovieClip;
class Canvas extends MovieClip {
private var bmp:BitmapData;
private var img:Bitmap;
private var trans:TransformImage;
public function Canvas():void {
trans = new TransformImage();
bmp = new BitmapData(400, 400, false, 0xffffff);
drawBase();
img = new Bitmap(bmp);
addChild(img);
}
public function setSource():void {
img.bitmapData = bmp;
}
public function setFan():void {
img.bitmapData = trans.fanMapping(bmp, bmp.width, bmp.height, 0xffffff, false, 200, 400, 0, 100, 0.2);
}
public function setSphere():void {
img.bitmapData = trans.circleMapping(bmp, bmp.width, bmp.height, 0xffffff, false);
}
public function setCyrinder():void {
img.bitmapData = trans.cylinderMapping(bmp, bmp.width, bmp.height, 0xffffff, false);
}
public function setCorn():void {
img.bitmapData = trans.coneMapping(bmp, bmp.width, bmp.height, 0xffffff, false);
}
private function drawBase():void {
var i:int = 0;
bmp.fillRect(bmp.rect,0xffffff);
for (var x:int = 1; x <= bmp.width; x++) {
for (var y:int = 0; y <= bmp.height; y++) {
if (i % 2 == 0) bmp.setPixel(x-1, y, 0x0000ff);
}
if (x % 10 == 0) i++;
}
}
}
class TransformImage {
public function fanMapping(bmp:BitmapData, width:int, height:int, bcol:uint, t:Boolean,ox:int,oy:int,xx:int,yy:int,rate_r:Number):BitmapData {
var ret:BitmapData = new BitmapData(width, height, t, bcol);
var th:Number,r:Number;
var rx1:int = 0, ry1:int = 0;
var rx2:int = bmp.width - 1;
var ry2:int = bmp.height - 1;
var x1:int = xx, y1:int = yy;
var x2:int = ox + (ox - xx);
var y2:int = yy, x3:int = ox, y3:int = oy;
var rrr:Number = getR(x1, y1, ox, oy);
var th1:Number = getAngleP(x1, y1, ox, oy);
var th2:Number = getAngleP(x2, y2, ox, oy);
var sx:int = Math.min(x1, x2, x3);
var sy:int = Math.min(y1, y2, y3);
var ex:int = Math.max(x1, x2, x3);
var ey:int = Math.max(y1, y2, y3);
var tth2:Number, th_rate:Number;
if (th2 < th1) {
tth2 = th2 + (Math.PI * 2);
}else {
tth2 = th2;
}
th_rate = tth2 - th1;
if (th1 < 0 && tth2 > 0)sy = y3 - (rrr + 0.9);
if (tth2 > Math.PI * 2.0)sy = y3 - (rrr + 0.9);
if (th1 < (Math.PI / 2.0) && tth2 > (Math.PI / 2.0))ex = x3 + (rrr + 0.9);
if (tth2 > (Math.PI * 5.0 / 2.0)) ex = x3 + (rrr + 0.9);
if (th1 < Math.PI && tth2 > Math.PI)ey = y3 + (rrr + 0.9);
if (tth2 > Math.PI) ey = y3 + (rrr + 0.9);
if (th1 < -(Math.PI / 2.0) && tth2 > -(Math.PI / 2.0))sx = x3 - (rrr + 0.9);
if (tth2 > (Math.PI * 3.0 / 2.0)) sx = x3 - (rrr + 0.9);
var w1:int = (rx2 - rx1 + 1);
var h1:int = (ry2 - ry1 + 1);
for (var y:int = sy; y <= ey; y++) {
for (var x:int = sx; x <= ex; x++) {
th = getAngle((x - x3), (y - y3));
if ((th1 > 0.0 || tth2 > 0.0) && th < th1) th += (Math.PI * 2);
th -= th1;
th /= th_rate;
r = getR(x, y, ox, oy);
r /= rrr;
r -= rate_r;
r /= (1.0 - rate_r);
var fx:Number = th * w1 + rx1;
var fy:Number = (1.0 - r) * h1 + ry1;
var col:uint = interpolate(bmp, fx, fy);
if (col != 0) {
ret.setPixel(x, y,col);
}else {
ret.setPixel(x, y, bcol);
}
}
}
return ret;
}
private function getAngle(dx:Number, dy:Number):Number {
var th:Number;
if(dy==0.0) {
if(dx<0.0){
th = -Math.PI / 2.0;
}else{
th = Math.PI / 2.0;
}
}else {
th = Math.atan(dx / -dy);
if (dy > 0.0) {
if (dx == 0.0) th = Math.PI;
if (dx < 0.0) th = th - Math.PI;
if (dx > 0.0) th = th + Math.PI;
}
}
return th;
}
private function getAngleP(x1:int, y1:int, ox:int, oy:int):Number {
var dx:Number = (x1 - ox);
var dy:Number = (y1 - oy);
return getAngle(dx,dy);
}
private function getR(x:int,y:int,x1:int,y1:int):Number{
var dx:Number = (x - x1);
var dy:Number = (y - y1);
return Math.sqrt(dx * dx + dy * dy);
}
public function circleMapping(bmp:BitmapData, width:int, height:int, bcol:uint, t:Boolean):BitmapData {
var ret:BitmapData = new BitmapData(width, height, t, bcol);
var theta:Number;
var x1:int = 0;
var y1:int = 0;
var x2:int = width - 1;
var y2:int = height - 1;
var rx1:int = 0;
var ry1:int = 0;
var rx2:int = bmp.width - 1;
var ry2:int = bmp.height - 1;
var tx1:Number = x1;
var ty1:Number = y1;
var tx2:Number = x2;
var ty2:Number = y2;
var aa:Number = (ty2 - ty1) / 2.0;
var a2:Number = aa * aa;
var bb:Number = (tx2 - tx1) / 2.0;
var cc:Number = (ry2 - ry1) / 2.0;
var dd:Number = (rx2 - rx1) / 2.0;
var toy:Number = (ty2 + ty1) / 2.0;
var tox:Number = (tx2 + tx1) / 2.0;
var foy:Number = ((ry2 + ry1)) / 2.0;
var fox:Number = ((rx2 + rx1)) / 2.0;
for (var y:int = y1; y <= y2; y++) {
for (var x:int = x1; x <= x2; x++) {
var xx:Number = aa * (x - tox) / bb;
var yy:Number = y - toy;
var rr:Number = Math.sqrt(xx * xx + yy * yy);
if (rr <= aa) {
var vx:Number = getVorg(yy, xx, aa);
var vy:Number = getVorg(xx, yy, aa);
var fx:Number = vx * dd + fox;
var fy:Number = vy * cc + foy;
ret.setPixel(x, y, interpolate(bmp, fx, fy));
}else {
ret.setPixel(x,y,bcol);
}
}
}
return ret;
}
private function getVorg(x:Number,y:Number,r:Number):Number{
if(y==0.0) {
vy=0.0;
}else {
var rt:Number=(r*r-x*x)/(y*y);
var vy:Number=1.0/Math.sqrt(rt);
if(y<0.0) vy= -vy;
}
return vy;
}
public function cylinderMapping(bmp:BitmapData, width:int, height:int, bcol:uint, t:Boolean):BitmapData {
var ret:BitmapData = new BitmapData(width, height, t, bcol);
var theta:Number;
var x1:int = 0;
var y1:int = 0;
var x2:int = ret.width - 1;
var y2:int = ret.height - 1;
var rx1:int = 0;
var ry1:int = 0;
var rx2:int = bmp.width - 1;
var ry2:int = bmp.height - 1;
var w1:int = rx2 - rx1 + 1;
var h1:int = ry2 - ry1 + 1;
var w2:int = x2 - x1 + 1;
var h2:int = y2 - y1 + 1;
var ro:Number = w2 / 2.0;
for (var y:int = y1; y <= y2; y++) {
for (var x:int = x1; x <= x2; x++) {
var ww:Number = (x - x1);
if(ro-ww != 0.0){
theta=Math.atan(Math.sqrt(2.0*ro*ww-ww*ww)/(ro-ww));
}else {
theta = Math.PI / 2.0;
}
if(theta<0.0) theta +=Math.PI;
var fx:Number = (theta * w1) / Math.PI + rx1;
var fy:Number = (y - y1) * h1 / h2 + ry1;
ret.setPixel(x, y, interpolate(bmp, fx, fy));
}
}
return ret;
}
public function coneMapping(bmp:BitmapData, width:int, height:int, bcol:uint, t:Boolean):BitmapData {
var ret:BitmapData = new BitmapData(width, height, t, bcol);
var theta:Number;
var x1:int=0;
var y1:int=0;
var x2:int = width - 1;
var y2:int = height - 1;
var rx1:int=0;
var ry1:int=0;
var rx2:int = bmp.width - 1;
var ry2:int = bmp.height - 1;
var w1:int = rx2 - rx1 + 1;
var h1:int = ry2 - ry1 + 1;
var w2:int = x2 - x1 + 1;
var h2:int = y2 - y1 + 1;
var wh:Number = w2 / 2.0;
for (var y:int = y1; y <= y2; y++) {
var ro:Number = (y - y1) / h2 * wh;
var xs:int = (wh - ro) + x1;
var xe:int = (wh + ro) + x1;
for (var x:int = x1; x <= x2; x++) {
if(x>=xs && x<=xe) {
var ww:Number = x - xs;
if(ro-ww != 0.0){
theta = Math.atan(Math.sqrt(2.0 * ro * ww - ww * ww) / (ro - ww));
}else{
theta = Math.PI / 2.0;
}
if (theta < 0.0) theta += Math.PI;
var fx:Number = (theta * w1) / Math.PI + rx1;
var fy:Number = (y - y1) * h1 / h2 + ry1;
ret.setPixel(x, y, interpolate(bmp, fx, fy));
} else {
ret.setPixel(x, y, bcol);
}
}
for(x=x1;x<=x2;x++) {
ww=Math.floor(x-x1);
if(ro-ww != 0.0){
theta=Math.atan(Math.sqrt(2.0*ro*ww-ww*ww)/(ro-ww));
}else{
theta = Math.PI / 2.0;
}
if (theta < 0.0) theta += Math.PI;
fx=(theta*w1)/Math.PI+rx1;
fy=(y-y1)*h1/h2+ry1;
}
}
return ret;
}
private function linarInterpolate(c1:Number,c2:Number,c3:Number,c4:Number,xr:Number,yr:Number):int{
var d:Number = c1 * (1.0 - xr) + c3 * xr;
var e:Number = c2 * (1.0 - xr) + c4 * xr;
var f:Number = d * (1.0 - yr) + e * yr;
var res:int = Math.floor(f + 0.5);
return Math.min(255, Math.max(0, res));
}
private function interpolate(bmp:BitmapData, x:Number, y:Number):uint {
var px:int = Math.floor(x);
var py:int = Math.floor(y);
var xrate:Number = x - px;
var yrate:Number = y - py;
var c1:Array = getRGB(bmp.getPixel(px, py));
var c2:Array = getRGB(bmp.getPixel(px, py + 1));
var c3:Array = getRGB(bmp.getPixel(px + 1, py));
var c4:Array = getRGB(bmp.getPixel(px + 1, py + 1));
var r:int = linarInterpolate(c1[0], c2[0], c3[0], c4[0], xrate, yrate);
var g:int = linarInterpolate(c1[1], c2[1], c3[1], c4[1], xrate, yrate);
var b:int = linarInterpolate(c1[2], c2[2], c3[2], c4[2], xrate, yrate);
return (r << 16) + (g << 8) + b;
}
private function getRGB(c:uint):Array {
return [(c & 0xff0000) >> 16, (c & 0xff00) >> 8, c & 0xff];
}
}