web-dev-qa-db-fra.com

superposer deux images dans Android pour définir une image

J'essaie de superposer deux images dans mon application, mais elles semblent planter à ma ligne canvas.setBitmap(). Qu'est-ce que je fais mal?

private void test() {
    Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.t);
    Bitmap mBitmap2 = BitmapFactory.decodeResource(getResources(), R.drawable.tt);
    Bitmap bmOverlay = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), mBitmap.getConfig());
    Canvas canvas = new Canvas();
    canvas.setBitmap(bmOverlay);
    canvas.drawBitmap(mBitmap, new Matrix(), null);
    canvas.drawBitmap(mBitmap2, new Matrix(), null);
    testimage.setImageBitmap(bmOverlay);
}
98
John

Vous pouvez ignorer la manipulation complexe de Canvas et le faire entièrement avec Drawables, en utilisant LayerDrawable . Vous avez l'un des deux choix: Vous pouvez soit définissez-le en XML , puis définissez simplement l'image, soit vous pouvez configurer un LayerDrawable de manière dynamique dans le code.

Solution n ° 1 (via XML):

Créez un nouveau fichier XML Drawable, appelons-le layer.xml:

<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@drawable/t" />
    <item Android:drawable="@drawable/tt" />
</layer-list>

Maintenant, définissez l'image en utilisant ce Drawable:

testimage.setImageDrawable(getResources().getDrawable(R.layout.layer));

Solution n ° 2 (dynamique):

Resources r = getResources();
Drawable[] layers = new Drawable[2];
layers[0] = r.getDrawable(R.drawable.t);
layers[1] = r.getDrawable(R.drawable.tt);
LayerDrawable layerDrawable = new LayerDrawable(layers);
testimage.setImageDrawable(layerDrawable);

(Je n'ai pas testé ce code, il peut donc y avoir une erreur, mais ce schéma général devrait fonctionner.)

231
Daniel Lew

ok, juste pour que vous sachiez qu'il existe un programme appelé DroidDraw. Cela peut vous aider à dessiner des objets et à les essayer les uns sur les autres. J'ai essayé votre solution mais j'avais l'animation sous la plus petite image pour que cela ne fonctionne pas. Mais ensuite, j'ai essayé de placer une image dans une mise en page relative supposée être placée en premier, puis j'ai ensuite dessiné l'autre image supposée être superposée et tout a bien fonctionné. Donc, RelativeLayout, DroidDraw et vous êtes prêt à partir :) Simple, pas de n'importe quel type de jockery pockery :) et voici un peu de code pour vous:

Le logo sera au-dessus de l'image de fond de shazam.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
Android:id="@+id/widget30"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
xmlns:Android="http://schemas.Android.com/apk/res/Android"
>
<ImageView
Android:id="@+id/widget39"
Android:layout_width="219px"
Android:layout_height="225px"
Android:src="@drawable/shazam_bkgd"
Android:layout_centerVertical="true"
Android:layout_centerHorizontal="true"
>
</ImageView>
<ImageView
Android:id="@+id/widget37"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:src="@drawable/shazam_logo"
Android:layout_centerVertical="true"
Android:layout_centerHorizontal="true"
>
</ImageView>
</RelativeLayout>
10
dropsOfJupiter

Vous pouvez utiliser le code ci-dessous pour résoudre le problème ou télécharger la démo ici

Créez deux fonctions pour gérer chacune.

Tout d'abord, la toile est dessinée et les images sont dessinées les unes sur les autres à partir du point (0,0).

Sur le bouton clic

public void buttonMerge(View view) {

        Bitmap bigImage = BitmapFactory.decodeResource(getResources(), R.drawable.img1);
        Bitmap smallImage = BitmapFactory.decodeResource(getResources(), R.drawable.img2);
        Bitmap mergedImages = createSingleImageFromMultipleImages(bigImage, smallImage);

        img.setImageBitmap(mergedImages);
    }

Fonction pour créer une superposition.

private Bitmap createSingleImageFromMultipleImages(Bitmap firstImage, Bitmap secondImage){

    Bitmap result = Bitmap.createBitmap(firstImage.getWidth(), firstImage.getHeight(), firstImage.getConfig());
    Canvas canvas = new Canvas(result);
    canvas.drawBitmap(firstImage, 0f, 0f, null);
    canvas.drawBitmap(secondImage, 10, 10, null);
    return result;
}

En savoir plus

4
Daniel Nyamasyo

Sa réponse est un peu tardive, mais elle couvre la fusion des images d'URL à l'aide de Picasso.

MergeImageView

import Android.annotation.TargetApi;
import Android.content.Context;
import Android.graphics.Bitmap;
import Android.graphics.BitmapFactory;
import Android.graphics.Canvas;
import Android.graphics.Color;
import Android.os.AsyncTask;
import Android.os.Build;
import Android.util.AttributeSet;
import Android.util.SparseArray;
import Android.widget.ImageView;
import com.squareup.picasso.Picasso;

import Java.io.IOException;
import Java.util.List;

public class MergeImageView extends ImageView {

    private SparseArray<Bitmap> bitmaps = new SparseArray<>();
    private Picasso picasso;
    private final int DEFAULT_IMAGE_SIZE = 50;
    private int MIN_IMAGE_SIZE = DEFAULT_IMAGE_SIZE;
    private int MAX_WIDTH = DEFAULT_IMAGE_SIZE * 2, MAX_HEIGHT = DEFAULT_IMAGE_SIZE * 2;
    private String picassoRequestTag = null;

    public MergeImageView(Context context) {
        super(context);
    }

    public MergeImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MergeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @TargetApi(Build.VERSION_CODES.Lollipop)
    public MergeImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean isInEditMode() {
        return true;
    }

    public void clearResources() {
        if (bitmaps != null) {
            for (int i = 0; i < bitmaps.size(); i++)
                bitmaps.get(i).recycle();
            bitmaps.clear();
        }
        // cancel picasso requests
        if (picasso != null && AppUtils.ifNotNullEmpty(picassoRequestTag))
            picasso.cancelTag(picassoRequestTag);
        picasso = null;
        bitmaps = null;
    }

    public void createMergedBitmap(Context context, List<String> imageUrls, String picassoTag) {
        picasso = Picasso.with(context);
        int count = imageUrls.size();
        picassoRequestTag = picassoTag;

        boolean isEven = count % 2 == 0;
        // if url size are not even make MIN_IMAGE_SIZE even
        MIN_IMAGE_SIZE = DEFAULT_IMAGE_SIZE + (isEven ? count / 2 : (count / 2) + 1);
        // set MAX_WIDTH and MAX_HEIGHT to twice of MIN_IMAGE_SIZE
        MAX_WIDTH = MAX_HEIGHT = MIN_IMAGE_SIZE * 2;
        // in case of odd urls increase MAX_HEIGHT
        if (!isEven) MAX_HEIGHT = MAX_WIDTH + MIN_IMAGE_SIZE;

        // create default bitmap
        Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_wallpaper),
                MIN_IMAGE_SIZE, MIN_IMAGE_SIZE, false);

        // change default height (wrap_content) to MAX_HEIGHT
        int height = Math.round(AppUtils.convertDpToPixel(MAX_HEIGHT, context));
        setMinimumHeight(height * 2);

        // start AsyncTask
        for (int index = 0; index < count; index++) {
            // put default bitmap as a place holder
            bitmaps.put(index, bitmap);
            new PicassoLoadImage(index, imageUrls.get(index)).execute();
            // if you want parallel execution use
            // new PicassoLoadImage(index, imageUrls.get(index)).(AsyncTask.THREAD_POOL_EXECUTOR);
        }
    }

    private class PicassoLoadImage extends AsyncTask<String, Void, Bitmap> {

        private int index = 0;
        private String url;

        PicassoLoadImage(int index, String url) {
            this.index = index;
            this.url = url;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            try {
                // synchronous picasso call
                return picasso.load(url).resize(MIN_IMAGE_SIZE, MIN_IMAGE_SIZE).tag(picassoRequestTag).get();
            } catch (IOException e) {
            }
            return null;
        }

        @Override
        protected void onPostExecute(Bitmap output) {
            super.onPostExecute(output);
            if (output != null)
                bitmaps.put(index, output);

            // create canvas
            Bitmap.Config conf = Bitmap.Config.RGB_565;
            Bitmap canvasBitmap = Bitmap.createBitmap(MAX_WIDTH, MAX_HEIGHT, conf);
            Canvas canvas = new Canvas(canvasBitmap);
            canvas.drawColor(Color.WHITE);

            // if height and width are equal we have even images
            boolean isEven = MAX_HEIGHT == MAX_WIDTH;
            int imageSize = bitmaps.size();
            int count = imageSize;

            // we have odd images
            if (!isEven) count = imageSize - 1;
            for (int i = 0; i < count; i++) {
                Bitmap bitmap = bitmaps.get(i);
                canvas.drawBitmap(bitmap, bitmap.getWidth() * (i % 2), bitmap.getHeight() * (i / 2), null);
            }
            // if images are not even set last image width to MAX_WIDTH
            if (!isEven) {
                Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmaps.get(count), MAX_WIDTH, MIN_IMAGE_SIZE, false);
                canvas.drawBitmap(scaledBitmap, scaledBitmap.getWidth() * (count % 2), scaledBitmap.getHeight() * (count / 2), null);
            }
            // set bitmap
            setImageBitmap(canvasBitmap);
        }
    }
}

xml

<com.example.MergeImageView
    Android:id="@+id/iv_thumb"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content" />

Exemple

List<String> urls = new ArrayList<>();
String picassoTag = null;
// add your urls
((MergeImageView)findViewById(R.id.iv_thumb)).
        createMergedBitmap(MainActivity.this, urls,picassoTag);
2
Haris Qureshi