Поместите изображение в виде наложения на изображение камеры

Привет, я кодирую приложение камеры с помощью API камеры Android!

Он имеет следующие функции:

  • Приложение имеет представление изображения над просмотром камеры
  • Пользователь может перетащить этот вид изображения на предварительный просмотр камеры
  • Событие перехвата задерживает положение изображения, где оно упало.
  • Пользователь фиксирует изображение, а изображение отображается на фотографии на нужном пользователю перетаскивании, а затем удаляется.

Вот код, который используется для перетаскивания изображения:

@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 содержится позиция, в которой пользователь откажется от этого изображения!


Это код, который я использую для определения ориентации устройства. Это делается датчиком, потому что по умолчанию для параметра activity.xml установлено значение portrait

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

У меня проблема с настройкой местоположения изображения с изображением водяной метки на захваченной фотографии с камеры! Я просто хочу установить местоположение изображения изображения водяной метки, которое будет установлено, когда пользователь перетащил и опустил изображение с изображением водяной метки.

Несмотря на то, что код работает хорошо, но есть недостаток точности и точности в настройке местоположения изображения изображения с водяной меткой на снятой фотографии для разных устройств.

Я пытаюсь использовать разные устройства, но каждое устройство искажает точное положение.

Может кто-нибудь дать мне какие-либо идеи или лучший подход, чтобы добавить изображение водяной метки на фотографию, снятую камерой?

Обратите внимание, что идентификаторы для камеры:

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

Мне нужен подход, чтобы я мог разместить изображение водяной метки во всех режимах ориентации устройства и, по крайней мере, для нескольких устройств.

введите описание изображения здесь Спасибо

Предположим, что если я перетащил изображение на эту синюю кнопку, когда экран находится в портретном положении, изображение должно быть сохранено на фотографии, снятой камерой, в том же месте, что и на синей кнопке! введите описание изображения здесь

Точно так же, если я поместил его на этот ящик, фотокамера, снятая камерой, должна позиционировать это изображение в том же окне в ландшафтном режиме!

Здесь используется 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>

Ответ 1

Вы можете преобразовать View Containing Camera View и вашу водную метку в растровое изображение и сохранить его в памяти телефона без захвата изображения непосредственно с камеры. Он будет работать как скриншот. И ваш водяной знак будет размещен в том же месте, где он появится.

Убедитесь, что изображение "Просмотр камеры" и "Изображение с водяным значком" находятся в одном и том же родительском представлении и преобразуют их родительское представление в растровое изображение.

Эта Ссылка может вам помочь.

Ответ 2

Попробуйте следующее:

Расширьте SurfaceView и переопределите метод onDraw(). Там вы можете вставить свое изображение в предварительный просмотр. И вы можете добавьте его в Jpeqcall после этого

Ответ 3

Просто замените 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;
    }
}

Это должно решить вашу проблему.

Ответ 4

Вы можете использовать эту библиотеку, это простая библиотека водяных знаков для 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);
}