Android – efecto de deformación de imagen
En mi aplicación Android, quiero aplicar efecto de warp
imagen proporcionado en la aplicación Photo Warp y Photo Deformer . Para eso utilicé BitmapMesh
. El problema es que, no es el ahorro imagen deformada. Siempre que toco la imagen, refresco la imagen y no ahorro mi imagen warped previamente. Quiero ahorrar esa imagen siempre que el usuario realice la operación de la deformación. Aquí estoy publicando mi código. Aquí estoy utilizando "BitmapMesh" actividad para realizar el efecto warp en la imagen.
Por favor ayúdame a resolver este problema. Gracias.
- Escala de diseño relativo personalizado?
- Diferencia entre View y ViewGroup en Android
- RemoveView no funciona después de LayoutInflater.inflate (resource, root, true)
- ¿Por qué ir para el diseño de restricciones ya que ya tenemos Disposición relativa?
- Problema en un grupo de vistas personalizado al actualizar ListViews
Código:
BitmapMesh Actividad:
import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.os.Bundle; import android.util.FloatMath; import android.view.MotionEvent; import android.view.View; public class BitmapMesh extends GraphicsActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(new SampleView(this)); } private static class SampleView extends View { private static final int WIDTH = 20; private static final int HEIGHT = 20; private static final int COUNT = (WIDTH + 1) * (HEIGHT + 1); private final Bitmap mBitmap; private final float[] mVerts = new float[COUNT * 2]; private final float[] mOrig = new float[COUNT * 2]; private final Matrix mMatrix = new Matrix(); private final Matrix mInverse = new Matrix(); private static void setXY(float[] array, int index, float x, float y) { array[index * 2 + 0] = x; array[index * 2 + 1] = y; } public SampleView(Context context) { super(context); setFocusable(true); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1); float w = mBitmap.getWidth(); float h = mBitmap.getHeight(); // construct our mesh int index = 0; for (int y = 0; y <= HEIGHT; y++) { float fy = h * y / HEIGHT; for (int x = 0; x <= WIDTH; x++) { float fx = w * x / WIDTH; setXY(mVerts, index, fx, fy); setXY(mOrig, index, fx, fy); index += 1; } } mMatrix.setTranslate(10, 10); mMatrix.invert(mInverse); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(0xFFCCCCCC); canvas.concat(mMatrix); canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0, null, 0, null); } private void warp(float cx, float cy) { final float K = 10000; float[] src = mOrig; float[] dst = mVerts; for (int i = 0; i < COUNT * 2; i += 2) { float x = src[i + 0]; float y = src[i + 1]; float dx = cx - x; float dy = cy - y; float dd = dx * dx + dy * dy; float d = FloatMath.sqrt(dd); float pull = K / (dd + 0.000001f); pull /= (d + 0.000001f); // android.util.Log.d("skia", "index " + i + " dist=" + d + // " pull=" + pull); if (pull >= 1) { dst[i + 0] = cx; dst[i + 1] = cy; } else { dst[i + 0] = x + dx * pull; dst[i + 1] = y + dy * pull; } } } private int mLastWarpX = -9999; // don't match a touch coordinate private int mLastWarpY; @Override public boolean onTouchEvent(MotionEvent event) { float[] pt = { event.getX(), event.getY() }; mInverse.mapPoints(pt); int x = (int) pt[0]; int y = (int) pt[1]; if (mLastWarpX != x || mLastWarpY != y) { mLastWarpX = x; mLastWarpY = y; warp(pt[0], pt[1]); invalidate(); } return true; } } }
Gráficos Actividad:
import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; class GraphicsActivity extends Activity { // set to true to test Picture private static final boolean TEST_PICTURE = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void setContentView(View view) { if (TEST_PICTURE) { ViewGroup vg = new PictureLayout(this); vg.addView(view); view = vg; } super.setContentView(view); } }
PictureLayout.java
import android.content.Context; import android.graphics.Canvas; import android.graphics.Picture; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; class PictureLayout extends ViewGroup { private final Picture mPicture = new Picture(); public PictureLayout(Context context) { super(context); } public PictureLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public void addView(View child) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child); } @Override public void addView(View child, int index) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, index); } @Override public void addView(View child, LayoutParams params) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, params); } @Override public void addView(View child, int index, LayoutParams params) { if (getChildCount() > 1) { throw new IllegalStateException( "PictureLayout can host only one direct child"); } super.addView(child, index, params); } @Override protected LayoutParams generateDefaultLayoutParams() { return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int count = getChildCount(); int maxHeight = 0; int maxWidth = 0; for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { measureChild(child, widthMeasureSpec, heightMeasureSpec); } } maxWidth += getPaddingLeft() + getPaddingRight(); maxHeight += getPaddingTop() + getPaddingBottom(); Drawable drawable = getBackground(); if (drawable != null) { maxHeight = Math.max(maxHeight, drawable.getMinimumHeight()); maxWidth = Math.max(maxWidth, drawable.getMinimumWidth()); } setMeasuredDimension(resolveSize(maxWidth, widthMeasureSpec), resolveSize(maxHeight, heightMeasureSpec)); } private void drawPict(Canvas canvas, int x, int y, int w, int h, float sx, float sy) { canvas.save(); canvas.translate(x, y); canvas.clipRect(0, 0, w, h); canvas.scale(0.5f, 0.5f); canvas.scale(sx, sy, w, h); canvas.drawPicture(mPicture); canvas.restore(); } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(mPicture.beginRecording(getWidth(), getHeight())); mPicture.endRecording(); int x = getWidth() / 2; int y = getHeight() / 2; if (false) { canvas.drawPicture(mPicture); } else { drawPict(canvas, 0, 0, x, y, 1, 1); drawPict(canvas, x, 0, x, y, -1, 1); drawPict(canvas, 0, y, x, y, 1, -1); drawPict(canvas, x, y, x, y, -1, -1); } } @Override public ViewParent invalidateChildInParent(int[] location, Rect dirty) { location[0] = getLeft(); location[1] = getTop(); dirty.set(0, 0, getWidth(), getHeight()); return getParent(); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = super.getChildCount(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final int childLeft = getPaddingLeft(); final int childTop = getPaddingTop(); child.layout(childLeft, childTop, childLeft + child.getMeasuredWidth(), childTop + child.getMeasuredHeight()); } } } }
- Stackoverflow error en la vista
- Prevención / captura "IllegalArgumentException: parámetro debe ser un descendente de esta vista" error
- Uso de dispatchDraw (Lienzo lienzo)
- NullPointerException: Intento de leer del campo 'int android.view.View.mViewFlags'
- Android - Ocultar vistas
- Construcción de un contenedor capaz de hacer zoom
- Android ViewGroup crash: Intenta leer desde el campo 'int android.view.View.mViewFlags' en una referencia de objeto nulo
- Vistas dentro de un grupo de vistas personalizado que no se representan después de un cambio de tamaño
//Little changes in this piece of code float[] dst; //Global public SampleView(Context context) { super(context); setFocusable(true); mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1); float w = mBitmap.getWidth(); float h = mBitmap.getHeight(); // construct our mesh int index = 0; for (int y = 0; y <= HEIGHT; y++) { float fy = h * y / HEIGHT; for (int x = 0; x <= WIDTH; x++) { float fx = w * x / WIDTH; setXY(mVerts, index, fx, fy); setXY(mOrig, index, fx, fy); index += 1; dst=mVerts;//Assign dst here just once } } mMatrix.setTranslate(10, 10); mMatrix.invert(mInverse); } @Override protected void onDraw(Canvas canvas) { canvas.drawColor(0xFFCCCCCC); canvas.concat(mMatrix); canvas.drawBitmapMesh(mBitmap, WIDTH, HEIGHT, mVerts, 0, null, 0, null); } private void warp(float cx, float cy) { final float K = 10000; float[] src = dst; //now you are applying wrap effect on the last effected pixels for (int i = 0; i < COUNT * 2; i += 2) { float x = src[i + 0]; float y = src[i + 1]; float dx = cx - x; float dy = cy - y; float dd = dx * dx + dy * dy; float d = FloatMath.sqrt(dd); float pull = K / (dd + 0.000001f); pull /= (d + 0.000001f); // android.util.Log.d("skia", "index " + i + " dist=" + d + // " pull=" + pull); if (pull >= 1) { dst[i + 0] = cx; dst[i + 1] = cy; } else { dst[i + 0] = x + dx * pull; dst[i + 1] = y + dy * pull; } } }