使用Android中的PAINT对象在画布上绘制椭圆

时间:2014-12-30 14:34:17

标签: android canvas drawing paint

在下面的代码中,我试图绘制一个随时间放大的椭圆。

Bitmap currBitmap = null;
Canvas currCanvas = null;

//Config Paint Case2
final Paint currPaint = new Paint();
List BlocksList = null;
boolean bSet = false;

public void DrawOval(Bitmap src, int nRadiusprct) 
{
    // image size
    int width = src.getWidth();
    int height = src.getHeight();

    //create bitmap output
    if(currBitmap  == null)
        currBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

    // set canvas for painting
    if(currCanvas == null)
    {
        currCanvas = new Canvas(currBitmap);
        currCanvas.drawARGB(0, 0, 0, 0);
        MainActivity.imgMain.setImageBitmap(currBitmap);
    }

    // config paint Case1
    /*final Paint currPaint = new Paint();
    currPaint.setAntiAlias(true);
    currPaint.setColor(Color.BLACK);*/

    // config paint Case2
    if(!bSet)
    {
        currPaint.setAntiAlias(true);
        currPaint.setColor(Color.BLACK);
        // create Xfer mode
         currPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        bSet = true;
    }

    // config rectangle for embedding
    int nMidWidth = width/2;
    int nMidHeight = height/2;
    float fPercent = (nRadiusprct / 100.0f);

    float fLeft = nMidWidth * (1 - fPercent);  
    float fRight = nMidWidth * (1 + fPercent);
    float fTop = nMidHeight * (1 - fPercent);
    float fBottom = nMidHeight * (1 + fPercent);

    final Rect rect = new Rect(0, 0, width, height);
    final RectF rectF = new RectF(fLeft, fTop, fRight, fBottom);

    currCanvas.drawOval(rectF, currPaint);

    // create Xfer mode, Config Paint Case1
    //currPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    currCanvas.drawBitmap(src, rect, rect, currPaint);

    MainActivity.imgMain.invalidate();
}

现在,如您所见,编写注释“Config Paint Case1”或“Config Paint Case2”,case1表示每次调用方法时创建绘图实例的情况,而情况2表示我定义成员的位置类中的对象所以我可以在需要的时候使用它,当我使用第一种情况时,一切都工作得很完美和准确,而当我使用第二种情况时没有发生任何事情的问题,在我看来主要的事情我不需要每次都创建一个绘图对象,所以我需要越来越多地优化我的代码,但为什么会发生这种情况......

1 个答案:

答案 0 :(得分:0)

最后我得到了这个问题的答案,这篇文章Transparency with JPEGs done right提供了很好的帮助,描述了PorterDuff模式是如何工作的,在那篇文章中我找到了Xfermodes Example,它给出了错误的地方和这是描述。

实际上,我不需要每次都创建一个绘图对象,我需要的是以正确的方式处理xfermodes,完美的代码是:

 Bitmap currBitmap = null;
 Canvas currCanvas = null;

 //Config Paint Case2
 final Paint currPaint = new Paint();
 List BlocksList = null;
 boolean bSet = false;

public void DrawOval(Bitmap src, int nRadiusprct) 
{
    // image size
    int width = src.getWidth();
    int height = src.getHeight();

    //create bitmap output
    if(currBitmap  == null)
        currBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

    // set canvas for painting
    if(currCanvas == null)
    {
        currCanvas = new Canvas(currBitmap);
        MainActivity.imgMain.setImageBitmap(currBitmap);
    }

    // config paint Case2
    if(!bSet)
    {
        currPaint.setAntiAlias(true);
        currPaint.setColor(Color.BLACK);
        bSet = true;
    }

    // config rectangle for embedding
    int nMidWidth = width/2;
    int nMidHeight = height/2;
    float fPercent = (nRadiusprct / 100.0f);

    float fLeft = nMidWidth * (1 - fPercent);  
    float fRight = nMidWidth * (1 + fPercent);
    float fTop = nMidHeight * (1 - fPercent);
    float fBottom = nMidHeight * (1 + fPercent);

    final Rect rect = new Rect(0, 0, width, height);
    final RectF rectF = new RectF(fLeft, fTop, fRight, fBottom);

    Xfermode BeforEPaintXferMode = currPaint.getXfermode();

    currCanvas.drawOval(rectF, currPaint);

    // create Xfer mode
    currPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

    // draw source image to canvas
    currCanvas.drawBitmap(src, rect, rect, currPaint);

    currPaint.setXfermode(BeforEPaintXferMode);

    MainActivity.imgMain.invalidate();
}

现在,你可以看到我只是在绘画之前存储当前的xfermode,然后我将它设置为SRC_IN模式,最后,我回到原来的模式。一切都很完美。