四角形の画像を歪める方法はありますか? 画像を歪めて、任意の方向に任意の角を引くことができる画像を実装したいと思います。誰でもそれをどうやって考えているのですか?私はしばらくの間、アンドロイドのものを使用して書きますが、アンドロイドにはそのような機能はありません。私は本当に新しい数学ライブラリを書くような気がしない:)。あなたがCanvas.drawBitmapMeshを必要とするよう四角形に画像を歪めるには?
挨拶、 できます
四角形の画像を歪める方法はありますか? 画像を歪めて、任意の方向に任意の角を引くことができる画像を実装したいと思います。誰でもそれをどうやって考えているのですか?私はしばらくの間、アンドロイドのものを使用して書きますが、アンドロイドにはそのような機能はありません。私は本当に新しい数学ライブラリを書くような気がしない:)。あなたがCanvas.drawBitmapMeshを必要とするよう四角形に画像を歪めるには?
挨拶、 できます
が見えます。 Android SDKには、その使用方法を示すサンプルがあります。
ビットマップをCanvas
に描画するには、Matrix
を使用する必要があります。ビットマップイメージをMatrix.polyToPolyメソッドで任意の四角形に収めるような変換を簡単に作成できます。これは次のようになります。
matrix.setPolyToPoly(
new float[] {
0, 0,
bitmap.getWidth(), 0
0, bitmap.getHeight(),
bitmap.getWidth(), bitmap.getHeight()
}, 0,
new float[] {
x0, y0,
x1, y1,
x2, y2,
x3, y3
}, 0,
4);
canvas.drawBitmap(bitmap, matrix, paint);
ここで、x0-x3、y0-y3は四角形の頂点座標です。
コードに問題があります。
matrix.setPolyToPoly(
new float[] {
x0, y0,
x1, y1,
x2, y2,
x3, y3},
0,
new float[] {
0, 0,
bitmap.getWidth(), 0
0, bitmap.getHeight(),
bitmap.getWidth(), bitmap.getHeight()
}, 0,
4);
:
public boolean setPolyToPoly (float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)
WHERE
src: The array of src [x,y] pairs (points)
...
dst: The array of dst [x,y] pairs (points)
だから、あなたのコードによると、マトリックスのように作成する必要があります。それは正しい方法であるが、あなたは、Androidのドキュメントに表示されるフロートが[]、パラメータを反転しています画像に示すように、この方法では、アプリは、正常に動作します:他の手で
を、user2498079が彼に言っているのについてローエンドのデバイスでの計算上の問題についてコメントしたければ、マトリックス変換計算の前にソースイメージのサイズ(と色の深度など)を減らすための簡単な手法をいくつか使用できます。それはローエンドの携帯電話がこの作業を実現するのを容易にします。
私はこれが役に立ちそうです。左上、右上のコーナーは、左下および右下を除いて機能しています。誰かがそれを追加できますか?私は底の部分を行う方法を把握することはできません。 :)
public class PerspectiveDistortView extends View implements OnTouchListener {
private Paint paintRect, paintCircle;
public int LEFT;
public int TOP;
public int RIGHT;
public int BOTTOM;
Point CIRCLE_TOP_LEFT;
Point CIRCLE_TOP_RIGHT;
Point CIRCLE_BOTTOM_LEFT;
Point CIRCLE_BOTTOM_RIGHT;
private int lastX, lastY;
Bitmap image;
Rect src, dst;
Matrix matrix2;
boolean isTouchCirclePoints = true;
float deform2 = 5f;
public PerspectiveDistortView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
public PerspectiveDistortView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public PerspectiveDistortView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
private void init(){
this.setOnTouchListener(this);
paintRect = new Paint();
paintRect.setColor(0xffff0000);
paintRect.setAntiAlias(true);
paintRect.setDither(true);
paintRect.setStyle(Paint.Style.STROKE);
paintRect.setStrokeJoin(Paint.Join.BEVEL);
paintRect.setStrokeCap(Paint.Cap.BUTT);
paintRect.setStrokeWidth(3);
paintCircle = new Paint();
paintCircle.setColor(0xff000000);
paintCircle.setAntiAlias(true);
paintCircle.setDither(true);
paintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
paintCircle.setStrokeJoin(Paint.Join.BEVEL);
paintCircle.setStrokeCap(Paint.Cap.BUTT);
LEFT = 90;
TOP = 40;
RIGHT = 500;
BOTTOM = 700;
CIRCLE_TOP_LEFT = new Point(LEFT, TOP);
CIRCLE_TOP_RIGHT = new Point(RIGHT, TOP);
CIRCLE_BOTTOM_LEFT = new Point(LEFT, BOTTOM);
CIRCLE_BOTTOM_RIGHT = new Point(RIGHT, BOTTOM);
image = BitmapFactory.decodeResource(getResources(), R.drawable.ai);
src = new Rect();
dst = new Rect();
matrix2 = new Matrix();
}
@Override
protected void onDraw(Canvas canvas) {
// draw image
src.left = LEFT;
src.top = TOP;
src.right = RIGHT;
src.bottom = BOTTOM + image.getHeight();
dst.left = CIRCLE_TOP_LEFT.x;
dst.top = CIRCLE_TOP_LEFT.y;
dst.right = CIRCLE_TOP_RIGHT.x;
dst.bottom = CIRCLE_BOTTOM_RIGHT.y;
// Free Transform bitmap
int bw = image.getWidth();
int bh = image.getHeight();
RectF src = new RectF(LEFT, TOP, bw, bh);
RectF dst = new RectF(CIRCLE_TOP_LEFT.x + 35, CIRCLE_TOP_LEFT.y + 30, CIRCLE_TOP_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y);
matrix2.setRectToRect(src, dst, ScaleToFit.FILL);
float[] pts = {
// source
0, 0,
0, bh,
bw, bh,
bw, 0,
// destination
0, 0,
0, 0,
0, 0,
0, 0};
matrix2.mapPoints(pts, 8, pts, 0, 4);
int DX = 100;
pts[10] -= CIRCLE_TOP_LEFT.x - LEFT;
pts[12] -= CIRCLE_TOP_RIGHT.x - RIGHT;
pts[13] += 0;
pts[14] += 0;
pts[15] += CIRCLE_TOP_RIGHT.y - CIRCLE_TOP_LEFT.y;
matrix2.setPolyToPoly(pts, 0, pts, 8, 4);
canvas.drawBitmap(image, matrix2, null);
isTouchCirclePoints = false;
// line left
canvas.drawLine(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, paintRect);
// line top
canvas.drawLine(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, paintRect);
// line right
canvas.drawLine(CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, paintRect);
// line bottom
canvas.drawLine(CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, paintRect);
// circle top left
canvas.drawCircle(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, 10, paintCircle);
// circle top right
canvas.drawCircle(CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, 10, paintCircle);
// circle bottom left
canvas.drawCircle(CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, 10, paintCircle);
// circle bottom right
canvas.drawCircle(CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, 10, paintCircle);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
lastX = (int) event.getX();
lastY = (int)event.getY();
if (inCircle(lastX, lastY, CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, 40))
{
isTouchCirclePoints = true;
CIRCLE_TOP_LEFT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, 40))
{
isTouchCirclePoints = true;
CIRCLE_TOP_RIGHT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, 40))
{
isTouchCirclePoints = true;
CIRCLE_BOTTOM_LEFT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, 40))
{
isTouchCirclePoints = true;
CIRCLE_BOTTOM_RIGHT.set(lastX, lastY);
}
invalidate();
return true;
}
private boolean inCircle(float x, float y, float circleCenterX, float circleCenterY, float circleRadius) {
double dx = Math.pow(x - circleCenterX, 2);
double dy = Math.pow(y - circleCenterY, 2);
if ((dx + dy) < Math.pow(circleRadius, 2)) {
return true;
} else {
return false;
}
}
}
@donmj。あなたのコードを修正しました。
public class PerspectiveDistortView extends View implements View.OnTouchListener {
private Paint paintRect, paintCircle;
public int LEFT;
public int TOP;
public int RIGHT;
public int BOTTOM;
Point CIRCLE_TOP_LEFT;
Point CIRCLE_TOP_RIGHT;
Point CIRCLE_BOTTOM_LEFT;
Point CIRCLE_BOTTOM_RIGHT;
private int lastX, lastY;
Bitmap image;
Matrix matrix2;
boolean isTouchCirclePoints = true;
public PerspectiveDistortView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
public PerspectiveDistortView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public PerspectiveDistortView(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
private void init() {
this.setOnTouchListener(this);
paintRect = new Paint();
paintRect.setColor(0xffff0000);
paintRect.setAntiAlias(true);
paintRect.setDither(true);
paintRect.setStyle(Paint.Style.STROKE);
paintRect.setStrokeJoin(Paint.Join.BEVEL);
paintRect.setStrokeCap(Paint.Cap.BUTT);
paintRect.setStrokeWidth(3);
paintCircle = new Paint();
paintCircle.setColor(0xff000000);
paintCircle.setAntiAlias(true);
paintCircle.setDither(true);
paintCircle.setStyle(Paint.Style.FILL_AND_STROKE);
paintCircle.setStrokeJoin(Paint.Join.BEVEL);
paintCircle.setStrokeCap(Paint.Cap.BUTT);
LEFT = 90;
TOP = 40;
RIGHT = 500;
BOTTOM = 700;
CIRCLE_TOP_LEFT = new Point(LEFT, TOP);
CIRCLE_TOP_RIGHT = new Point(RIGHT, TOP);
CIRCLE_BOTTOM_LEFT = new Point(LEFT, BOTTOM);
CIRCLE_BOTTOM_RIGHT = new Point(RIGHT, BOTTOM);
image = BitmapFactory.decodeResource(getResources(), R.drawable.penguins);
matrix2 = new Matrix();
}
@Override
protected void onDraw(Canvas canvas) {
// Free Transform bitmap
int bw = image.getWidth();
int bh = image.getHeight();
float[] pts = {
// source
0, 0,
0, bh,
bw, bh,
bw, 0,
// destination
0, 0,
0, 0,
0, 0,
0, 0};
pts[8] = CIRCLE_TOP_LEFT.x;
pts[9] = CIRCLE_TOP_LEFT.y;
pts[10] = CIRCLE_BOTTOM_LEFT.x;
pts[11] = CIRCLE_BOTTOM_LEFT.y;
pts[12] = CIRCLE_BOTTOM_RIGHT.x;
pts[13] = CIRCLE_BOTTOM_RIGHT.y;
pts[14] = CIRCLE_TOP_RIGHT.x;
pts[15] = CIRCLE_TOP_RIGHT.y;
matrix2.setPolyToPoly(pts, 0, pts, 8, 4);
canvas.drawBitmap(image, matrix2, null);
isTouchCirclePoints = false;
// line left
canvas.drawLine(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, paintRect);
// line top
canvas.drawLine(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, paintRect);
// line right
canvas.drawLine(CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, paintRect);
// line bottom
canvas.drawLine(CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, paintRect);
// circle top left
canvas.drawCircle(CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, 10, paintCircle);
// circle top right
canvas.drawCircle(CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, 10, paintCircle);
// circle bottom left
canvas.drawCircle(CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, 10, paintCircle);
// circle bottom right
canvas.drawCircle(CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, 10, paintCircle);
}
@Override
public boolean onTouch(View view, MotionEvent event) {
lastX = (int) event.getX();
lastY = (int) event.getY();
if (inCircle(lastX, lastY, CIRCLE_TOP_LEFT.x, CIRCLE_TOP_LEFT.y, 40)) {
isTouchCirclePoints = true;
CIRCLE_TOP_LEFT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_TOP_RIGHT.x, CIRCLE_TOP_RIGHT.y, 40)) {
isTouchCirclePoints = true;
CIRCLE_TOP_RIGHT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_BOTTOM_LEFT.x, CIRCLE_BOTTOM_LEFT.y, 40)) {
isTouchCirclePoints = true;
CIRCLE_BOTTOM_LEFT.set(lastX, lastY);
} else if (inCircle(lastX, lastY, CIRCLE_BOTTOM_RIGHT.x, CIRCLE_BOTTOM_RIGHT.y, 40)) {
isTouchCirclePoints = true;
CIRCLE_BOTTOM_RIGHT.set(lastX, lastY);
}
invalidate();
return true;
}
private boolean inCircle(float x, float y, float circleCenterX, float circleCenterY, float circleRadius) {
double dx = Math.pow(x - circleCenterX, 2);
double dy = Math.pow(y - circleCenterY, 2);
if ((dx + dy) < Math.pow(circleRadius, 2)) {
return true;
} else {
return false;
}
}
}
matrix.setPolyToPoly
とcanvas.drawBitmap
は、すべてのマトリックス変換を解決することができません。ここで私はcanvas.drawBitmapMesh
を使って解決策を見つけました。
Distorting an image to a quadrangle fails in some cases on Android
お返事ありがとうございました。私は、マトリックスクラスのsetPolytoPolyメソッドが見えないのは馬鹿だと思うが、これはうまくいくはずだ。私は明日仕事でそれをテストします:-)! – Geki
この方法の問題点は、非常に計算量が多く、ローエンドのデバイスでは非常に遅いということです。 – user2498079
はい、実際にそうする以外の方法はありません。 – Geki