Я хотел бы изменить изображение, которое я загрузил, чтобы иметь круглые углы.
Любые подсказки, руководства, лучшие практики, о которых вы знаете?
Я хотел бы изменить изображение, которое я загрузил, чтобы иметь круглые углы.
Любые подсказки, руководства, лучшие практики, о которых вы знаете?
Для более контролируемого метода нарисуйте закругленный прямоугольник и замаскируйте его на свое изображение, используя режим рисования портье-duff Xfer.
Сначала установите Xfer-краску и закругленное растровое изображение:
Bitmap myCoolBitmap = ... ; // <-- Your bitmap you want rounded
int w = myCoolBitmap.getWidth(), h = myCoolBitmap.getHeight();
// We have to make sure our rounded corners have an alpha channel in most cases
Bitmap rounder = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(rounder);
// We're going to apply this paint eventually using a porter-duff xfer mode.
// This will allow us to only overwrite certain pixels. RED is arbitrary. This
// could be any color that was fully opaque (alpha = 255)
Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
xferPaint.setColor(Color.RED);
// We're just reusing xferPaint to paint a normal looking rounded box, the 20.f
// is the amount we're rounding by.
canvas.drawRoundRect(new RectF(0,0,w,h), 20.0f, 20.0f, xferPaint);
// Now we apply the 'magic sauce' to the paint
xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
Теперь примените это растровое изображение на вашем изображении:
Bitmap result = Bitmap.createBitmap(myCoolBitmap.getWidth(), myCoolBitmap.getHeight() ,Bitmap.Config.ARGB_8888);
Canvas resultCanvas = new Canvas(result)
resultCanvas.drawBitmap(myCoolBitmap, 0, 0, null);
resultCanvas.drawBitmap(rounder, 0, 0, xferPaint);
Растровое изображение с закругленными углами теперь находится в результате.
Почему бы не использовать clipPath?
protected void onDraw(Canvas canvas) {
Path clipPath = new Path();
float radius = 10.0f;
float padding = radius / 2;
int w = this.getWidth();
int h = this.getHeight();
clipPath.addRoundRect(new RectF(padding, padding, w - padding, h - padding), radius, radius, Path.Direction.CW);
canvas.clipPath(clipPath);
super.onDraw(canvas);
}
Ромен Гай сам пишет об этом в своем блоге:
Чтобы сгенерировать округленные изображения, я просто написал пользовательский Drawable, который рисует закругленный прямоугольник с помощью Canvas.drawRoundRect(). Уловка использовать Paint с BitmapShader для заполнения закругленного прямоугольника с помощью текстура вместо простого цвета. Вот как выглядит код:
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);
Пример приложения идет немного дальше и подделывает виньетку эффект путем объединения BitmapShader с RadialGradient.
Здесь я нашел это с помощью ImageView. Я пробовал другие методы, в том числе ответы здесь и на подобные вопросы, но я обнаружил, что они не работают хорошо для меня, поскольку мне нужны углы, которые будут применяться к представлению изображения, а не напрямую к растровому изображению. Применение непосредственно к растровому изображению не будет работать, если вы масштабируете/обрезаете/панорамируете это растровое изображение, так как углы также будут масштабироваться/обрезаны/подкрашены.
public class RoundedCornersImageView extends ImageView {
private final Paint restorePaint = new Paint();
private final Paint maskXferPaint = new Paint();
private final Paint canvasPaint = new Paint();
private final Rect bounds = new Rect();
private final RectF boundsf = new RectF();
public RoundedCornersImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RoundedCornersImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersImageView(Context context) {
super(context);
init();
}
private void init() {
canvasPaint.setAntiAlias(true);
canvasPaint.setColor(Color.argb(255, 255, 255, 255));
restorePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
maskXferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
}
@Override
protected void onDraw(Canvas canvas) {
canvas.getClipBounds(bounds);
boundsf.set(bounds);
canvas.saveLayer(boundsf, restorePaint, Canvas.ALL_SAVE_FLAG);
super.onDraw(canvas);
canvas.saveLayer(boundsf, maskXferPaint, Canvas.ALL_SAVE_FLAG);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawRoundRect(boundsf, 75, 75, canvasPaint);
canvas.restore();
canvas.restore();
}
}
Здесь альтернатива, которая использует аппаратные уровни для композита последнего уровня:
public class RoundedCornersImageView extends ImageView {
private final Paint restorePaint = new Paint();
private final Paint maskXferPaint = new Paint();
private final Paint canvasPaint = new Paint();
private final Rect bounds = new Rect();
private final RectF boundsf = new RectF();
public RoundedCornersImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public RoundedCornersImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RoundedCornersImageView(Context context) {
super(context);
init();
}
private void init() {
canvasPaint.setAntiAlias(true);
canvasPaint.setColor(Color.argb(255, 255, 255, 255));
restorePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
maskXferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
setLayerType(View.LAYER_TYPE_HARDWARE, restorePaint);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.getClipBounds(bounds);
boundsf.set(bounds);
super.onDraw(canvas);
canvas.saveLayer(boundsf, maskXferPaint, Canvas.ALL_SAVE_FLAG);
canvas.drawARGB(0, 0, 0, 0);
canvas.drawRoundRect(boundsf, 75, 75, canvasPaint);
canvas.restore();
}
}
Сначала мне не удалось заставить его работать с этим методом, потому что мои углы становились черными; Позже я понял, в чем проблема после прочтения этого вопроса: Android, как применить маску к ImageView?. Оказывается, что изменение альфы в холсте фактически "царапает" прямо на экране и пробивает отверстие в нижнем окне, которое является черным. Для этого нужны два слоя: один для применения маски, а другой - для применения композитного изображения к экрану.
Как создать NinePatchDrawable изображение с закругленными углами и прозрачным телом. Наложите изображение соответствующим образом измененным размером вашего NinePatchDrawable.
package com.pkg;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;
import android.os.Bundle;
import android.os.Environment;
import android.widget.ImageView;
public class RoundedImage extends Activity {
/** Called when the activity is first created. */
ImageView imag;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imag=(ImageView)findViewById(R.id.image);
//ImageView img1=(ImageView)findViewById(R.id.imageView1);
BitmapFactory.Options bitopt=new BitmapFactory.Options();
bitopt.inSampleSize=1;
// String img=Environment.getExternalStorageDirectory().toString();
// String filepath =Environment.getExternalStorageDirectory().toString();
String filepath ="/mnt/sdcard/LOST.DIR";
File imagefile = new File(filepath + "/logo.jpg");
FileInputStream fis = null;
try
{
fis = new FileInputStream(imagefile);
}
catch (FileNotFoundException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
Bitmap bi = BitmapFactory.decodeStream(fis);
if(bi!=null){
imag.setImageBitmap(getRoundedCornerBitmap(bi));
}
}
public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.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, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
final float roundPx = 12;
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}