Android 自定义相机 - 在矩形内裁剪图像

Posted

技术标签:

【中文标题】Android 自定义相机 - 在矩形内裁剪图像【英文标题】:Android Custom Camera - Crop image inside Rectangle 【发布时间】:2017-05-18 16:02:32 【问题描述】:

我有一个自定义的相机应用程序,它有一个居中的矩形视图,如下所示:

当我拍照时,我想忽略矩形之外的所有内容。该视图与我的 XML 视图中的 Camera Preview 或 SurfaceView 没有任何连接,如下所示:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_>
<FrameLayout
    android:id="@+id/preview"
    android:layout_
    android:layout_>
    <SurfaceView
        android:id="@+id/cameraview"
        android:name="com.kut.camera.KutCameraFragment"
        android:layout_
        android:layout_ />

    <View android:id="@+id/viewTamanho"
        android:layout_
        android:layout_
        android:layout_marginBottom="400px"
        android:layout_marginTop="300px"
        android:layout_marginStart="70px"
        android:layout_marginEnd="70px"
        android:background="@drawable/border" />

    <RelativeLayout
        android:id="@+id/rel_layout"
        android:layout_
        android:layout_ >

        <LinearLayout
            android:layout_
            android:layout_
            android:alpha="1"
            android:background="@android:color/black"
            android:orientation="vertical"
            android:padding="10dp" >

            <RelativeLayout
                android:layout_
                android:layout_ >

                <TextView
                    android:id="@+id/textViewReferan"
                    android:layout_
                    android:layout_
                    android:layout_centerHorizontal="true"
                    android:layout_centerVertical="true"
                    android:text="Evidência"
                    android:textColor="@android:color/white"
                    android:textSize="16sp" />

                <Button
                    android:id="@+id/button_exit"
                    android:layout_
                    android:layout_
                    android:layout_alignParentEnd="true"
                    android:layout_alignParentRight="true"
                    android:layout_alignParentTop="true"
                    android:background="@android:color/transparent"
                    android:text="Sair"
                    android:textColor="#2799CF" />
            </RelativeLayout>

            <LinearLayout
                android:id="@+id/progress_layout"
                android:layout_
                android:layout_
                android:layout_gravity="center"
                android:gravity="center"
                android:orientation="vertical"
                android:visibility="gone" >

                <ProgressBar
                    android:id="@+id/progressBar1"
                    android:layout_
                    android:layout_ />

                <TextView
                    android:id="@+id/islem_value_textView"
                    android:layout_
                    android:layout_
                    android:text="Carregando..." />

            </LinearLayout>
        </LinearLayout>

        <RelativeLayout
            android:id="@+id/RelativeLayout1"
            android:layout_
            android:layout_
            android:layout_alignParentBottom="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:alpha="0.9"
            android:background="@android:color/black"
            android:padding="10dp" >

            <ImageView
                android:id="@+id/imageView_foto"
                android:layout_
                android:layout_
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:src="@drawable/camera" />

            <ImageView
                android:id="@+id/imageView_photo"
                android:layout_
                android:layout_
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="5dp"
                android:layout_marginEnd="5dp"
                android:padding="5dp"
                android:scaleType="fitCenter"
                android:src="@drawable/fotoicon" />
        </RelativeLayout>
    </RelativeLayout>
</FrameLayout>

有人可以帮我如何正确裁剪图像吗?我试图基于我的 XML 创建一个新的位图,但显然它不起作用,类似于:

Camera.PictureCallback jpegCallback = new Camera.PictureCallback() 
    public void onPictureTaken(byte[] data, Camera camera) 
        //.../
        Bitmap imagemOriginal = BitmapFactory.decodeByteArray(data, 0, data.length);
        Bitmap imagemCortada = Bitmap.createBitmap(imagemOriginal, 70, 400, imagemOriginal.getWidth() - 70,
                imagemOriginal.getHeight() - 400);
        //.../
    

我为 x 和 y 设置了这些初始值,并尝试从宽度和高度中减去(基于来自 View 的 XML 值,指的是 marginTop、Bottom 等),但我没有成功,因为我没有知道如何将 View 坐标与从 Camera 获取的图像坐标相匹配。另外,对我来说,Bitmap.createBitmap 的裁剪似乎有限,显然我不能直接将它裁剪为矩形。

【问题讨论】:

究竟是什么不起作用?您的代码的主要问题是原始位图可能很大并且您的应用程序可能会耗尽内存。也许你没有正确配置你的相机,尤其是没有正确调用setPictureSize() 我说我不知道​​如何正确裁剪它以适应矩形的坐标。您在 Bitmap.createBitmap 中看到我为 x 和 y 输入初始值,并尝试从宽度和高度中减去值,但我无法找出正确的值。我只是把这些值放在那里,因为那是我在 XML 中从 marginTop、marginBottom 放的。另外,如果屏幕尺寸有范围,我怎么知道 setPictureSize() 的正确值是什么。 这里正在裁剪 ui 库 android-arsenal.com/details/1/207 如果您可以使用它,请查看它...或获取任何灵感 请检查这个对我有用的答案:***.com/a/63801992/6631601 【参考方案1】:

要控制裁剪,您必须控制图片大小和矩形大小。

非常重要a)选择与预览相同纵横比的图片尺寸,b)确保预览在屏幕上不失真.如果您为各种设备准备应用程序,那么这两项任务都不是微不足道的。要实现后者,您需要同时控制预览大小和 SurfaceView 大小。我已经更详细地解释了这一点elsewhere。

为简单起见,我建议忽略可能具有自然横向方向的平板电脑。在手机上,即使您将相机方向设置为纵向(仅影响预览),捕获的图像也会“旋转”90°。不要指望setRotation() 会为您解决这个问题:从书上讲,允许为捕获的图像简单地设置 EXIF 标志。

您将 viewTamanho 的边距设置为 px。这可能无法在各种屏幕上很好地扩展。我建议以编程方式将此视图的尺寸设置为预览表面的某个百分比。您可以使用support library 在 XML 中定义它,但恐怕这不会给您足够的控制权。

有了这一切,假设我们有 1280×720 的预览,2560×1440 的图片,我们的屏幕是 1280×800,矩形在中间,616×400 像素(或多或少)减去从您的屏幕截图缩放的大小)。

屏幕上的实际预览尺寸可能为 1000x562,左右填充,黑色边距为 79 像素。那么下面的代码就会产生预期的抓图:

public void onPictureTaken(byte[] data, Camera camera) 
    //.../
    Bitmap imagemOriginal = BitmapFactory.decodeByteArray(data, 0, data.length); // 2560×1440
    float scale = 1280/1000F;
    int left = (int) scale*(imagemOriginal.getWidth()-400)/2;
    int top = (int) scale*(imagemOriginal.getHeight()-616)/2;
    int width = (int) scale*400;
    int height = (int) scale*616;
    Matrix rotationMatrix = new Matrix();
    rotationMatrix.postRotate(90);
    Bitmap imagemCortada = Bitmap.createBitmap(imagemOriginal, left, top, width, height, rotationMatrix, false);
    //.../

【讨论】:

嗨 .. 它的工作原理.. 但对于特定设备.. 我们如何才能使其通用化? @VarunChandran 你需要什么概括?你试过什么? 我认为是因为相机中的图片大小,我使用了 setpicturesize(1600,1200)。但并非所有设备都支持? 如何选择图片尺寸? ***.com/questions/48642695/…请尝试回答这个问题【参考方案2】:

我在这里用了这个

implementation 'com.otaliastudios:cameraview:2.6.2'

拍照后获取位图的库。

这是我如何实现这一目标的代码

public void croppingRectangle (Bitmap bitmap, CameraView mCameraView, FrameLayout rectangle) 

int cameraHeight = mCameraView.getHeight();
int cameraWidth = mCameraView.getWidth();

    DisplayMetrics displayMetrics = new DisplayMetrics();
    getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

    int leftAndRightMarginsInPixels = Math.round(Math.round(getResources().getDimension(Your_dimens) * 2));`

我在这里做了缩放,拍照后

    int left = (int) Math.round(((double)rectangle.getX()/(double)cameraWidth) * bitmap.getWidth();
    int top = (int) Math.round(((double)rectangle.getY()/(double)cameraHeight) * bitmap.getHeight();
    int width =
            (int) (capturedWidth - Math.round(((double)leftAndRightMarginsInPixels / (double) displayMetrics.widthPixels) * bitmap.getWidth())); 
    int height = (int) Math.round(((double) rectangle.getHeight() / (double) displayMetrics.heightPixels) * bitmap.getHeight());

    Matrix rotationMatrix = new Matrix();
    rotationMatrix.postRotate(0);
    Bitmap croppedImage = Bitmap.createBitmap(bitmap, left, top, width, height, rotationMatrix, false);

P.S : 我已经达到了 95% 的顶部和底部准确率,70% 的框架宽度

【讨论】:

你是怎么得到上面的矩形视图的?我使用了相同的库,它只是在没有控件的情况下打开相机。如何启用它们?我在这里提到的 XML 中使用它:github.com/natario1/CameraView#setup 嘿@ShailendraMadda,您需要深入了解这个库,并且要使用cameraView捕获图像,您必须使用库中提到的方法。我上面提到的是关于在拍摄图片后裁剪图像。谢谢!如果您有任何问题,请告诉我 :) 干杯 请问有什么方法可以启用在此处显示预览图像的控件github.com/natario1/CameraView#setup? 我使用 FrameLayout 设置我的自定义图像(drawables),在 mCameraView 之上,库不支持这些类型的 UI 内容。你必须自己做。谢谢:) 是的,这就是我想知道为什么他们没有提供 UI 或控件来显示图片。我已经按照你说的做了,它也有效。但我想知道我们能否在库中启用这些图标,如编辑、捕获、快照、视频图标等,如图所示。

以上是关于Android 自定义相机 - 在矩形内裁剪图像的主要内容,如果未能解决你的问题,请参考以下文章

从 Swift 中的自定义相机拍摄后裁剪图像

Android 上的自定义裁剪

根据放置在相机上的视图裁剪图像的特定部分

Swift 中的自定义相机和裁剪图像

使用 Objective C 自定义相机捕捉图像和裁剪

在图像 Python 中裁剪自定义区域 [关闭]