6

I'm trying to develop this simple app that takes pictures . Everything is fine. The only thing I have a fixed size oval shaped imageview in center of my preview.Capturing of image is working fine but the problem is I want to capture image and crop it automatically which lies inside the oval shaped imageview.I do not want whole image to be saved , i just want the portion of image which lies inside the shape. Now, I don't know how to proceed.After hours spent on Google for solutions I decided that I had to give up and come here.I am not getting that how can i get only that portion of image which lies inside the shape(That fixed oval shape image).

Here is my code :-

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

Second Approach :-

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>

So please, if someone knows anything, let me know.

Thanks

Nongthonbam Tonthoi
  • 12,667
  • 7
  • 37
  • 64
user2028
  • 163
  • 4
  • 15
  • 40
  • Any help on above question...i am stuck from last two days ...any suggestion will be life saving for me ...please guide me .. – user2028 May 23 '16 at 12:11
  • First of all, there are lots of irrelevant code to your problem, try to keep your question simple, it is hard to find where to look. Second, try googling `Bitmap`. What you need to do is first save the original image, then crop the `Bitmap` so it is rounded (or oval), then save it, then delete the original image, then show the rounded image or something along those lines. HTH – NecipAllef May 24 '16 at 04:01
  • Hey @NecipAllef , thanks for your reply and yes in second approach i am trying to do same thing i am first saving the image and then re-sizing the bitmap , but i think i am going wrong somewhere in startx , starty , end x , end y values ...so i am concentrating on that ... – user2028 May 24 '16 at 04:37
  • 1
    this may help http://stackoverflow.com/questions/11932805/cropping-circular-area-from-bitmap-in-android – NecipAllef May 24 '16 at 06:04
  • I think, the easier method is to capture the image first, then merge it with the oval-shaped imageview, compared to cropping method. Since you already have the oval-shaped imageview defined. – Nazar Merza May 26 '16 at 19:35

1 Answers1

1

Have been playing with this a bit. Here is how I solved it:

1) Just take the picture, with all it's glorious pix. Yes, this is way more then you want.

2) Get the proportions of your overlay. Now you know where to crop.

3) Let the computer do the hard calculating work, it is good at it.

My - not complete - code: (parts of it, it draws a rectangle over a photo to crop it)

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);
}
  • can you please explain it , i have mentioned my code above , i am really not able to do it even today , please provide me more detail , when and where to you scaleImage(ImageView image) and As from above code you can see that i am getting Bitmap bitmapPicture , Now if i am passing the height and width of picture inside your described function cropImage(int width, int height) , i am not getting what are user_points and where in canvasRectangle .. i am confused , please help me out here – user2028 Dec 16 '16 at 13:25