12
votes

Peinture Android: Comment obtenir l'effet "Airbrush"?

Je suis à la suite de la démo "doigt" dans les démos de l'API.

J'aurais besoin d'obtenir un effet "aérographe", dans le sens où lorsque je dessine sur le même endroit, il devient plus sombre et plus sombre. P >

S'il vous plaît voir l'image: p>

Comme vous pouvez le constater que le centre est plus sombre parce que je suis passé avec la peinture sur le même endroit plus d'une fois. P>

s'il vous plaît comment je veux Obtenez le même effet, d'avoir une tache plus sombre si elle est tirée sur plus d'une fois? p>

entrez Image Description Ici P>

Edit Modifier Modifier P>

Le type suggéré p> xxx pré>

type de travail, mais seulement si je libère la touche et Puis touchez à nouveau, si je ne libère pas et gardez le doigt sur l'écran, l'effet n'est pas atteint. p>

Le point est que vous n'atteignez pas l'effet si vous ne libérez pas votre doigt de l'écran, Si vous continuez à dessiner sans libérer le contact, il ne faut pas plus sombre lorsque vous peignez. Si vous relâchez la touche, puis dessinez à nouveau, vous obtenez l'effet P>

c'est le résultat que je reçois. Et je ne veux pas: strong> p>

Entrez la description de l'image ici p >

Ce serait le résultat souhaité: strong> p>

entrez Image Description Ici P>


Ceci est le code prélevé forme les démos de l'API: P>

public class FingerPaint extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new MyView(this));

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0x44FF0000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(12);

}

private Paint mPaint;

public class MyView extends View {

    private static final float MINP = 0.25f;
    private static final float MAXP = 0.75f;

    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;

    public MyView(Context c) {
        super(c);

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFAAAAAA);

        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
    }

    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touch_up();
            invalidate();
            break;
        }
        return true;
    }
}

}


14 commentaires

Définissez ceci pour votre objet peinture PORTERDUFFF.MODE.SRC_ATOP)); mpain.setalpha (0x80); ou juste mpain.setalpha (0x80);


mpain.setalpha (0x80) fonctionne de travail, mais seulement si je libère la touche, puis touchez à nouveau, si je ne libère pas et que je garde le doigt à l'écran, l'effet n'est pas atteint.


cela n'a rien à faire avec l'objet de peinture. c'est votre dessin qui provoque le problème


@Raghunandan merci, je posterai le code


Je vais tester et te laisser bientôt


@Raghunandan merci beaucoup !!


Je ne vois pas de problème ça marche bien. Testé sur l'émulateur


@Raghunandan Le point est que vous n'atteignez pas l'effet si vous ne relâchez pas votre doigt de l'écran, si vous continuez à dessiner sans libérer le contact, il ne faut pas plus sombre lors de la peinture. Si vous relâchez la touche, puis dessinez à nouveau, vous obtenez l'effet.


Laissez-nous Continuer cette discussion en chat


@Raghunandan Je suis désolé, mais le chat est désactivé parce que je suis derrière un pare-feu :-(


Vérifiez la réponse ci-dessous et Snap Shot, cela fonctionne pour moi et je ne peux pas dupliquer votre problème.


Avez-vous essayé ci-dessous ça marche maintenant?


Salut Lisa, ma réponse a-t-elle de l'aide? Faites-moi savoir si cela ne produit pas le même résultat propre pour vous.


Quelqu'un a-t-il obtenu une solution parfaite pour ce scénario?


3 Réponses :


5
votes

Je n'ai fait que peu de changements mineurs dans votre code.

public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(new MyView(this));

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(Color.BLACK);
    mPaint.setAlpha(0x80); // only change
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(12);

}

private Paint mPaint;

public class MyView extends View {

    private static final float MINP = 0.25f;
    private static final float MAXP = 0.75f;

    private Bitmap mBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint mBitmapPaint;

    public MyView(Context c) {
        super(c);

        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(0xFFAAAAAA);

        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

        canvas.drawPath(mPath, mPaint);
    }

    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;

    private void touch_start(float x, float y) {
        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private void touch_move(float x, float y) {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
            mX = x;
            mY = y;
        }
    }

    private void touch_up() {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        mPath.reset();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touch_start(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            touch_move(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            touch_up();
            invalidate();
            break;
        }
        return true;
    }
}

}


5 commentaires

Merci, ça ne fonctionne pas comme je voudrais. Si vous aimez, veuillez consulter les modifications de ma question.


Je ne suis pas mince que possible depuis que lorsque vous touchez et déplacez-vous jusqu'à ce que vous souleviez le tirage au sort n'est pas terminé.


Merci beaucoup Raghunandan! S'il vous plaît, avez-vous une idée d'une approche différente? Merci. Lisa


Je ne suis au courant d'aucune autre idée. Pardon


toute autre solution?



2
votes

a trouvé la solution. Pour ceux qui pourraient être intéressés:

public class DrawView extends View {
public Paint mPaint;
private Paint mPaint1;
private Paint mPaint2;

private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;

public DrawView(Context context, AttributeSet attrs) {
    super( context,  attrs);

    mPath = new Path();
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    mPaint = new Paint();
    mPaint.setAlpha(0x80);
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setColor(0x44000000);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.BUTT);
    mPaint.setStrokeWidth(5);

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);

}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawColor(0xFF00B8F5);

    canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    //mCanvas.drawPoint(x, y, mPaint);

}

private void touch_move(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();
    Path npath=new Path();
    npath.moveTo(mX, mY);
    npath.lineTo( x ,y );
    mX=x;
    mY=y;
    mCanvas.drawPath(npath, mPaint);
    npath.reset();
    //Log.e("","sto disegando");
}

private void touch_up() {

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        touch_start(x, y);
        invalidate();
        break;
    case MotionEvent.ACTION_MOVE:
        touch_move(event);
        invalidate();
        break;
    case MotionEvent.ACTION_UP:
        touch_up();
        invalidate();
        break;
    }
    return true;
}
}


8 commentaires

Toujours ma suggestion contient du bien mpain.setalpha (0x80) Vous ne faites rien sur Touch Up.


Avez-vous toujours besoin de cette mpain.setalpha (0x80)?


Voulez-vous le même résultat que le snap shot?


@Raghunandan Je sais que avec un grand coup conduit à un mauvais résultat. Je n'avais pas de chance mieux ... Je vais considérer vos autres observations et vous le faire savoir. Acclamations


Pas même les grands coups si vous regardez la largeur de course de coup de poing, il y a 12 ans et vous pouvez voir l'effet. Le problème se produit si le tirage au sort change de direction.


@Raghunandan je sais ... Avez-vous une meilleure solution? Celui-ci avec petit coup semble décent sur un véritable appareil ...


Ce n'est pas une bonne solution. Quoi qu'il en soit, si je connais une meilleure solution, je posterai la même chose. Mais ce n'est pas la même chose que la photo de la question.


Ce n'est pas une solution bonne et parfaite, veuillez décocher la réponse à la mauvaise réponse.



4
votes

Cette approche est plus une simulation de la manière dont quelque chose comme Photoshop le ferait: intégrer le long du chemin et dessiner des éclaboussures de peinture individuelles avec un espacement réglable entre entre elles.

 Entrez la description de l'image ici xxx

EDIT: Snap Shot (Raghunandan). Test de résultat avec fond blanc et peinture couleur noire.

Entrez la description de l'image ici


8 commentaires

La partie centrale du trait semble plus sombre que les bords. aussi le tirage au sort est lent.


Lisez les commentaires du code. L'automne peut être ajusté. Vous pouvez obtenir une meilleure vitesse de dessin en ajustant l'espacement. Il est également préférable d'utiliser une vision superficielle pour ce genre de chose, ce sera beaucoup plus rapide. Mais cela sort de la portée de cette question.


J'ai augmenté la largeur de course. Lorsque vous changez la direction de la partie où la direction du tirage au sort est plus sombre, même si je ne cherche pas au même endroit


Oui, comme vous l'attendez d'un aérographe. Ce que vous dites, c'est à attendre de la méthode que j'ai décrite.


Mais l'OP veut que la partie soit assombrie uniquement lorsque vous remplacez le tirage au sort. dessiner le dessin. peut-il être fait avec ce qui précède? Je suis juste des curiosités pour une meilleure solution


Je vais poster un coup de pression. Vérifiez le coup de pression. augmenté le cuve et j'ai essayé de dessiner lentement


Merci Raghunandan, ce n'est pas le genre d'artefact que je m'attendais, j'espère poster une solution pour cela plus tard.


Comment changez-vous la couleur de la course? Je pensais que c'était réglé dans couleur.argb (255, 0, 0, 0) mais j'ai changé et la couleur reste noire.