草庐IT

android - 拍摄覆盖范围内的照片

coder 2023-12-05 原文

我正在尝试开发这个简单的拍照应用。一切都很好。我唯一在预览中心有一个固定大小的椭圆形 ImageView 。捕获图像工作正常,但问题是 我想捕获位于椭圆形 ImageView 内的图像并自动裁剪它。我不想保存整个图像,我只想要位于形状内的图像部分。 现在,我不知道如何继续。在谷歌上花了几个小时寻找解决方案后,我决定我不得不放弃并来到这里。我不明白我怎么才能只得到位于形状内的那部分图像(那个固定的椭圆形图像)。

这是我的代码:-

 public class MainActivity extends Activity implements SurfaceHolder.Callback {

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean cameraview = false;
    LayoutInflater inflater = null;
    private ImageView ImgContainer;
    private Button btn;
    private ImageView mIvCaptureImage;
    FrameLayout frameLayout;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        getWindow().setFormat(PixelFormat.UNKNOWN);
        frameLayout = (FrameLayout) findViewById(R.id.view);
        surfaceView = (SurfaceView) findViewById(R.id.camera_preview);
        ImgContainer = (ImageView) findViewById(R.id.Img_container);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        // GuideBox box = new GuideBox(MainActivity.this);
        // llContainer.addView(box, new LayoutParams(LayoutParams.WRAP_CONTENT,
        // LayoutParams.WRAP_CONTENT));
        btn = (Button) findViewById(R.id.button);
        mIvCaptureImage = (ImageView) findViewById(R.id.imageview1);
        btn.setOnClickListener(new OnClickListener() {

            @SuppressWarnings("deprecation")
            @Override
            public void onClick(View v) {
                if (camera != null) {
                    camera.takePicture(myShutterCallback,
                            myPictureCallback_RAW, myPictureCallback_JPG);

                }

            }
        });

    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @SuppressWarnings("deprecation")
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
        if (cameraview) {
            camera.stopPreview();
            cameraview = false;
        }

        if (camera != null) {
            try {
                setCameraDisplayOrientation(this,
                        CameraInfo.CAMERA_FACING_BACK, camera);
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                cameraview = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    @SuppressWarnings("deprecation")
    private void setCameraDisplayOrientation(Activity activity, int cameraId,
            android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
        case Surface.ROTATION_0:
            degrees = 0;
            break;
        case Surface.ROTATION_90:
            degrees = 90;
            break;
        case Surface.ROTATION_180:
            degrees = 180;
            break;
        case Surface.ROTATION_270:
            degrees = 270;
            break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }

    ShutterCallback myShutterCallback = new ShutterCallback() {

        public void onShutter() {
            // TODO Auto-generated method stub
        }
    };

    PictureCallback myPictureCallback_RAW = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
            // TODO Auto-generated method stub

        }
    };

    PictureCallback myPictureCallback_JPG = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
            // TODO Auto-generated method stub
            Rect rc = getViewPositionRelative();
            Bitmap bitmapPicture = BitmapFactory.decodeByteArray(data, 0,
                    data.length);
            Matrix mat = new Matrix();
            mat.postRotate(90);
            Bitmap correctBmp = Bitmap.createBitmap(bitmapPicture, rc.left,
                    rc.top, ImgContainer.getWidth(), ImgContainer.getHeight(),
                    mat, true);
            // Bitmap circularBitmap = ImageConverter.getRoundedCornerBitmap(
            // correctBmp, 100);
            mIvCaptureImage.setImageBitmap(correctBmp);
        }
    };

    public Rect getViewPositionRelative() {
        // Locate on screen
        int[] location = new int[2];
        ImgContainer.getLocationOnScreen(location); 

        Rect rect = new Rect();
        rect.left = location[0];
        rect.top = location[1];
        rect.right = rect.left + ImgContainer.getWidth();
        rect.bottom = rect.top + ImgContainer.getHeight();
        return rect;
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera = Camera.open();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
        camera = null;
        cameraview = false;
    }
}

第二种方法:-

PictureCallback myPictureCallback_JPG = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, android.hardware.Camera camera) {
        Boolean isSDPresent = android.os.Environment
                .getExternalStorageState().equals(
                        android.os.Environment.MEDIA_MOUNTED);

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
                Locale.getDefault()).format(new Date());

        // checking for SD card
        if (isSDPresent) {
            mediaStorageDir = new File(Environment
                    .getExternalStorageDirectory().getAbsolutePath(),
                    IMAGE_DIRECTORY_NAME);

            mediaFile = new File(mediaStorageDir.getPath() + File.separator
                    + "IMG_" + timeStamp + ".jpg");

            // Create the storage directory if it does not exist
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                }
            }

            try {
                Bitmap userImage = BitmapFactory.decodeByteArray(data, 0,
                        data.length);

                // set file out stream
                FileOutputStream out = new FileOutputStream(mediaFile);
                // set compress format quality and stream
                userImage.compress(Bitmap.CompressFormat.JPEG, 100, out);

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                userImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);

                try {
                    out.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else {
            Toast.makeText(getApplicationContext(),
                    "Please insert SD card !", Toast.LENGTH_LONG).show();

        }
        if (mediaStorageDir.exists()) {
            getPathOfCapturedImage();
        }

    }
};

private void getPathOfCapturedImage() {
    final String ImagePath = mediaFile.getAbsolutePath();
    Bitmap bitmap = BitmapFactory.decodeFile(ImagePath);

    int bitWidth = bitmap.getWidth();
    int bitHeight = bitmap.getHeight();

    // 3. Size of camera preview on screen
    int preWidth = surfaceView.getWidth();
    int preHeight = surfaceView.getHeight();

    Rect rc = getViewPositionRelative();
    Matrix mat = new Matrix();
    mat.postRotate(90);

    int startx = rc.left * bitWidth / preWidth;
    int starty = rc.top * bitHeight / preHeight;
    int endx = rc.right * bitWidth / preWidth;
    int endy = rc.bottom * bitHeight / preHeight;

    Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, startx, starty,
            endx, endy);
    mIvCaptureImage.setImageBitmap(resizedBitmap);
}

public Rect getViewPositionRelative() {
    // Locate on screen
    int[] location = new int[2];
    ImgContainer.getLocationOnScreen(location);

    Rect rect = new Rect();
    rect.left = location[0];
    rect.top = location[1];
    rect.right = rect.left - ImgContainer.getWidth();
    rect.bottom = rect.top - ImgContainer.getHeight();
    return rect;
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera = Camera.open();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    camera.stopPreview();
    camera.release();
    camera = null;
    cameraview = false;
}

XML:-

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout
        android:id="@+id/view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight=".6" >

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

        <ImageView
            android:id="@+id/Img_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:background="@drawable/eclipce"/>
    </FrameLayout>

    <ImageView
        android:id="@+id/imageview1"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_weight=".2" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_gravity="center"
        android:layout_weight=".2"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="Capture" />
    </LinearLayout>

</LinearLayout>

所以,如果有人知道任何事情,请告诉我。

谢谢

最佳答案

一直在玩这个。这是我解决它的方法:

1) 只需拍下照片,就可以拍出漂亮的照片。是的,这比您想要的要多得多。

2) 获取叠加层的比例。现在您知道在哪里裁剪了。

3) 让计算机去做艰苦的计算工作,它很擅长。

我的 - 不完整 - 代码:(它的一部分,它在照片上绘制一个矩形以裁剪它)

ArrayList<int []> userPoints = new ArrayList<>();

/**
 * Method to Crop the image
 *
 * @param width             Width of the output image, in mm.
 * @param height            Height of the output image, in mm.
 */
private void cropImage(int width, int height) {
    Paint paint = new Paint();
    paint.setAntiAlias(false);
    paint.setFilterBitmap(false);

    int output_width_start = 0;
    int output_width_end = (width * 5) / 2;
    int output_height_start = 0;
    int output_height_end = (height * 5) / 2;

    Matrix matrix = new Matrix();
    matrix.setPolyToPoly(
            // where to take it from
            new float[]{
                    userPoints.get(0)[0], userPoints.get(0)[1],
                    userPoints.get(1)[0], userPoints.get(1)[1],
                    userPoints.get(2)[0], userPoints.get(2)[1],
                    userPoints.get(3)[0], userPoints.get(3)[1]},
            0,
            // what it should be
            new float[]{
                    output_width_start, output_height_start,
                    output_width_end, output_width_start,
                    output_width_end, output_height_end,
                    output_height_start, output_height_end},
            0, 4);

    Uri image_uri = Uri.fromFile(file); // get where the temp is stored
    Bitmap bitmap = BitmapFactory.decodeFile(image_uri.getPath());
    canvasRectangle.drawBitmap(bitmap, matrix, paint);
}

private void scaleImage(ImageView image) {
    Matrix matrix = image.getImageMatrix();
    RectF drawableRect = new RectF(userPoints.get(0)[0], userPoints.get(0)[1], 400, 300);
    RectF viewRect = new RectF(0, 0, imageViewPhoto.getWidth(), imageViewPhoto.getHeight());
    matrix.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
    imageViewPhoto.setImageMatrix(matrix);
}

关于android - 拍摄覆盖范围内的照片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37360426/

有关android - 拍摄覆盖范围内的照片的更多相关文章

  1. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  2. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  3. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

  4. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  5. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  6. ruby - 覆盖相似的方法,更短的语法 - 2

    在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a

  7. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  8. Ruby 从大范围中获取第 n 个项目 - 2

    假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit

  9. ruby-on-rails - 从应用程序中自定义文件夹内的命名空间自动加载 - 2

    我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty

  10. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

随机推荐