How to combine overlay bitmap and captured image in android?

I have a requirement that I need to create a custom camera and allow the user to place the logo during image capture. The logo can be enlarged / resized and moved anywhere. I wrote the following code to do this, I was able to successfully enlarge / reduce the image and move the logo, but when I combine both the logo and the image taken from the camera, it does not fit correctly. The image of the logo placed elsewhere has been reduced. Please help me with this, as I am stuck here and could not find what is wrong. I also attached screenshots taken in my phone for reference. Please check this out.

I moved the logo to the lower left corner before clicking on the capture button

enter image description here

After clicking on the capture button, both images are combined as follows.

enter image description here

public class CustomCamera extends Activity implements OnTouchListener,
    SurfaceHolder.Callback {

private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
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 mid = new PointF();
private float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
private float[] lastEvent = null;
String logoImageId = "";
Bitmap bitmap = null;
private Camera camera = null;
private SurfaceView cameraSurfaceView = null;
private SurfaceHolder cameraSurfaceHolder = null;
private boolean previewing = false;
RelativeLayout relativeLayout;
int currentCameraId = 0;
private Button btnCapture = null;
ImageButton useOtherCamera = null;
ImageView logoImageView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFormat(PixelFormat.TRANSLUCENT);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.camera_layout);
    logoImageView = (ImageView) findViewById(R.id.logoImageView);
    Bundle extras = getIntent().getExtras();
    if (extras != null) {
        logoImageId = extras.getString("logoImageId ");
    }
    try {
        File file = new File(Environment.getExternalStorageDirectory()
                + "/" + getPackageName() + "/logo/" + logoImageId 
                + ".jpg");
        bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    logoImageView.setImageBitmap(bitmap);
    logoImageView.setOnTouchListener(this);
    relativeLayout = (RelativeLayout) findViewById(R.id.containerImg);
    relativeLayout.setDrawingCacheEnabled(true);
    cameraSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
    cameraSurfaceHolder = cameraSurfaceView.getHolder();
    cameraSurfaceHolder.addCallback(this);
    btnCapture = (Button) findViewById(R.id.button);
    btnCapture.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            camera.takePicture(null, null, cameraPictureCallbackJpeg);
        }
    });

}

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:
    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);
                float scale = (newDist / oldDist);
                matrix.postScale(scale, scale, mid.x, mid.y);
            }
            if (lastEvent != null && event.getPointerCount() == 3) {
                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);
            }
        }
        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);
}

PictureCallback cameraPictureCallbackJpeg = new PictureCallback() {
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        // TODO Auto-generated method stub
        Bitmap cameraBitmap = BitmapFactory.decodeByteArray(data, 0,
                data.length);

        int wid = cameraBitmap.getWidth();
        int hgt = cameraBitmap.getHeight();

        Bitmap newBitmap = Bitmap.createBitmap(wid, hgt,
                Bitmap.Config.ARGB_8888);

        Canvas canvas = new Canvas(newBitmap);
        canvas.drawBitmap(cameraBitmap, 0f, 0f, null);
        canvas.drawBitmap(bitmap, matrix, null);

        File storagePath = new File(
                Environment.getExternalStorageDirectory() + "/PhotoAR/");
        storagePath.mkdirs();

        File myImage = new File(storagePath, Long.toString(System
                .currentTimeMillis()) + ".jpg");

        try {
            FileOutputStream out = new FileOutputStream(myImage);
            newBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);

            out.flush();
            out.close();
        } catch (FileNotFoundException e) {
            Log.d("In Saving File", e + "");
        } catch (IOException e) {
            Log.d("In Saving File", e + "");
        }

    }
};

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

    if (previewing) {
        camera.stopPreview();
        previewing = false;
    }
    try {

        if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
            camera.setDisplayOrientation(90);
        }

        camera.setPreviewDisplay(cameraSurfaceHolder);
        camera.startPreview();
        previewing = true;
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    try {
        camera = Camera.open();
    } catch (RuntimeException e) {
        Toast.makeText(
                getApplicationContext(),
                "Device camera  is not working properly, please try after sometime.",
                Toast.LENGTH_LONG).show();
    }
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera.stopPreview();
    camera.release();
    camera = null;
    previewing = false;
}

}

and this is my xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<RelativeLayout
    android:id="@+id/containerImg"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true" />

    <ImageView
        android:id="@+id/logoImageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:contentDescription="@string/app_name"
        android:scaleType="matrix" />
</RelativeLayout>

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right|center_vertical"
    android:background="@drawable/camera" />

Thanks in advance.

+4
source share
3 answers

Ok, there are a few things to fix.

  • Set the correct size to view the surface size that you use for the camera.
  • rotate the captured bitmap according to the orientation of the screen
  • your code will have an error from memory, because you load it correctly into memory and do not process it (I won’t fix it, you will find the answer if you specified google :): search injustdecodebounds and bitmap conversion)

, , :

    public class CameraActivity extends FragmentActivity implements OnTouchListener,
        SurfaceHolder.Callback {

    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    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 mid = new PointF();
    private float oldDist = 1f;
    private float d = 0f;
    private float newRot = 0f;
    private float[] lastEvent = null;
    String logoImageId = "";
    Bitmap bitmap = null;
    private Camera camera = null;
    private SurfaceView cameraSurfaceView = null;
    private SurfaceHolder cameraSurfaceHolder = null;
    private boolean previewing = false;
    RelativeLayout relativeLayout;
    int currentCameraId = 0;
    private Button btnCapture = null;
    ImageButton useOtherCamera = null;
    ImageView logoImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_camera);
        logoImageView = (ImageView) findViewById(R.id.logoImageView);
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            logoImageId = extras.getString("logoImageId ");
        }
        try {
            /*File file = new File(Environment.getExternalStorageDirectory()
                    + "/" + getPackageName() + "/logo/" + logoImageId
                    + ".jpg");
            bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());*/
            bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
            logoImageView.setImageBitmap(bitmap);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        logoImageView.setOnTouchListener(this);
        relativeLayout = (RelativeLayout) findViewById(R.id.containerImg);
        relativeLayout.setDrawingCacheEnabled(true);
        cameraSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        cameraSurfaceHolder = cameraSurfaceView.getHolder();
        cameraSurfaceHolder.addCallback(this);
        btnCapture = (Button) findViewById(R.id.button);
        btnCapture.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                camera.takePicture(null, null, cameraPictureCallbackJpeg);
            }
        });

    }

    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:
            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);
                        float scale = (newDist / oldDist);
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                    if (lastEvent != null && event.getPointerCount() == 3) {
                        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);
                    }
                }
                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);
    }

    Camera.PictureCallback cameraPictureCallbackJpeg = new Camera.PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
            // TODO Auto-generated method stub
            BitmapFactory.Options options = new BitmapFactory.Options();
            //o.inJustDecodeBounds = true;
            Bitmap cameraBitmapNull = BitmapFactory.decodeByteArray(data, 0,
                    data.length, options);

            int wid = options.outWidth;
            int hgt = options.outHeight;
            Matrix nm = new Matrix();

            Camera.Size cameraSize = camera.getParameters().getPictureSize();
            float ratio = relativeLayout.getHeight()*1f/cameraSize.height;
            if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
                nm.postRotate(90);
                nm.postTranslate(hgt, 0);
                wid = options.outHeight;
                hgt = options.outWidth;
                ratio = relativeLayout.getWidth()*1f/cameraSize.height;

            }else {
                wid = options.outWidth;
                hgt = options.outHeight;
                ratio = relativeLayout.getHeight()*1f/cameraSize.height;
            }

            float[] f = new float[9];
            matrix.getValues(f);

            f[0] = f[0]/ratio;
            f[4] = f[4]/ratio;
            f[5] = f[5]/ratio;
            f[2] = f[2]/ratio;
            matrix.setValues(f);

            Bitmap newBitmap = Bitmap.createBitmap(wid, hgt,
                    Bitmap.Config.ARGB_8888);

            Canvas canvas = new Canvas(newBitmap);
            Bitmap cameraBitmap = BitmapFactory.decodeByteArray(data, 0,
                    data.length, options);

            canvas.drawBitmap(cameraBitmap, nm, null);
            cameraBitmap.recycle();

            canvas.drawBitmap(bitmap, matrix, null);
            bitmap.recycle();

            File storagePath = new File(
                    Environment.getExternalStorageDirectory() + "/PhotoAR/");
            storagePath.mkdirs();

            File myImage = new File(storagePath, Long.toString(System
                    .currentTimeMillis()) + ".jpg");

            try {
                FileOutputStream out = new FileOutputStream(myImage);
                newBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);

                out.flush();
                out.close();
            } catch (FileNotFoundException e) {
                Log.d("In Saving File", e + "");
            } catch (IOException e) {
                Log.d("In Saving File", e + "");
            }

        }
    };

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
        // TODO Auto-generated method stub

        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }
        try {

            if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
                camera.setDisplayOrientation(90);
                Camera.Size cameraSize = camera.getParameters().getPictureSize();
                int wr = relativeLayout.getWidth();
                int hr = relativeLayout.getHeight();
                float ratio = relativeLayout.getWidth()*1f/cameraSize.height;
                float w = cameraSize.width*ratio;
                float h = cameraSize.height*ratio;
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams((int)h, (int)w);
                cameraSurfaceView.setLayoutParams(lp);
            }else {
                camera.setDisplayOrientation(0);
                Camera.Size cameraSize = camera.getParameters().getPictureSize();
                float ratio = relativeLayout.getHeight()*1f/cameraSize.height;
                float w = cameraSize.width*ratio;
                float h = cameraSize.height*ratio;
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams((int)w, (int)h);
                cameraSurfaceView.setLayoutParams(lp);
            }

            camera.setPreviewDisplay(cameraSurfaceHolder);
            camera.startPreview();
            previewing = true;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        try {
            camera = Camera.open();
            Camera.Parameters params = camera.getParameters();

            // Check what resolutions are supported by your camera
            List<Camera.Size> sizes = params.getSupportedPictureSizes();

            // setting small image size in order to avoid OOM error
            Camera.Size cameraSize = null;
            for (Camera.Size size : sizes) {
                //set whatever size you need
                //if(size.height<500) {
                    cameraSize = size;
                    break;
                //}
            }

            if (cameraSize != null) {
                params.setPictureSize(cameraSize.width, cameraSize.height);
                camera.setParameters(params);

                float ratio = relativeLayout.getHeight()*1f/cameraSize.height;
                float w = cameraSize.width*ratio;
                float h = cameraSize.height*ratio;
                RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams((int)w, (int)h);
                cameraSurfaceView.setLayoutParams(lp);
            }
        } catch (RuntimeException e) {
            Toast.makeText(
                    getApplicationContext(),
                    "Device camera  is not working properly, please try after sometime.",
                    Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }
}

note , OOM

+3

; , .

, " ":

  • .
  • ( , )
  • .
+1

, Ovelay , . .

, .

public Bitmap combineImages(Bitmap frame, Bitmap image) {
        Bitmap cs = null;
        Bitmap rs = null;

        rs = Bitmap.createScaledBitmap(frame, image.getWidth() + 50,
                image.getHeight() + 50, true);

        cs = Bitmap.createBitmap(rs.getWidth(), rs.getHeight(),
                Bitmap.Config.RGB_565);

        Canvas comboImage = new Canvas(cs);

        comboImage.drawBitmap(image, 25, 25, null);
        comboImage.drawBitmap(rs, 0, 0, null);
        if (rs != null) {
            rs.recycle();
            rs = null;
        }
        Runtime.getRuntime().gc();
        return cs;
    }

, .

, .

1) android

2)

3)

+1

Source: https://habr.com/ru/post/1613235/


All Articles