Schwoebel
Schwoebel

Reputation: 216

Overlay camera with resizeable/re-positionable item than upon click merge the images together

I need to let a user move an image around on the screen and resize it too.

That part I have accomplished already.

The part that I can't figure out is how to, upon taking a picture, freeze the moveable/resizable Image on the photo-image than merge the two together to make 1 Bitmap.

I don't really have any "snippets" of code to post. I am just hoping some people may have had an experience with this before and might care to shed some light.

EDIT. I understand that when I take the picture the image is already frozen on the screen. At that instance I capture the items location on canvas. What I need to do is to take the canvas that I already have something drawn on and somehow overlay that onto another canvas that I assigned the photo too.

EDIT #2

OK ladies and gentlemen. I figured it out. Here is the code for making an overlay for the camera (as described by mmeyer.)

    Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] imageData, Camera c) {
        Context ct = new Context;

        RelativeLayout relativeview = new RelativeLayout(ct);
        if (imageData != null) {
            Context ct = HagsCamera.this;
            new Intent(ct, PreviewandSend.class);

        Bitmap photo = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);
        int picwidth= (photo.getWidth()/2);
        int picheight = (photo.getHeight()/2);

        Bitmap photocopy = Bitmap.createScaledBitmap(photo, picwidth, picheight,     false);
            Canvas c2 = crv.canvastoreturn;
            c2.setBitmap(photocopy);
        //photo.recycle();  

        ImageView newImage = new ImageView(ct);
        relativeview.addView(newImage);
        relativeview.draw(c2);
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                photo.getWidth()/2, photo.getHeight()/2);
        relativeview.setLayoutParams(lp);

Good luck to you all. I hope this helps save alot of headaches.

In short: Make a Bitmap of your picture.
Make a canvas for your overlay and toss your stuff up on there
Get a copy of your overlay's canvas
.setBitmap() that canvas and set it to your photo-bitmap.
Make a RelativeLayout and add a new ImageView to that.
Draw your canvas on the ImageView.
then figure out your layout parameters for your RelativeLayout.

Now that I think about it, maybe you can just set the top layer canvas to your Photo's Bitmap...and just save that...... You can test that yourself.

Upvotes: 1

Views: 820

Answers (1)

mmeyer
mmeyer

Reputation: 3608

I done something in the past where I have an overlay view on top of a surface view which holds camera preview.

When the user wants to capture the pic, I take the next preview frame from Camera.PreviewCallback.onPreviewFrame() and then convert that from YUV to bitmap.

I then get a canvas against that bitmap and pass that canvas to the Draw() method of the custom view class that is my overlay view, and it will draw whatever it had been drawing onscreen to my new canvas! I can then take the bitmap and save it a jpg/png to SD.

Note that within that custom view class it has to deal with scaling due to the fact that the canvas it gets when being asked to draw on screen is a different size than the canvas it is given when asked to draw onto the canvas from the preview frame.

Beware of preview sizes and out of memory errors here though as many phones have very large default preview frame sizes and making bitmaps to draw onto with canvas can chew up memory fast. Learn about how to use Bitmap.recycle() and how to monitor native heap to combat these.

Hope that helps.

After reading the follow up comments and the issue youre having with black/blank images I decided to post some psuedo code to show how I'm doing this...

// decode the camera data into an immutable bitmap
Bitmap raw = CameraHelper.decodeYUV(frameInfo.frameData, frameInfo.frameSize.x, frameInfo.frameSize.y);
frameInfo.frameData = null; // allow large bytearry to to get gc'd

Bitmap cameraPic = raw.copy(Bitmap.Config.RGB_565, true);   // make a mutable copy
Canvas c2 = (new Canvas(cameraPic));        // create a canvas from the camera pic

raw.recycle(); // we're done with raw bitmap now and can reclaim from native heap.

reticleOverlay.draw(c2); // reticle overlay is a class that implements View

String filename = acquireNextShotFilename()); // get a filename to write to SD
 FileOutputStream fileoutputStream;
try {
    fileoutputStream = new FileOutputStream(filename);
 } catch (FileNotFoundException e) {
    MyLogger.e("Couldnt open fileoutputstream: ", e);
    throw e;
}  

cameraPic.compress(CompressFormat.PNG, 100, fileoutputStream);
cameraPic.recycle();
try {
    fileoutputStream.flush();
    fileoutputStream.close();
} catch (IOException e) {
    MyLogger.e("Error writing to file: ", e);
    fileoutputStream.close();
} 

Upvotes: 1

Related Questions