画像編集を含むAndroidアプリケーションを構築しています。いくつかの特徴は、画像を回転させ、画像の一部を消去することである。Androidで回転した画像を消去しても正しいパスが消去されない
我々は次のライブラリを使用している:https://github.com/nimengbo/StickerView
は、我々が正常に回転した画像を消去する機能を作成しました。ただし、次の操作を実行しようとしたとき:
- ある程度画像を回転しています。
- 次に、イメージを消去します。
我々は、次のバグが見つかりました:
- を我々が回転した画像を消去しようとしたときに、消去パスは、私たちの指が画面上でトレースパスを反映するものではありませんでした。上記画像から
、黄色の線は、(まっすぐ垂直ステッカーを横切る)指の実際の動きです。しかし、消去された経路は対角であることが判明した。
この問題は、画像を回転した場合にのみ発生します。イメージが回転していないときは存在しません。
はさらに、デバッグした後、我々は、上記の問題のいくつかの仮定があります
- により回転された画像には、xとyの赦免の位置が変更されます。したがって、経路はタッチ経路によって正しい経路を反映しない。
どのようにして、回転した後でも指が触れている正しいパスを経路が参照していることを確認できますか?
クラスを拡張したStickerView.java
クラスのコードは次のとおりです。
onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = MotionEventCompat.getActionMasked(event);
float[] pointXY = new float[2];
pointXY = getAbsolutePosition(event.getX(0),event.getY(0));
float xPoint = pointXY[0];
float yPoint = pointXY[1];
switch (action) {
case MotionEvent.ACTION_DOWN:
// first touch
// if it is inside the image
if (isInBitmap(event)) {
// set isInSide to true
isInSide = true;
// if it is a scratch
if(doScratch){
// start creating the scratch path
mScratchPath = new Path();
mScratchPath.moveTo(xPoint, yPoint);
mScratchPath.lineTo(xPoint, yPoint);
paths.add(new Pair<Path, Paint>(mScratchPath, mScratchCurrentPaint));
}
}
break;
case MotionEvent.ACTION_MOVE:
// if two fingers touch and is not a scratch,
// then it means we can rotate/resize/pan
if (isPointerDown && !doScratch) {
// reset matrix
matrix.reset();
// get the center point
scaledImageCenterX = (mImageWidth * mScaleFactor)/2 ;
scaledImageCenterY = (mImageHeight * mScaleFactor)/2;
// ROTATE THE IMAGE !!!
matrix.postRotate(lastRotateDegree, scaledImageCenterX, scaledImageCenterY);
// done to call onDraw
invalidate();
}
break;
}
if (operationListener != null) {
operationListener.onEdit(this);
}
// if it is a scratch
if(doScratch){
// then for every point, create a scratch path
mScratchPath.lineTo(xPoint, yPoint);
invalidate();
}else{
mScaleDetector.onTouchEvent(event);
mRotateDetector.onTouchEvent(event);
mMoveDetector.onTouchEvent(event);
mShoveDetector.onTouchEvent(event);
}
return handled;
}
onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// if the image exists
if (mBitmap != null) {
// save canvas
canvas.save();
// if it is a scratch
if(doScratch){
// scratch the image
mFillCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
// Draw our surface, nice an pristine
final Drawable surface = mScratchSurface;
if(surface != null) {
surface.draw(mFillCanvas);
}
//Scratch the surface
if(paths != null) {
for (Pair<Path, Paint> p : paths) {
mFillCanvas.drawPath(p.first,p.second);
}
}
mBitmap = mFillCache;
}
canvas.drawBitmap(mBitmap, matrix, bitmapPaint);
canvas.restore();
}
}
getAbsolutePosition機能
public float[] getAbsolutePosition(float Ax, float Ay) {
float[] mMatrixValues = new float[9];
matrix.getValues(mMatrixValues);
float x = mImageWidth - ((mMatrixValues[Matrix.MTRANS_X] - Ax)/mMatrixValues[Matrix.MSCALE_X]) - (mImageWidth - getTranslationX());
float y = mImageHeight - ((mMatrixValues[Matrix.MTRANS_Y] - Ay)/mMatrixValues[Matrix.MSCALE_X]) - (mImageHeight - getTranslationY());
return new float[] { x, y};
}
どこで回転行列を適用すればよいですか? onTouchEventの位置にありますか?またはgetAbsolutePosition関数で? –
thetaは、imageViewが回転された角度であるとします。次に、消去位置(またはオンタッチ位置)を(-theta)すなわちθの負数だけ回転させる必要があります。これを行うには、(-theta)を使用してユーザーが画面に触れる場所で変換を適用し、結果として得られた座標をimageViewから消去します。 –
最初に、変換を適用せずに消去パス全体を計算することができます。その後、パス全体が計算されたら、パス全体に変換を適用して結果のパスを得ることができます。次に、この変換されたパスをイメージから消去します –