代码之家  ›  专栏  ›  技术社区  ›  Jack

如何以编程方式将两个可绘制内容合并为一个可绘制内容[复制]

  •  0
  • Jack  · 技术社区  · 7 年前

    我试图在我的应用程序中覆盖两个图像,但它们似乎在我的应用程序崩溃 canvas.setBitmap() 线路。我做错什么了?

    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);
    }
    
    0 回复  |  直到 10 年前
        1
  •  237
  •   deadboy    9 年前

    您可以跳过复杂的画布操作,完全使用Drawables,使用 LayerDrawable . 你有两个选择之一:你可以 define it in XML 可分层绘制

    解决方案1(通过XML):

    创建一个新的可绘制XML文件,我们称之为 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>
    

    现在使用该绘图工具设置图像:

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

    解决方案2(动态):

    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);
    

    (我还没有测试过这段代码,所以可能会有错误,但是这个概要应该可以用。)

        2
  •  10
  •   Pavan Gandhi    14 年前

    好吧,你知道有一个叫做DroidDraw的程序。它可以帮助您绘制对象,并尝试将它们一个放在另一个上。我尝试了你的解决方案,但我有动画下的较小的图像,所以没有工作。但后来我试着把一个图像放在一个相对的布局中,假设是在下面,然后在上面,我画了另一个图像,假设是覆盖,一切都很好。所以RelativeLayout,DroidDraw和你很好:)简单,没有任何形式的骗局:)这里有一些代码给你:

    标志将是在沙扎姆的背景图像顶部。

    <?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>
    
        3
  •  6
  •   Kishan Thakkar    6 年前

    您可以使用下面的代码来解决问题或 download demo here

    创建两个函数来处理每个函数。

    单击按钮

    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);
        }
    

    函数创建覆盖。

    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;
    }
    

    Read more

        4
  •  2
  •   Haris Qurashi    9 年前

    合并图像视图

    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" />
    

    例子

    List<String> urls = new ArrayList<>();
    String picassoTag = null;
    // add your urls
    ((MergeImageView)findViewById(R.id.iv_thumb)).
            createMergedBitmap(MainActivity.this, urls,picassoTag);
    
        5
  •  1
  •   Sadeq Nameni    5 年前

        public Bitmap Blend(Bitmap topImage1, Bitmap bottomImage1, PorterDuff.Mode Type) {
    
            Bitmap workingBitmap = Bitmap.createBitmap(topImage1);
            Bitmap topImage = workingBitmap.copy(Bitmap.Config.ARGB_8888, true);
    
            Bitmap workingBitmap2 = Bitmap.createBitmap(bottomImage1);
            Bitmap bottomImage = workingBitmap2.copy(Bitmap.Config.ARGB_8888, true);
    
            Rect dest = new Rect(0, 0, bottomImage.getWidth(), bottomImage.getHeight());
            new BitmapFactory.Options().inPreferredConfig = Bitmap.Config.ARGB_8888;
            bottomImage.setHasAlpha(true);
            Canvas canvas = new Canvas(bottomImage);
            Paint paint = new Paint();
    
            paint.setXfermode(new PorterDuffXfermode(Type));
    
            paint.setFilterBitmap(true);
            canvas.drawBitmap(topImage, null, dest, paint);
            return bottomImage;
        }
    

    imageView.setImageBitmap(Blend(topBitmap, bottomBitmap, PorterDuff.Mode.SCREEN));
    

    imageView.setImageBitmap(Blend(topBitmap, bottomBitmap, PorterDuff.Mode.OVERLAY));
    

    覆盖模式: Overlay mode

    Screen mode