【问题标题】:Android - Cut a circle from a square BitmapAndroid - 从方形位图中切出一个圆圈
【发布时间】:2012-11-08 09:00:08
【问题描述】:

我正在尝试使用以下代码从方形位图中切出一个圆圈

        Canvas canvas=new Canvas(bitmapimg );
        int circleXCoord = bitmapimg .getWidth() / 2;
        int circleYCoord = bitmapimg .getHeight() / 2;
        int circleRadius = bitmapimg .getWidth() / 2;

        Rect rect = new Rect(circleXCoord - circleRadius, circleYCoord - circleRadius, circleXCoord + circleRadius, circleYCoord + circleRadius);

        int width = rect.width();
        int height = rect.height();

        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.BLUE);
        canvas.drawRect(rect, paint);
        canvas.drawBitmap(bitmapimg , rect, rect, paint);
        Path p = new Path();
        p.addCircle(circleXCoord, circleYCoord, width / 2F, Path.Direction.CW);
        canvas.clipPath(p, Region.Op.DIFFERENCE);
        canvas.drawColor(0, PorterDuff.Mode.CLEAR);

这个想法是将一个正方形(矩形)位图附加到画布上,然后剪辑一个圆形路径。清除矩形和圆形之间的差异(使其透明)。

该代码在 Android 4 上运行良好,但在 Android 2.3.3 设备上,差异区域显示为黑色而不是透明。

我在这里遗漏了什么还是姜饼不支持 PorterDuff.Mode.CLEAR?有没有更好的方法从Android中的正方形切出一个圆?

【问题讨论】:

    标签: android


    【解决方案1】:

    似乎 PorterDuff.Mode.Clear 不适用于姜饼

    解决了问题(使用此代码从正方形切圆)

     public Bitmap BitmapCircularCroper(Bitmap bitmapimg){
        Bitmap output = Bitmap.createBitmap(bitmapimg.getWidth(),
                bitmapimg.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
    
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmapimg.getWidth(),
                bitmapimg.getHeight());
    
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawCircle(bitmapimg.getWidth() / 2,
                bitmapimg.getHeight() / 2, bitmapimg.getWidth() / 2, paint);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(bitmapimg, rect, rect, paint);
        return output;
    
    }
    

    【讨论】:

    • 获取圆形位图但为什么在我的情况下方形透明区域显示为黑色?
    【解决方案2】:
    import android.graphics.PorterDuff.Mode;
    import android.graphics.Bitmap.Config;
    
    public static Bitmap getCircularBitmap(Bitmap bitmap) 
    {
        Bitmap output;
    
        if (bitmap.getWidth() > bitmap.getHeight()) {
            output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Config.ARGB_8888);
        } else {
            output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Config.ARGB_8888);
        }
    
        Canvas canvas = new Canvas(output);
    
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
    
        float r = 0;
    
        if (bitmap.getWidth() > bitmap.getHeight()) {
            r = bitmap.getHeight() / 2;
        } else {
            r = bitmap.getWidth() / 2;
        }
    
        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawCircle(r, r, r, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
    
        return output;
    }
    

    【讨论】:

      【解决方案3】:

      对于仍在关注此问题的任何人,此答案将导致一些问题。

      1.) 您在此实例中创建的画布将没有硬件加速。即使您的 Paint 对象具有抗锯齿功能,画布也不会。当您决定在 onDraw() 调用中将其绘制回原始画布时,这将导致伪影。

      2.) 这需要更多资源。您必须创建第二个位图(这可能导致 OOM)和一个辅助 Canvas 以及您必须做的所有不同的更改。

      请查看 Romain Guy 的回答。您创建一个 BitmapShader,然后创建一个 RoundRect 给您一个圆形。您只需要知道 RectF 的尺寸,它就可以正确确定圆。

      这意味着如果你知道中心点 (x, y) 和半径,你可以很容易地确定 RectF。

      left = x - radius;
      top = y - radius;
      right = x + radius;
      bottom = y + radius;
      

      这也意味着使用下面发布的此解决方案,您只需在屏幕上绘制一次,其他所有操作都在屏幕外缓冲区中完成。

      http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/

      在这里找到最好的解决方案:

      BitmapShader shader;
      shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
      
      Paint paint = new Paint();
      paint.setAntiAlias(true);
      paint.setShader(shader);
      
      RectF rect = new RectF(0.0f, 0.0f, width, height);
      
      // rect contains the bounds of the shape
      // radius is the radius in pixels of the rounded corners
      // paint contains the shader that will texture the shape
      canvas.drawRoundRect(rect, radius, radius, paint);
      

      【讨论】:

      • 非常有用绘制圆形照片作为通知的大图标,必须是位图。谢谢
      猜你喜欢
      • 1970-01-01
      • 2015-06-13
      • 2018-12-15
      • 2012-06-29
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      • 2011-03-10
      相关资源
      最近更新 更多