Android - вырезать круг из квадратного растрового изображения
Я пытаюсь вырезать круг из квадратного растрового изображения, используя следующий код
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?
Ответы
Ответ 1
Кажется, что PorterDuff.Mode.Clear не работает для пряников
Решена проблема (вырезаем круг из квадрата с помощью этого кода)
Bitmap output = Bitmap.createBitmap(bitmapimg.getWidth(),
bitmapimg.getHeight(), 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(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), а также вторичный холст, а также все различные изменения, которые вы должны выполнить.
Пожалуйста, проверьте ответ Ромен Гай. Вы создаете 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);