Подтвердить что ты не робот

Закругленные углы с Пикассо

Есть ли разумный способ сделать закругленные углы с Пикассо, которые

  • Не значительно замедляет рисование
  • Работает с аппаратными слоями
  • Не создает дополнительного растрового изображения для каждого изображения
  • Позволяет изменять размер загруженного растрового изображения в размере целевого изображения

Большинство советов по picasso по закругленным углам подсказывает, что нужно использовать преобразование, но я не видел примера, который не создает дополнительный битмап как часть преобразования.

Это похоже на то, что Picasso использует только растровые изображения, в то время как трюки для округлых углов используют тот факт, что вы можете динамически рисовать округленные углы достаточно эффективно (большинство решений используют что-то в строках http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/).

Выполнение этого с помощью Volley было немного взломанным, но возможным, просто изменив тип ImageView на то, что получило пользовательский чертеж, который нарисовал закругленные углы. Поскольку Picasso нуждается в растровых изображениях (по крайней мере, есть только растровое преобразование bitmap → ), это не так, поскольку преобразование рисованного в растровое изображение создает растровое изображение в процессе.

Одним из решений было бы сделать работу по изменению picasso в отдельной ветке, которая добавила преобразование bitmap → drawable, но я бы предположил, что есть лучший способ сделать это.

Я не хочу нарисовать 9-патч поверх представления, чтобы создать видимость закругленных углов.

4b9b3361

Ответ 1

EDIT: ответ, который я бы предложил, - это ждать Picasso 2.3 или развернуть их github сейчас, где вы действительно можете попасть в BitmapDrawable.

Один из подходов, который я нашел до сих пор, заключается в том, что вы можете загружать изображения в объект Target, создавая пользовательский чертеж из растрового изображения таким образом, а затем устанавливайте drawable в ImageView, где он будет рисовать без создания нового растрового изображения.

Этот подход вроде отстой из-за нескольких причин:

1) Вы должны управлять объектами Target. Это слабые ссылки (к счастью), поэтому вы должны сами отслеживать их. Ик. Память утечки ahoy.

2) Когда вы получаете обратный вызов, вам лучше проверить, чтобы состояние мира по-прежнему имело отношение к изображению, что является частью того, чего вы хотите избежать, используя пикассо.

Короче говоря, есть несколько вещей, которые, кажется, препятствуют лучшему решению.

1) Picasso обертывает растровые изображения в PicassoDrawables. Это означает, что вы должны обрабатывать произвольные чертежи в своем пользовательском imageView (если вы идете по этому маршруту) или специальный случай для этого класса. 2) PicassoDrawable не раскрывает исходное растровое изображение, поэтому вам нужно преобразовать drawable в растровое изображение (требуется создание нового растрового изображения, afaict). 3) Нет никакой функции растрового отображения → drawable transform (см. # 1, почему, скорее всего).

Хотелось бы услышать, если что-то мне не хватает, или кто-то придумал лучшее решение. В настоящее время мой лучший план состоит в том, чтобы либо предложить управление целями, предлагаемое выше, либо переделать picasso repo, изменить PicassoDrawable, чтобы иметь общедоступный аксессуар для базового растрового изображения, и сделать преобразование в пользовательский способ для рисования таким образом в моем изображении.

Ответ 2

  • Этот код отлично работает для меня
         enter image description here

    Picasso.with(getApplicationContext())
            .load(sp.getString("image_url", ""))
            .transform(new RoundedTransformation(100, 0))
            .fit()
            .into(userProfileImg);
    

//вот класс для make

    public class RoundedTransformation implements
        com.squareup.picasso.Transformation {
    private final int radius;
    private final int margin; // dp

    // radius is corner radii in dp
    // margin is the board in dp
    public RoundedTransformation(final int radius, final int margin) {
        this.radius = radius;
        this.margin = margin;
    }

    @Override
    public Bitmap transform(final Bitmap source) {
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP,
                Shader.TileMode.CLAMP));

        Bitmap output = Bitmap.createBitmap(source.getWidth(),
                source.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        canvas.drawRoundRect(new RectF(margin, margin, source.getWidth()
                - margin, source.getHeight() - margin), radius, radius, paint);

        if (source != output) {
            source.recycle();
        }

        return output;
    }

    @Override
    public String key() {
        return "rounded";
    }
}

Ответ 3

Мне также понадобилось что-то вроде этого, но с границей. Я обыскал интернет, и я нашел одну версию (без округлых углов), которая выглядела хорошо, но граница была над изображением, и мне это не понравилось. Поэтому я сделал свою версию с границей вне изображения.

public class BitmapBorderTransformation implements Transformation {
private int mBorderSize;
private int mCornerRadius = 0;
private int mColor;

public BitmapBorderTransformation(int borderSize, int color) {
    this.mBorderSize = borderSize;
    this.mColor = color;
}

public BitmapBorderTransformation(int borderSize, int cornerRadius, int color) {
    this.mBorderSize = borderSize;
    this.mCornerRadius = cornerRadius;
    this.mColor = color;
}

@Override 
public Bitmap transform(Bitmap source) {
    int width = source.getWidth();
    int height = source.getHeight();

    Bitmap image = Bitmap.createBitmap(width, height, source.getConfig());
    Canvas canvas = new Canvas(image);
    canvas.drawARGB(0, 0, 0, 0);

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Rect rect = new Rect(0, 0, width, height);


    if(this.mCornerRadius == 0) {
        canvas.drawRect(rect, paint);
    }
    else {
        canvas.drawRoundRect(new RectF(rect),
                this.mCornerRadius, this.mCornerRadius, paint);
    }

    paint.setXfermode(new PorterDuffXfermode((PorterDuff.Mode.SRC_IN)));
    canvas.drawBitmap(source, rect, rect, paint);

    Bitmap output;

    if(this.mBorderSize == 0) {
        output = image;
    }
    else {
        width = width + this.mBorderSize * 2;
        height = height + this.mBorderSize * 2;

        output = Bitmap.createBitmap(width, height, source.getConfig());
        canvas.setBitmap(output);
        canvas.drawARGB(0, 0, 0, 0);

        rect = new Rect(0, 0, width, height);

        paint.setXfermode(null);
        paint.setColor(this.mColor);
        paint.setStyle(Paint.Style.FILL);

        canvas.drawRoundRect(new RectF(rect), this.mCornerRadius, this.mCornerRadius, paint);

        canvas.drawBitmap(image, this.mBorderSize, this.mBorderSize, null);
    }

    if(source != output){
        source.recycle();
    }
    return output;
}

@Override 
public String key() {
    return "bitmapBorder(" +
            "borderSize=" + this.mBorderSize + ", " +
            "cornerRadius=" + this.mCornerRadius + ", " +
            "color=" + this.mColor +")";
 }
}

Вот несколько примеров:

Также вы можете сделать границу без закругленных углов:
новый BitmapBorderTransformation (3, Color.WHITE);

Ответ 4

это будет работать для любого изображения любого размера -

1) сначала создайте пустой контейнер изображения для разного разрешения 2), то во время выполнения получите его высоту и ширину этим -------

BitmapFactory.Options dimensions = new BitmapFactory.Options(); 
dimensions.inJustDecodeBounds = true;
Bitmap mBitmap = BitmapFactory.decodeResource(activity.getResources(), R.drawable.icon, dimensions);
        int height = dimensions.outHeight;
        int width =  dimensions.outWidth;

3)

Picasso.with(getActivity())
            .load(url)
            .error(R.drawable.image2)
            .placeholder(R.drawable.ic_drawer)
           .resize(width, height )
            .transform(new ImageTrans_roundedcorner())
            .into(imageView1);

4) теперь класс трансформации ----

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Bitmap.Config;
import android.graphics.Rect;
import android.graphics.RectF;
import com.squareup.picasso.Transformation;

public class ImageTrans_roundedcorner implements Transformation{

    private int mBorderSize=10;
    private int mCornerRadius = 20;
    private int mColor=Color.BLACK;

    @Override
    public Bitmap transform(Bitmap source) {
        // TODO Auto-generated method stub
        Bitmap output = Bitmap.createBitmap(source.getWidth(), source.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, source.getWidth(), source.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = mCornerRadius;

        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(source, rect, rect, paint);

     // draw border
        paint.setColor(color);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth((float) mBorderSize);
        canvas.drawRoundRect(rectF, mCornerRadius, mCornerRadius, paint);
        //-------------------

            if(source != output) source.recycle();

            return output;
    }

    @Override
    public String key() {
        // TODO Auto-generated method stub
        return "grayscaleTransformation()";
    }

}