Как сохранить изображение с камеры? - PullRequest
4 голосов
/ 21 декабря 2011

Вот мой код:

package com.commonsware.android.skeleton;

import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.*;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

// ----------------------------------------------------------------------

public class SimpleBulbActivity extends Activity {
    private Preview mPreview;
    private static final String TAG = "CameraDemo";
    FrameLayout preview;
    Camera mCamera;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Hide the window title.
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
    }

    protected void onResume() {
        super.onResume();
        //Setup the FrameLayout with the Camera Preview Screen
        mPreview = new Preview(this);
        preview = (FrameLayout)findViewById(R.id.preview); 
        preview.addView(mPreview);
    }

    public void snap() {
        mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
    }
    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) {
          FileOutputStream outStream = null;
            try {
                // write to local sandbox file system
                // outStream =
                // CameraDemo.this.openFileOutput(String.format("%d.jpg",
                // System.currentTimeMillis()), 0);
                // Or write to sdcard
                outStream = new FileOutputStream(String.format(
                        "/sdcard/%d.jpg", System.currentTimeMillis()));
                outStream.write(data);
                outStream.close();
                Log.d(TAG, "onPictureTaken - wrote bytes: " + data.length);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
            Log.d(TAG, "onPictureTaken - jpeg");
      }
    };

 // ----------------------------------------------------------------------

    class Preview extends SurfaceView implements SurfaceHolder.Callback {
        SurfaceHolder mHolder;

        Preview(Context context) {
            super(context);

            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            mHolder = getHolder();
            mHolder.addCallback(this);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }

        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, acquire the camera and tell it where
            // to draw.
            mCamera = Camera.open();
            try {
               mCamera.setPreviewDisplay(holder);
               mCamera.setPreviewCallback(new PreviewCallback() {

                public void onPreviewFrame(byte[] data, Camera arg1) {
                    FileOutputStream outStream = null;
                    try {
                        outStream = new FileOutputStream(Environment.getExternalStorageDirectory().toString());
                        outStream.write(data);
                        outStream.close();
                        Log.d(TAG, "onPreviewFrame - wrote bytes: "
                                + data.length);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                    }
                    Preview.this.invalidate();
                }
            });
        } catch (IOException e) {
                mCamera.release();
                mCamera = null;
                e.printStackTrace();
            }
        }

        public void surfaceDestroyed(SurfaceHolder holder) {
            // Surface will be destroyed when we return, so stop the preview.
            // Because the CameraDevice object is not a shared resource, it's very
            // important to release it when the activity is paused.
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }


        private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.05;
            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) {
            // Now that the size is known, set up the camera parameters and begin
            // the preview.
            Camera.Parameters parameters = mCamera.getParameters();

            List<Size> sizes = parameters.getSupportedPreviewSizes();
            Size optimalSize = getOptimalPreviewSize(sizes, w, h);

            Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();

            if(display.getRotation() == Surface.ROTATION_0)
            {
                parameters.setPreviewSize(optimalSize.height, optimalSize.width);                           
                mCamera.setDisplayOrientation(90);
            }

            if(display.getRotation() == Surface.ROTATION_90)
            {
                parameters.setPreviewSize(optimalSize.width, optimalSize.height);                         
            }

            if(display.getRotation() == Surface.ROTATION_180)
            {
                parameters.setPreviewSize(optimalSize.width, optimalSize.height);               
            }

            if(display.getRotation() == Surface.ROTATION_270)
            {
                parameters.setPreviewSize(optimalSize.width, optimalSize.height);
                mCamera.setDisplayOrientation(0);
            }

            mCamera.setParameters(parameters);
            mCamera.startPreview();
        }

    }

}

Хорошо, я немного изменил свой код.

У меня есть это в моем основном макете:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent" android:id="@+id/layout">
    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content" android:text="Camera Demo"
        android:textSize="24sp" />

    <FrameLayout android:layout_weight="1" android:layout_width="fill_parent"
        android:layout_height="fill_parent">

    <FrameLayout android:id="@+id/preview"
        android:layout_weight="1" android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    </FrameLayout>

    <ImageView android:src="@drawable/litbulb"
                   android:layout_width="match_parent"
                   android:layout_height="112dip" />

    </FrameLayout>

    <Button android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:id="@+id/buttonClick"
        android:text="Snap!" android:layout_gravity="center"></Button>

</LinearLayout>

КогдаЯ нажимаю кнопку «Snap!»или кнопку buttonClick, она должна захватывать и сохранять изображение, но это не так.Может кто-нибудь помочь мне изменить этот код, чтобы он сделал?

Кроме того, он падает каждый раз, когда я покидаю приложение.Вот соответствующие данные logcat:

12-21 13:30:47.820: ERROR/AndroidRuntime(3906): FATAL EXCEPTION: main
12-21 13:30:47.820: ERROR/AndroidRuntime(3906): java.lang.RuntimeException: Method called after release()
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at android.hardware.Camera.setHasPreviewCallback(Native Method)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at android.hardware.Camera.access$600(Camera.java:114)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at android.hardware.Camera$EventHandler.handleMessage(Camera.java:519)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at android.os.Looper.loop(Looper.java:123)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at android.app.ActivityThread.main(ActivityThread.java:4627)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at java.lang.reflect.Method.invokeNative(Native Method)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at java.lang.reflect.Method.invoke(Method.java:521)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-21 13:30:47.820: ERROR/AndroidRuntime(3906):     at dalvik.system.NativeStart.main(Native Method)

Ответы [ 3 ]

2 голосов
/ 21 декабря 2011
pre.camera.takePicture(shutterCallback, rawCallback,
                            jpegCallback);
            PictureCallback rawCallback = new PictureCallback() {
            public void onPictureTaken(byte[] data, Camera camera) {
                System.out.println( "onPictureTaken - raw");
            }
        };

        /** Handles data for jpeg picture */
        PictureCallback jpegCallback = new PictureCallback() {
            public void onPictureTaken(byte[] data, Camera camera) {


                 BitmapFactory.Options options=new BitmapFactory.Options();
                    options.inSampleSize = 5;

                m=BitmapFactory.decodeByteArray(data,0,data.length,options);
2 голосов
/ 21 декабря 2011

Просто взглянув на ваш код, вам нужно передать обратные вызовы в метод takePicture mPreview.getCamera (). TakePicture (shutterCallback, rawCallback, null, jpegCallback);Посмотрите здесь для более подробной информации.

Ваша трассировка стека, кажется, предполагает, что она не знает, что делать после того, как она сделала фотографию.

Также яподозреваю, что вы можете указывать на неправильный корневой каталог для записи ... попробуйте это: Environment.getExternalStorageDirectory (). toString ()

1 голос
/ 13 июля 2013

Вот оно:

public class PictureSaver {

private static final String TAG = "PictureSaver";

public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** null if unable to save the file */
public static File savePicture(byte[] data, String folder_name) throws SaveFileException {
    File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE, folder_name);
    if (pictureFile == null){
        Log.d(TAG, "Error creating media file, check storage permissions!");
        throw new SaveFileException(TAG, "Error creating media file, check storage permissions!");
    }

    try {
        FileOutputStream fos = new FileOutputStream(pictureFile);
        fos.write(data);
        fos.close();
    } catch (FileNotFoundException e) {
        Log.d(TAG, "File not found: " + e.getMessage());
        throw new SaveFileException(TAG, "File not found: " + e.getMessage());
    } catch (IOException e) {
        Log.d(TAG, "Error accessing file: " + e.getMessage());
        throw new SaveFileException(TAG, "Error accessing file: " + e.getMessage());
    }
    return pictureFile;
}

/** Create a File for saving an image or video 
 *  null if unable to create the file */
private static File getOutputMediaFile(int type, String folder_name) throws SaveFileException {
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), folder_name);
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d(TAG, "Unable to create directory!");
            throw new SaveFileException(TAG, "Unable to create directory!");
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "VID_"+ timeStamp + ".mp4");
    } else {
        throw new SaveFileException(TAG, "Unkknown media type!");
    }
    Log.d(TAG,mediaStorageDir.getPath() + File.separator +
            "IMG_"+ timeStamp + ".jpg");
    return mediaFile;
}}

Не забудьте также сделать что-то вроде:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,
                         Uri.parse("file://"+ Environment.getExternalStorageDirectory())));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                         Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...