10

Hello There I am coding a Camera App using Android Camera API!

It has the following functions:

  • The app has an image view over the camera preview
  • The user can drag and drop that image view on the camera preview
  • The drop event catch the position of the image view where it dropped
  • The user captures an image and the image view is being added on the photo on the user's desired drag then dropped location

Here is the code that is used for the image view drag and drop:

@Override
public boolean onTouch(View view, MotionEvent event) {
    final int X = (int) event.getRawX();
    final int Y = (int) event.getRawY();
    switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
            _xDelta = X - lParams.leftMargin;
            _yDelta = Y - lParams.topMargin;
            break;
        case MotionEvent.ACTION_UP:
            xloc=X;
            yloc=Y;
            Toast.makeText(getContext(), "Location==="+Integer.toString(xloc)+"==="+Integer.toString(yloc), Toast.LENGTH_SHORT).show();
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            break;
        case MotionEvent.ACTION_POINTER_UP:
            break;
        case MotionEvent.ACTION_MOVE:
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
                    .getLayoutParams();
            layoutParams.leftMargin = X - _xDelta;
            layoutParams.topMargin = Y - _yDelta;
            layoutParams.rightMargin = -250;
            layoutParams.bottomMargin = -250;
            view.setLayoutParams(layoutParams);
            break;
    }
    mRrootLayout.invalidate();
    return true;
}

The xloc and yloc contains the postion where the user will drop that image view!


This is the code I am using to determine the device orientation. It is being done by the sensor because the activity is set to portrait in manifest.xml by default

        @Override
        public void onSensorChanged(SensorEvent event) {
            float x = event.values[0];
            float y = event.values[1];

            if (x < 5 && x > -5 && y > 5){
                //portrait UP ↑↑↑
                cam_orientation = 0;
                image_watermark.setRotation(0); //rotating the water mark with screen orientation
            }
            else if (x<-5 && y<5 && y>-5) {
                //landscape RIGHT →→→
                cam_orientation = 3;
                image_watermark.setRotation(270);
            }
            else if (x<5 && x>-5 && y<-5) {
                //Portrait DOWN ↓↓↓
                cam_orientation = 4;
                image_watermark.setRotation(0);
            }
            else if (x>5 && y<5 && y>-5){
                //Landscape LEFT ←←←
                cam_orientation = 1;
                image_watermark.setRotation(90);
            }

        }

Here is the code for capturing the image

   private Camera.PictureCallback mPicture = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {

        File pictureFile = getOutputMediaFile(1);
        if (pictureFile == null){
            Log.i("#LOGTAG pic","Exception");
            return;
        }

        try {
            //rotate the image view as expected
            BitmapFactory.Options options = new BitmapFactory.Options();
            Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length, options);


            if(cam_orientation==0){
                //portrait UP ↑↑↑
                if(cam_id==1){
                    //this is front camera id=1
                    mBitmap= rotate(mBitmap, 270);
                    mBitmap=flip(mBitmap);
                }
                if(cam_id==0){
                    mBitmap= rotate(mBitmap, 90);
                }
            }

            if(cam_orientation==1){
                //Landscape LEFT ←←←
                if(cam_id==1){
                    //this is front camera id=1
                    mBitmap= rotate(mBitmap, 0);
                    mBitmap=flip(mBitmap);
                }
                if(cam_id==0){
                    //this is back camera id=0
                    mBitmap= rotate(mBitmap, 0);
                }
            }

            if(cam_orientation==3){
                //landscape RIGHT →→→
                if(cam_id==1){
                    //this is front camera id=1
                    mBitmap= rotate(mBitmap, 180);
                    mBitmap=flip(mBitmap);
                }
                if(cam_id==0){
                    //this is back camera id=0
                    mBitmap= rotate(mBitmap, 180);
                }
            }

            if(cam_orientation==4){
                //Portrait DOWN ↓↓↓
                if(cam_id==1){
                    //this is front camera id=1
                    mBitmap= rotate(mBitmap, 90);
                    mBitmap=flip(mBitmap);
                }
                if(cam_id==0){
                    //this is back camera id=0
                    mBitmap= rotate(mBitmap, 270);
                }
            }

            //add the water mark to the camera photo bitmap here
            Bitmap mutableBitmap = mBitmap.copy(Bitmap.Config.ARGB_8888, true);

            image_watermark.buildDrawingCache();
            Bitmap bmap = image_watermark.getDrawingCache();

            Bitmap final_image=Bitmap.createScaledBitmap(bmap,(image_watermark.getMeasuredWidth())*2,(image_watermark.getMeasuredWidth())*2,false);
            Canvas canvas = new Canvas(mutableBitmap);

            if(cam_id==1){
                canvas.drawBitmap(icon,(int)(xloc*1.5),(int)(yloc*1.5), null); //setting the location of the water mark image view on front camera/photo
            }

            if(cam_id==0){
                canvas.drawBitmap(icon,xloc*2,yloc*2, null);
                 //setting the location of the water mark image view on back camera/photo
            }

            FileOutputStream fos = new FileOutputStream(pictureFile);
            mutableBitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);

            fos.close();
}

I have a problem of setting up the location of water mark image view on the captured photo from the camera! I just want to set the location of the water mark image view to be set where the user dragged and dropped that water mark image view.

Though the code works alright, but there is a lack of precision and accuracy in setting up the water mark image view location on captured photo for different devices.

I have been trying on different devices, but each device distorts the accurate position.

Can somebody give me any idea or a better approach to add a water mark image on the camera captured photo!

Please Note That the ids for camera are:

   cam_id=1 for the from camera
   cam_id=0 for the back camera

I need an approach, so that I could able to position my water mark image on all device orientation modes and for at least some multiple devices.

enter image description here Thanks

Suppose that if i drag my image view on this blue button when the screen is in portrait position, the image should be save on the camera captured photo on the same location that is on the blue button! enter image description here

Similarly, if i placed it on that box the camera captured photo should position this image view same on that box in landscape mode!

Here is the used XML below

     <RelativeLayout
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"
tools:context="">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@color/colorAccent">
        <ToggleButton
            android:id="@+id/flipper"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:background="@drawable/my_btn_toggle"
            android:textOff=""
            android:textOn=""/>
    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="10"
        android:id="@+id/root">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/camera_preview">


        </FrameLayout>

        <ImageView
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:id="@+id/watermark"
            />

    </RelativeLayout>

<LinearLayout
  android:layout_width="match_parent"
  android:layout_height="0dp"
  android:layout_weight="1"
  android:background="#000"
  android:layout_alignParentBottom="true"
  android:gravity="center"
  android:id="@+id/capture_layout">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/capture"
        android:text="Capture"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"/>

   <Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/neg"
    android:text="Cancel Para"
    android:layout_alignParentBottom="true"
    android:layout_alignParentRight="true"/>

 </LinearLayout>
  </LinearLayout>
</RelativeLayout>
Android Nerd
  • 625
  • 1
  • 8
  • 13
Java Nerd
  • 958
  • 3
  • 19
  • 51

4 Answers4

0

You can convert View Containing Camera View and your water mark to bitmap and save it to your phone memory without capturing Image directly from camera. It will work like a screenshot. And your watermark will be placed on the same location its appearing.

Make sure both the Camera View and watermark Image-View are in same parent view and convert their parent view to bitmap.

This Link may help you.

Community
  • 1
  • 1
abdul khan
  • 843
  • 2
  • 7
  • 24
0

Try that :

Extend your SurfaceView and Override the onDraw() Method. There you can insert your Image in the preview. And you can add it in the Jpeqcall after that

Ahmet K
  • 713
  • 18
  • 42
0

Just replace your Camera.PictureCallback with this one:

private Camera.PictureCallback mPicture = new Camera.PictureCallback() 
{
    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        File pictureFile = getOutputMediaFile(1);
        if (pictureFile == null){
            Log.i("#LOGTAG pic","Exception");
            return;
        }

        //rotate the image view as expected
        Bitmap mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

        if(cam_orientation==0){
            //portrait UP ↑↑↑
            if(cam_id==1){
                //this is front camera id=1
                mBitmap= rotate(mBitmap, 270);
                mBitmap=flip(mBitmap);
            }
            if(cam_id==0){
                mBitmap= rotate(mBitmap, 90);
            }
        }

        if(cam_orientation==1){
            //Landscape LEFT ←←←
            if(cam_id==1){
                //this is front camera id=1
                mBitmap= rotate(mBitmap, 0);
                mBitmap=flip(mBitmap);
            }
            if(cam_id==0){
                //this is back camera id=0
                mBitmap= rotate(mBitmap, 0);
            }
        }

        if(cam_orientation==3){
            //landscape RIGHT →→→
            if(cam_id==1){
                //this is front camera id=1
                mBitmap= rotate(mBitmap, 180);
                mBitmap=flip(mBitmap);
            }
            if(cam_id==0){
                //this is back camera id=0
                mBitmap= rotate(mBitmap, 180);
            }
        }

        if(cam_orientation==4){
            //Portrait DOWN ↓↓↓
            if(cam_id==1){
                //this is front camera id=1
                mBitmap= rotate(mBitmap, 90);
                mBitmap=flip(mBitmap);
            }
            if(cam_id==0){
                //this is back camera id=0
                mBitmap= rotate(mBitmap, 270);
            }
        }

        Bitmap newImage = Bitmap.createBitmap(
            mBitmap.getWidth(), 
            mBitmap.getHeight(), 
            Bitmap.Config.ARGB_8888
        );

        Canvas canvas = new Canvas(newImage);
        canvas.drawBitmap(mBitmap, 0f, 0f, null);

        image_watermark.buildDrawingCache();
        Drawable drawable = new BitmapDrawable(getResources(), image_watermark.getDrawingCache());
        drawable.setBounds(
            xloc, 
            yloc, 
            image_watermark.getMeasuredWidth() + xloc, 
            image_watermark.getMeasuredHeight() + yloc
        );
        drawable.draw(canvas);

        try
        {
            FileOutputStream out = new FileOutputStream(pictureFile);
            newImage.compress(Bitmap.CompressFormat.JPEG, 100, out);

            out.flush();
            out.close();
        }
        catch (Exception e) {
            Log.d("In Saving File", e.getMessage(), e);
        }

        Log.d("Image", "Pic taken!");

        // Camera preview should be started again after taking a picture
        camera.startPreview();

        // Release image
        newImage.recycle();
        newImage = null;
    }
}

This should solve your problem.

S. Brukhanda
  • 132
  • 10
0

You can use this library, this is a Simple Watermark Library for Android, converting XML (VIEW) to bitmap

private Bitmap generateWaterMark(Bitmap src) {

    //src is your original image, like camera preview
    WaterMark waterMark = new WaterMark(this);
    View view = getLayoutInflater().inflate(R.layout.register_email_layout, null, false);

    //Manipulate your view like you prefer, then invoke the method getImageWaterMarkFromView

    return waterMark.getImageWaterMarkFromView(src, view);
}