Kadrowanie kwadratowego obrazu do okręgu-programowo

Szukałem przeszłości jednego dnia i nie udało mi się.

Otrzymuję obraz z API i pobieram go do pliku bitmapowego używając poniższego kodu .

private Bitmap DownloadImage(String URL) 
    {
        Bitmap bitmap = null;
        InputStream in = null;
        try 
        {
            in = OpenHttpConnection(URL);
            bitmap = BitmapFactory.decodeStream(in);
            in.close();
        }
        catch (IOException e1) 
        {
            e1.printStackTrace();
        }
        return bitmap;
    }

    private InputStream OpenHttpConnection(String urlString) throws IOException 
    {
        InputStream in = null;
        int response = -1;

        URL url = new URL(urlString);
        URLConnection conn = url.openConnection();

        if (!(conn instanceof HttpURLConnection))
            throw new IOException("Not an HTTP connection");

        try 
        {
            HttpURLConnection httpConn = (HttpURLConnection) conn;
            httpConn.setAllowUserInteraction(false);
            httpConn.setInstanceFollowRedirects(true);
            httpConn.setRequestMethod("GET");
            httpConn.connect();

            response = httpConn.getResponseCode();
            if (response == HttpURLConnection.HTTP_OK) 
            {
                in = httpConn.getInputStream();
            }
        }
        catch (Exception ex) 
        {
            throw new IOException("Error connecting");
        }
        return in;
    }

I dostaję obraz jako kwadrat i chcę przyciąć cztery rogi i zrobić z niego okrągły obraz . Czy jest jakiś możliwy sposób, aby to osiągnąć ?

Wszelkie powiązane odpowiedzi są mile widziane . Z góry dzięki .

Author: Loktar, 2013-04-01

7 answers

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        DrawingView dv = new DrawingView(this);
        setContentView(dv);
    }

    class DrawingView extends View {
        Bitmap bitmap;

        public DrawingView(Context context) {
            super(context);
            bitmap = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.glossy_overlay);

        }

        @Override
        public void onDraw(Canvas canvas) {
            Paint paint = new Paint();
            // paint.setColor(Color.CYAN);
            canvas.drawBitmap(getclip(), 30, 20, paint);
        }

        public Bitmap getclip() {
            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());

            paint.setAntiAlias(true);
            canvas.drawARGB(0, 0, 0, 0);
            // paint.setColor(color);
            canvas.drawCircle(bitmap.getWidth() / 2,
                    bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
            paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
            canvas.drawBitmap(bitmap, rect, rect, paint);
            return output;
        }
    }
}
 21
Author: Raghunandan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-06 12:13:53

Po pobraniu bitmapyRoundedBitmapDrawableFactory może być użyty do wygenerowania RoundedBitmapDrawable z biblioteki V4 . To Drawable można następnie zastosować do ImageView lub bezpośrednio narysować do Canvas.

// Create the RoundedBitmapDrawable.
RoundedBitmapDrawable roundDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
roundDrawable.setCircular(true);

// Apply it to an ImageView.
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setImageDrawable(roundDrawable);

// Alternatively, draw it to an canvas (e.g. in onDraw where a Canvas is available).
// setBounds since there's no View handling size and positioning.
roundDrawable.setBounds(left, top, right, bottom);
roundDrawable.draw(canvas);
 18
Author: Godfrey Duke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-26 20:35:34

Użyj poniższej funkcji, aby narysować okrąg na bitmapie, a następnie Ustaw okrążoną bitmapę na imageView

 public static Bitmap getClip(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
            bitmap.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f,
            bitmap.getWidth() / 2f, paint);
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);
        return output;
    }

Uwaga: dzielenie liczb musi być float

 17
Author: actsai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-08 05:38:47

Roman Nurik

Zmieniłem trochę kod, aby zrobić owalny obraz i przetestowałem się. Efekt i wydajność są naprawdę dobre:

public  class StreamDrawable extends Drawable {
private static final boolean USE_VIGNETTE = true;

private final RectF mRect = new RectF();
private final BitmapShader mBitmapShader;
private final Paint mPaint;
private final int mMargin;

public StreamDrawable(Bitmap bitmap, int margin) {

    mBitmapShader = new BitmapShader(bitmap,
            Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setShader(mBitmapShader);

    mMargin = margin;
}

@Override
protected void onBoundsChange(Rect bounds) {
    super.onBoundsChange(bounds);
    mRect.set(mMargin, mMargin, bounds.width() - mMargin, bounds.height() - mMargin);

    if (USE_VIGNETTE) {
        RadialGradient vignette = new RadialGradient(
                mRect.centerX(), mRect.centerY() * 1.0f / 0.7f, mRect.centerX() * 1.3f,
                new int[] { 0, 0, 0x7f000000 }, new float[] { 0.0f, 0.7f, 1.0f },
                Shader.TileMode.CLAMP);

        Matrix oval = new Matrix();
        oval.setScale(1.0f, 0.7f);
        vignette.setLocalMatrix(oval);

        mPaint.setShader(
                new ComposeShader(mBitmapShader, vignette, PorterDuff.Mode.SRC_OVER));
    }
}

@Override
public void draw(Canvas canvas) {
    canvas.drawOval(mRect, mPaint);
}

@Override
public int getOpacity() {
    return PixelFormat.TRANSLUCENT;
}

@Override
public void setAlpha(int alpha) {
    mPaint.setAlpha(alpha);
}

@Override
public void setColorFilter(ColorFilter cf) {
    mPaint.setColorFilter(cf);
}
}
 2
Author: Renascienza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-09 09:09:59

Można to po prostu zrobić w xml, proszę zobaczyć moją odpowiedź tutaj: https://stackoverflow.com/a/18287979/665930

<RelativeLayout
            android:id="@+id/icon_layout"
            android:layout_width="@dimen/icon_mask"
            android:layout_height="@dimen/icon_mask"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true" >

            <ImageView
                android:id="@+id/icon"
                android:layout_width="@dimen/icon"
                android:layout_height="@dimen/icon"
                android:layout_centerInParent="true"
                android:scaleType="fitXY" >
            </ImageView>

            <ImageView
                android:id="@+id/icon_mask"
                android:layout_width="@dimen/icon_mask"
                android:layout_height="@dimen/icon_mask"
                android:layout_centerInParent="true"
                android:background="@drawable/circle"
                android:scaleType="fitXY" >
            </ImageView>


 </RelativeLayout>


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" >
    <gradient android:startColor="#00FFFFFF" android:endColor="#00FFFFFF"
        android:angle="270"/>
     <stroke android:width="10dp" android:color="#FFAAAAAA"/>
 0
Author: Ash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:50

Próbowałem powyższych rozwiązań, ale żaden nie działał dobrze dla mnie. Dzieje się tak dlatego, że mój aparat telefoniczny nie wykonuje kwadratowego obrazu, ale tylko prostokątne obrazy. Tak więc wprowadzam pewne zmiany w rozwiązaniu @ actsai, aby zawsze przyjmować mniejszy wymiar, a następnie kadrować obraz w okręgu:

public static Bitmap getBitmapClip(Bitmap bitmap) {
    int maxLenth = bitmap.getWidth() <= bitmap.getHeight() ? bitmap.getWidth() : bitmap.getHeight();
    Bitmap output = Bitmap.createBitmap(maxLenth,
            maxLenth, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, maxLenth, maxLenth);

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    canvas.drawCircle(maxLenth / 2, maxLenth / 2,
            maxLenth / 2, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, paint);
    return output;
}

Użyłem następującej właściwości scale, aby wypełnić mój ImageView nową bitmapą:

<ImageView
    android:id="@+id/iv_photo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_gravity="center"
    android:scaleType="fitXY" />
 0
Author: Ângelo Polotto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 15:24:21

Po polowaniu na wiele odpowiedzi wpadłem na ten mały hack, który wykorzystuje FrameLayout (nakłada widoki dzieci jako stos) i atrybut stroke o owalnym kształcie. Można to zrobić po prostu w XML bez większych kłopotów i bibliotek stron trzecich.

  1. Utwórz nowy plik zasobu układu " circle_image.xml " w katalogu res / layout.
  2. Dodaj nowy FrameLayout jako widok główny w circle_image.xml.
  3. Utwórz ImageView (baza/tło), aby pomieścić obraz lub ikonę, którą chcesz przyciąć jako pierwsze dziecko w ramie.
  4. Utwórz ImageView (Maska / pierwszy plan), aby utrzymać Kształt (Owal z okręgu z atrybutem size o tej samej wysokości i szerokości), który maskuje obraz tła jako drugie/ostatnie dziecko wewnątrz FrameLayout.

Uwaga:

Naszym celem jest wykluczenie obszaru wokół okręgu i wyświetlenie zawartości obrazu widocznego wewnątrz okręgu)

  1. Utwórz nowy plik Drawable resource "circle_mask.xml " w katalogu res / drawable.
  2. Dodaj nowy kształt za pomocą android: shape= "oval" w circle_mask.xml.
  3. Dodaj znacznik rozmiaru dla kształtu, aby określić wysokość i szerokość, które muszą być równe(aby uczynić z niego okrąg) i powinny pasować do jego macierzystego FrameLayout.
  4. Dodaj stały znacznik dla kształtu, aby określić przezroczystość wewnątrz okręgu. 10.Dodaj znacznik obrysu dla kształtu tak, że będzie pierścień o określonej szerokości (Android: width)z kolorem określonym przez android: atrybut koloru.

Uwaga:

A. Kolor (kolor obrysu) określony w znaczniku stoke to MaskColor / BackgroundColor wokół naszego przyciętego obrazu. ponieważ chciałem, aby ten kolor był taki sam jak w moim widoku bazowym, który był cardView. Użyłem tego samego koloru "biały".

B. szerokość (szerokość obrysu) jest ustawiona na ogromną wartość, tak że jest zbyt gruba z wystarczającą ilością miejsca dla naszego przyciętego obrazu w środku.

C. ImageView (górna warstwa maski) utworzona w Krok 4 jest również wykorzystywany przez określenie ogromnego wymiaru, który jest znacznie większy niż jego macierzysty FrameLayout, co powoduje, że rozszerza się on poza wymiary FrameLayout. To wypełnia obszar, który nas interesuje maskowanie kolorem pierścienia o dużej szerokości obrysu.

Circle_image.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/icon_layout"
    android:layout_width="64dp"
    android:layout_height="64dp">

    <ImageView
        android:id="@+id/iv_profile_pic"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/ic_launcher_background"
        android:contentDescription="TODO"/>


    <ImageView
        android:layout_width="90dp"
        android:layout_height="90dp"
        android:layout_gravity="center"
        android:background="@drawable/circle"
        android:scaleType="fitXY" >
    </ImageView>
</FrameLayout>

Circle_mask.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <size android:width="64dp"
        android:height="64dp"/>
    <solid android:color="@android:color/transparent"/>
    <stroke
        android:width="18dp"
        android:color="@android:color/white" />
</shape>

Owalny (okrąg) kształt i ostateczny obraz

 0
Author: mahee96,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-04 18:08:53