将图像视图定位为相机预览上的叠加图像

时间:2016-07-11 14:35:24

标签: android imageview android-camera overlay android-bitmap

您好我在使用Android Camera API对相机应用进行编码!

它具有以下功能:

  • 该应用程序具有相机预览的图像视图
  • 用户可以将该图像视图拖放到相机预览上
  • 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;
}

xloc和yloc包含用户将删除该图像视图的位置!

这是我用来确定设备方向的代码。它由传感器完成,因为默认情况下,manifest.xml中的活动设置为纵向

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

        }

以下是捕获图片的代码

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

我在设置摄像机拍摄的照片上水印图像视图的位置时遇到问题!我只想设置水印图像视图的位置,以便用户拖放水印图像视图。

虽然代码可以正常工作,但在为不同设备拍摄的照片上设置水印图像视图位置时缺乏准确性和准确性。

我一直在尝试不同的设备,但每台设备都会扭曲准确的位置。

有人可以给我任何想法或更好的方法在相机拍摄的照片上添加水印图像!

请注意相机的ID为:

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

我需要一种方法,以便能够将水印图像放置在所有设备方向模式上,并且至少可以安装多个设备。

enter image description here 谢谢

假设当我在屏幕处于纵向位置时将图像视图拖到此蓝色按钮上时,图像应保存在相机拍摄的照片上,位于蓝色按钮上的相同位置! enter image description here

同样,如果我把它放在那个盒子上,相机拍摄的照片应该在横向模式下将该图像视图定位在该盒子上!

以下是

下使用的XML
     <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>

4 个答案:

答案 0 :(得分:0)

您可以将包含摄像机视图的视图和水印转换为位图并将其保存到手机存储器中,而无需直接从相机捕获图像。它将像截图一样工作。并且您的水印将被放置在它出现的相同位置。

确保“摄像机视图”和水印“图像 - 视图”位于同一父视图中,并将其父视图转换为位图。

Link可能会对您有所帮助。

答案 1 :(得分:0)

试试:

扩展SurfaceView并覆盖onDraw()方法。 在那里,您可以在预览中插入您的图像。你可以 之后将其添加到Jpeqcall中

答案 2 :(得分:0)

只需将Camera.PictureCallback替换为这个:

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

这可以解决您的问题。

答案 3 :(得分:0)

你可以使用这个library,这是一个Android的简单水印库,将XML(VIEW)转换为位图

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