android - 从自定义前置摄像头拍摄的照片在存储时被裁剪

标签 android image android-camera surfaceview

我正在开发一个自定义相机应用程序,它也允许自拍。 当我点击捕捉图像时,图像在底部被裁剪并被保存。我在下面附上我的示例代码

public class CameraActivity extends Activity {




Camera camera;
CameraPreview preview;
            Activity act;
            Context ctx;
            TappableSurfaceView surfaceView;
            ImageView image;
            private View bottomPanel=null;
            public View imagePanel=null;
            int cameraId;
            private boolean cameraClicked=false;

        @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ctx = this; 
        act = this;
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.new_lay);
        try{            
            image=(ImageView)findViewById(R.id.image);
            surfaceView=(TappableSurfaceView)findViewById(R.id.surfaceView);
            surfaceView.addTapListener(onTap);
            preview = new CameraPreview (this, surfaceView);  
            preview.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
            ((FrameLayout) findViewById(R.id.layout)).addView(preview);
            preview.setKeepScreenOn(true);
        }catch(Exception e){                
            GlobalMembers.showAlert(ctx,e);
        }
    }


    @Override
    protected void onResume() {
        super.onResume();
        int numCams = Camera.getNumberOfCameras(); 
        if(numCams > 0){
            try{
                for (int camNo = 0; camNo < Camera.getNumberOfCameras(); camNo++) {
/* getting front camera */
                        CameraInfo camInfo = new CameraInfo();
                        Camera.getCameraInfo(camNo, camInfo);
                        if (camInfo.facing==

(Camera.CameraInfo.CAMERA_FACING_FRONT)) {
                            camera = Camera.open(camNo);
                            cameraId=camNo;
                            camera.startPreview();
                            preview.setCamera(camera);
                            break;
                    }
                }

            } catch (RuntimeException ex){
                Toast.makeText(ctx, getString(R.string.camera_not_found), Toast.LENGTH_LONG).show();
                GlobalMembers.showAlert(ctx,ex);
            }
        }
        else{
            Toast.makeText(ctx, getString(R.string.camera_not_found), Toast.LENGTH_LONG).show();
            finish();
        }
    }

    @Override
    protected void onPause() {
        if(camera != null) {
            camera.stopPreview();
            preview.setCamera(null);
            camera.release();
            camera = null; 
        }
        super.onPause();
    }


    private TappableSurfaceView.TapListener onTap=
            new TappableSurfaceView.TapListener() {
        public void onTap(MotionEvent event) {
            Log.d(TAG, "TappableSurfaceView - listener");   
            camera.takePicture(shutterCallback, rawCallback, jpegCallback);
                cameraClicked=true;

        }

    };



    private void resetCam() {
        camera.startPreview();
        cameraClicked=false;
        preview.setCamera(camera);
    }

    private void refreshGallery(File file) {
        Intent mediaScanIntent = new Intent( Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        mediaScanIntent.setData(Uri.fromFile(file));
        sendBroadcast(mediaScanIntent);
    }

    ShutterCallback shutterCallback = new ShutterCallback() {
        public void onShutter() {

            Log.d(TAG, "onShutter'd");
        }
    };

    PictureCallback rawCallback = new PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d(TAG, "onPictureTaken - raw");

        }
    };

    PictureCallback jpegCallback = new PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {

            Log.d(TAG, "onPictureTaken - jpeg");
            if(data!=null){
                data=rotateImageBeforeSaving(data);
            }           
            new SaveImageTask().execute(data);

            resetCam();

        }
    };


    public int calculateRotation(){

        int rotation = this.getWindowManager().getDefaultDisplay()
                .getRotation();
        Log.d(GlobalMembers.TAG,"Rotation before Saving : "+rotation);
        int toRotate=0;
        switch(rotation){
        case 0:{
            toRotate=270;
        }
        break;
        case 1:{
            toRotate=0;
        }
        break;
        case 2:{
            toRotate=180;
        }
        break;
        case 3:{
            toRotate=180;
        }
        break;
        }
        return toRotate;
    }

    public byte[] rotateImageBeforeSaving(byte[] data){ 
        try {         
            InputStream is = new ByteArrayInputStream(data);
            Bitmap bmp = BitmapFactory.decodeStream(is);     

            int w = bmp.getWidth();
            int h = bmp.getHeight();
            // Setting post rotate to 90
            Matrix mtx = new Matrix();
            mtx.postRotate(calculateRotation());
            Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            rotatedBMP.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray(); 
            return byteArray;

        } catch (Exception e) {
            e.printStackTrace();    
            Log.e(GlobalMembers.TAG,"Error Occured in CameraActivity",e);
            GlobalMembers.showAlert(ctx,e);
            return null;
        } finally {

        }
    }



    private class SaveImageTask extends AsyncTask<byte[], Void, String> {

        @Override
        protected void onPostExecute(String imageFilePath) {
            // TODO Auto-generated method stub
            super.onPostExecute(imageFilePath);
            cameraClicked=false;
            Intent intent = new Intent(ctx, ViewActivity.class);
            intent.putExtra("imageFilePath", imageFilePath);
            startActivity(intent);
        }

        @Override
        protected String doInBackground(byte[]... data) {
            FileOutputStream outStream = null;

            // Write to SD Card
            try {
                File sdCard = Environment.getExternalStorageDirectory();
                File dir = new File (sdCard.getAbsolutePath() + "/smartselfiepro");
                dir.mkdirs();

                String fileName = "image"+String.format("%d.jpg", System.currentTimeMillis());
                File outFile = new File(dir, fileName);
                String imageFilePath=dir+File.separator+fileName;
                Log.d(GlobalMembers.TAG,"ImageFilePath "+imageFilePath);
                outStream = new FileOutputStream(outFile);
                outStream.write(data[0]);
                outStream.flush();
                outStream.close();      
                Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length + " to " + outFile.getAbsolutePath());
                refreshGallery(outFile);
                return imageFilePath;


            } catch (FileNotFoundException e) {
                Log.e(GlobalMembers.TAG,"Error Occured in CameraActivity",e);
                GlobalMembers.showAlert(ctx,e);
            } catch (IOException e) {
                Log.e(GlobalMembers.TAG,"Error Occured in CameraActivity",e);
                GlobalMembers.showAlert(ctx,e);
            } finally {
            }
            return null;
        }

    }


    /**
     * Decode strem.
     * 
     * @param fil
     *            the fil
     * @param selectedImage
     *            the selected image
     * @param mContext
     *            the m context
     * @return the bitmap
     */


    public Bitmap rotateImage(Bitmap bmp, String imageUrl) {
        if (bmp != null) {
            ExifInterface ei;
            int orientation = 0;
            try {
                ei = new ExifInterface(imageUrl);
                orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                        ExifInterface.ORIENTATION_NORMAL);

            } catch (IOException e) {
                e.printStackTrace();
            }
            int bmpWidth = bmp.getWidth();
            int bmpHeight = bmp.getHeight();
            Matrix matrix = new Matrix();
            Log.d(GlobalMembers.TAG,"Orientation : "+orientation);
            int rotation = this.getWindowManager().getDefaultDisplay()
                    .getRotation();
            int toRotate=0;
            Log.d(GlobalMembers.TAG,"rotation : "+rotation);
            switch(rotation){
            case 0:{
                toRotate=0;
            }
            break;
            case 1:{
                toRotate=0;
            }
            break;
            case 2:{
                toRotate=180;
            }
            break;
            case 3:{
                toRotate=180;
            }
            break;
            }       
            matrix.postRotate(toRotate);
            Bitmap resizedBitmap = Bitmap.createBitmap(bmp, 0, 0, bmpWidth,
                    bmpHeight, matrix, true);
            return resizedBitmap;
        } else {
            return bmp;
        }
    }

}

CameraPreview 类

class CameraPreview extends ViewGroup implements SurfaceHolder.Callback {
private final String TAG = "Preview";

TappableSurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
Context mContext;

protected List<Camera.Size> mPreviewSizeList;
protected List<Camera.Size> mPictureSizeList;      
protected Camera.Size mPictureSize;
private int cameraId;



@SuppressWarnings("deprecation")
Preview(Context context, TappableSurfaceView sv) {
    super(context);
    mContext=context;
    mSurfaceView = sv;

    mHolder = mSurfaceView.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    getCameraId();
}


public void getCameraId(){
    try{
        for (int camNo = 0; camNo < Camera.getNumberOfCameras(); camNo++) {
            CameraInfo camInfo = new CameraInfo();
            Camera.getCameraInfo(camNo, camInfo);
            if (camInfo.facing==(Camera.CameraInfo.CAMERA_FACING_FRONT)) {                  
                cameraId=camNo;
                break;
            }
        }

    } catch (RuntimeException ex){

    }
}

public void setCamera(Camera camera) {
    mCamera = camera;
    if (mCamera != null) {
        mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
        requestLayout();

        // get Camera parameters
        Camera.Parameters params = mCamera.getParameters();

        List<String> focusModes = params.getSupportedFocusModes();
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
            // set the focus mode
            params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            // set Camera parameters
            mCamera.setParameters(params);
        }
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // We purposely disregard child measurements because act as a
    // wrapper to a SurfaceView that centers the camera preview instead
    // of stretching it.
    Log.d(this.getClass().getName(), "onMeasure Called");
    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
    }
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    Log.d(this.getClass().getName(), "onLayout Called");
    if (changed && getChildCount() > 0) {
        final View child = getChildAt(0);

        final int width = r - l;
        final int height = b - t;

        int previewWidth = width;
        int previewHeight = height;
        if (mPreviewSize != null) {
            previewWidth = mPreviewSize.width;
            previewHeight = mPreviewSize.height;
        }

        // Center the child SurfaceView within the parent.
        if (width * previewHeight > height * previewWidth) {
            final int scaledChildWidth = previewWidth * height / previewHeight;
            child.layout((width - scaledChildWidth) / 2, 0,
                    (width + scaledChildWidth) / 2, height);
        } else {
            final int scaledChildHeight = previewHeight * width / previewWidth;
            child.layout(0, (height - scaledChildHeight) / 2,
                    width, (height + scaledChildHeight) / 2);
        }
    }
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    try {
        if (mCamera != null) {
            // setWillNotDraw(false);
            mCamera.setPreviewDisplay(holder);
        }
    } catch (IOException exception) {
        Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
    }
}

@Override
protected void onDraw(Canvas canvas) {
    Log.d(this.getClass().getName(), "On Draw Called");
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        mCamera.stopPreview();
    }
}


private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    // Try to find an size match aspect ratio and size
    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if(mCamera != null) {
        Camera.Parameters parameters = mCamera.getParameters();
        //boolean portrait = isPortrait();
        //          if(portrait){
        //              mCamera.setDisplayOrientation(90);
        //          }
        setRotationParameter((Activity)mContext,parameters);
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);

        // configureCameraParameters(parameters, portrait); 
        requestLayout();

        mCamera.setParameters(parameters);
        //mCamera.setDisplayOrientation(degrees)
        mCamera.startPreview();
    }
}


public boolean isPortrait() {
    return (((Activity)mContext).getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
}

public  void setRotationParameter(Activity activity, Camera.Parameters param) {
    android.hardware.Camera.CameraInfo info =
            new android.hardware.Camera.CameraInfo();
    android.hardware.Camera.getCameraInfo(cameraId, info);

    int rotation = activity.getWindowManager().getDefaultDisplay()
            .getRotation();
    int toRotate=0;
    switch(rotation){
    case 0:{
        toRotate=90;
    }
    break;
    case 1:{
        toRotate=0;
    }
    break;
    case 2:{
        toRotate=180;
    }
    break;
    case 3:{
        toRotate=180;
    }
    break;
    }


    Log.d("Preview","Rotation : "+rotation);
    rotation = (rotation + 45) / 90 * 90;
    // int toRotate = (info.orientation + rotation) % 360;
    mCamera.setDisplayOrientation(toRotate);
}

}

我尝试了所有的论坛问题,但无法解决问题。请帮忙。 此外,在某些手机中,相机预览显示良好且聚焦,但在拍摄时显示模糊的图像。我不确定为什么在不同的相机中会出现不同的行为。

最佳答案

您好,经过数小时的搜索,我发现图像被裁剪背后的问题。 我没有设置图片大小参数。

不同手机的相机行为仍未解决

关于android - 从自定义前置摄像头拍摄的照片在存储时被裁剪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32707563/

相关文章:

android - 在 onPictureTaken 中处理原始图像数据

Android相机预览回调和mediarecorder录制视频

android - 无法解析目标 'Google Inc.:Google APIs:15'

java - 在 greenDAO 中使用 WHERE OR 选择多个元素的简单解决方案?

javascript - Canvas 上的 JavaScript 错误(HTML5)- 无法弄清楚

java - 如何在图片上写文字

c++ - 图像旋转,伪造图像直方图

java - 创建新项目时android studio出错

android - 如何在形状为椭圆形按钮的按钮内添加图标

android - 某些图片尺寸导致 Camera.takePicture() 失败