像我们在屏幕上看到的那样在2个图像视图上合并2个位图

时间:2013-12-30 05:09:50

标签: android bitmap

我正在编写照片应用程序,在透明框架上重叠用户的照片。我在imageview上显示用户的位图,在其他imageview上显示帧(相对布局)。位图可以缩放,拖动。之后,用户可以在此图像视图上合并2位图,如在屏幕上看到的那样。 我的问题是在缩放和拖动时获得imageview内部的位图。我想获得imageview内部位图的坐标以通过画布绘制(合并位图和框架)

我的代码

public class Overlapping extends Activity implements OnTouchListener {

    private Matrix matrix = new Matrix();
    private Matrix matrixTest = new Matrix();
    private Matrix savedMatrix = new Matrix();
    // we can be in one of these 3 states
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    private PointF start = new PointF();
    private PointF start1Up = new PointF();
    private PointF mid = new PointF();
    private float oldDist = 1f;
    private float d = 0f;
    private float[] lastEvent = null;

    public static float newRot = 0f; // lấy góc quay về
    public static float scale;

    float deltax, deltay = 0;

    ImageView view, topView;
    TextView textInfo;
    Button btSave;
    Bitmap bm1 = null;
    Bitmap bm2 = null;
    Bitmap newBitmap = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_overlapping);
        textInfo = (TextView) findViewById(R.id.textInfo);

        view = (ImageView) findViewById(R.id.bottomFrame);
        topView = (ImageView) findViewById(R.id.topFrame);
        bm1 = BitmapFactory.decodeResource(getResources(), R.drawable.test4);
        bm2 = BitmapFactory.decodeResource(getResources(), R.drawable.home_frame);

        Bitmap bitmap = Bitmap.createScaledBitmap(
                bm1,
                (int) (bm1.getWidth() / 1.6), (int) (bm1.getHeight() / 1.6),
                false
        );
        view.setImageBitmap(bitmap);
        view.setOnTouchListener(this);

        btSave = (Button) findViewById(R.id.btSave);
        btSave.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                Bitmap processedBitmap = ProcessingBitmap();
                topView.setImageBitmap(processedBitmap);
            }
        });
    }

    private Bitmap ProcessingBitmap() {
        try {
            int w = bm2.getWidth();
            int h = bm2.getHeight();

            Config config = bm1.getConfig();
            if (config == null) {
                config = Bitmap.Config.ARGB_8888;
            }

            newBitmap = Bitmap.createBitmap(w, h, config); // dùng cái này tùy
            Canvas newCanvas = new Canvas(newBitmap);
            Drawable drawables = view.getDrawable();
            Rect rectImage = drawables.getBounds();

            float[] newvalues = new float[9];
            matrixTest.getValues(newvalues);
            Bitmap rotatedBitmap = Bitmap.createBitmap(
                    bm1,
                    0,
                    0,
                    bm1.getWidth(),
                    bm1.getHeight(),
                    matrix,
                    true
            );
            topView.setImageBitmap(rotatedBitmap);
            newCanvas.drawBitmap(
                    rotatedBitmap,
                    (int) (deltax * rotatedBitmap.getWidth() / view.getWidth() / 1.45),
                    (int) (deltay * rotatedBitmap.getHeight() / view.getHeight() / 1.45),
                    null
            );
            newCanvas.drawBitmap(bm2, 0, 0, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newBitmap;
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // handle touch events here

        ImageView view = (ImageView) v;
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                savedMatrix.set(matrix);
                start.set(event.getX(), event.getY());
                mode = DRAG;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > 10f) {
                    savedMatrix.set(matrix);
                    midPoint(mid, event);
                    mode = ZOOM;
                }
                lastEvent = new float[4];
                lastEvent[0] = event.getX(0);
                lastEvent[1] = event.getX(1);
                lastEvent[2] = event.getY(0);
                lastEvent[3] = event.getY(1);
                d = rotation(event);
                break;
            case MotionEvent.ACTION_UP:
                break;
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                lastEvent = null;

                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {
                    matrix.set(savedMatrix);
                    float dx = event.getX() - start.x;
                    float dy = event.getY() - start.y;
                    matrix.postTranslate(dx, dy);

                } else if (mode == ZOOM) {
                    float newDist = spacing(event);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        scale = (newDist / oldDist);
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                    if (lastEvent != null && event.getPointerCount() == 2) {
                        newRot = rotation(event);
                        float r = newRot - d;
                        float[] values = new float[9];
                        matrix.getValues(values);
                        float tx = values[2];
                        float ty = values[5];
                        float sx = values[0];
                        float xc = (view.getWidth() / 2) * sx;
                        float yc = (view.getHeight() / 2) * sx;
                        matrix.postRotate(r, tx + xc, ty + yc);
                        matrixTest.set(matrix);
                    }
                }
                break;
        }

        view.setImageMatrix(matrix);
        return true;
    }

    /**
     * Determine the space between the first two fingers
     */
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /**
     * Calculate the mid point of the first two fingers
     */
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    /**
     * Calculate the degree to be rotated by.
     *
     * @param event
     * @return Degrees
     */
    private float rotation(MotionEvent event) {
        double delta_x = (event.getX(0) - event.getX(1));
        double delta_y = (event.getY(0) - event.getY(1));
        double radians = Math.atan2(delta_y, delta_x);
        return (float) Math.toDegrees(radians);
    }
}

XML:

<RelativeLayout
    android:id="@+id/RelativeLayout1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="left" >

    <ImageView
        android:id="@+id/bottomFrame"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_margin="10dp"
        android:paddingTop="2dip"
        android:src="@drawable/em"
        android:scaleType="matrix" />

    <ImageView
        android:id="@+id/topFrame"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_margin="10dp"
        android:scaleType="fitStart"
        android:src="@drawable/home_frame" />
</RelativeLayout>

3 个答案:

答案 0 :(得分:1)

我的应用程序中有同样的需求。这就是我所做的,希望它能帮到你。

public Bitmap mergeBitmaps() {
    Bitmap baseBitmap = ((BitmapDrawable) image.getDrawable()).getBitmap();

    Bitmap mergedBitmap = Bitmap.createBitmap(baseBitmap.getWidth(), baseBitmap.getHeight(), baseBitmap.getConfig());
    Canvas canvas = new Canvas(mergedBitmap);
    canvas.drawBitmap(baseBitmap, new Matrix(), null);

    for (ImageView sticker: stickers) {
        float viewSizeRatio = (float) sticker.getWidth() / image.getWidth();
        float bitmapSizeRatio = (float) sticker.getDrawable().getBounds().width() / image.getDrawable().getBounds().width();
        float ratioFactor = viewSizeRatio / bitmapSizeRatio;

        float deltaX = sticker.getTranslationX()* ratioFactor;
        float deltaY = sticker.getTranslationY()* ratioFactor;
        float scaleX = sticker.getScaleX()* ratioFactor;
        float scaleY = sticker.getScaleY()* ratioFactor;
        float rotation = sticker.getRotation();

        Matrix matrix = new Matrix();
        matrix.postScale(scaleX, scaleY);
        matrix.postRotate(rotation);
        matrix.postTranslate(deltaX, deltaY);

        Bitmap stickerBitmap = ((BitmapDrawable) sticker.getDrawable()).getBitmap();
        canvas.drawBitmap(stickerBitmap, matrix, null);
    }

    return mergedBitmap;
}

有一个名为&#34; image&#34;的基础ImageView(较大的一个)。这是在RelativeLayout,&amp;其他ImageViews命名为&#34;贴纸&#34;被添加到坐标{0,0}中的相对布局。它们将被拖拽,缩放和放大由用户轮换。最后你可以得到他们的翻译&amp;使用画布将主题与基本图像合并在一个位图中。

答案 1 :(得分:0)

尝试从多个图像中创建一个单一的位图。

您可以尝试使用原始数据, 通过从图像中提取像素数据作为32位整数ARGB像素阵列, 合并一个大数组,并使用Bitmap类的方法创建一个新的Bitmap,如copyPixelsToBuffer(),createBitmap()和setPixels()。

您也可以使用直接压缩格式数据和流以及BitmapFactory类的方法(如decodeByteArray())来实现。

如果您没有一次使用太多图像,可以使用单独的ImageView并回收它们/重新加载资源。

public static Bitmap mergeImage(Bitmap b1, Bitmap b2)
{
    Bitmap mBitmap = Bitmap.createBitmap(b1.getWidth(), b1.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(mBitmap);

    int adWDelta = (int)(b1.getWidth() - b2.getWidth())/2 ;
    int adHDelta = (int)(b1.getHeight() - b2.getHeight())/2;

    canvas.drawBitmap(b1, 0, 0, null);
    canvas.drawBitmap(b2, adWDelta, adHDelta, null);

    return mBitmap;
}

答案 2 :(得分:0)

如果您真的希望它像我们在屏幕上看到并且不关心合并图片的分辨率,您可以将父视图导出为如下图像:

void saveButtonPressed() {
    View parentView = findViewById(R.id.RelativeLayout1); //from your XML
    parentView.setDrawingCacheEnabled(true);
    Bitmap final_bitmap = parentView.getDrawingCache();
    String root = Environment.getExternalStorageDirectory().toString();
    String imageName = "Image-" + System.currentTimeMillis() + ".jpg";
    saveImage(final_bitmap, root, imageName);
}

public static boolean saveImage(Bitmap finalBitmap, String root, String image_name) {
    File myDir = new File(root);
    if (!myDir.exists()) {
        myDir.mkdirs();
    }
    File file = new File(myDir, image_name);
    if (file.exists()) file.delete();
    Log.i("LOAD", root + image_name);
    try {
        FileOutputStream out = new FileOutputStream(file);
        finalBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

这会将父视图的整个画布导出到图像中。确保您正在管理所需的权限。