【问题标题】:Getting a black screen after save photo - Android Camera保存照片后出现黑屏 - Android 相机
【发布时间】:2014-08-14 23:58:21
【问题描述】:

我正在开发一个适用于 Android 的应用程序,它可以捕获最大 fps 并保存到 SD 卡中。

问题是保存的照片是黑屏,不明白是什么原因。

谁能告诉我问题出在哪里?

我这样做的代码:

public class PhotoFragment extends Fragment {
private Camera cam;
private CameraPreview camPreview;
private boolean recording = false;
private ArrayList<byte[]> fotos;
private ArrayList<String> tempos;
private Thread thread;

public PhotoFragment() {

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_photofinish, container, false);
    cam = getCameraInstance();
    if(cam != null) {
        cam.setDisplayOrientation(90);

        // set Camera parameters
        Camera.Parameters cameraParameters = cam.getParameters();

        //set color efects to none
        cameraParameters.setColorEffect(Camera.Parameters.EFFECT_NONE);

        //set antibanding to none
        if (cameraParameters.getAntibanding() != null) {
            cameraParameters.setAntibanding(Camera.Parameters.ANTIBANDING_OFF);
        }

        // set white ballance
        if (cameraParameters.getWhiteBalance() != null) {
            cameraParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT);
        }

        //set flash
        if (cameraParameters.getFlashMode() != null) {
            cameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        }

        //set zoom
        if (cameraParameters.isZoomSupported()) {
            cameraParameters.setZoom(0);
        }

        //set focus mode
        cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);

        List<Size> sizes = cameraParameters.getSupportedPictureSizes();
        Camera.Size size = sizes.get(0);
        cameraParameters.setPictureSize(size.width, size.height);
        cam.setParameters(cameraParameters);
        fotos = new ArrayList<byte[]>();
        tempos = new ArrayList<String>();
        camPreview = new CameraPreview(this.getActivity(), cam);
        FrameLayout preview = (FrameLayout) rootView.findViewById(R.id.camera_preview);
        preview.addView(camPreview);
        TextView startRecording = (TextView) rootView.findViewById(R.id.start_record_button);
        startRecording.setOnClickListener( new View.OnClickListener() {
            public void onClick(View v) {
                if(!recording)
                {
                    recording = true;   
                    Size previewSize = cam.getParameters().getPreviewSize();
                    int dataBufferSize=(int)(previewSize.height*previewSize.width*(ImageFormat.getBitsPerPixel(cam.getParameters().getPreviewFormat())/8.0));
                    thread.start();
                    cam.addCallbackBuffer(new byte[dataBufferSize]);
                    cam.addCallbackBuffer(new byte[dataBufferSize]);
                    cam.addCallbackBuffer(new byte[dataBufferSize]);
                    cam.setPreviewCallbackWithBuffer(new PreviewCallback() {
                        public void onPreviewFrame(byte[] imageData, Camera arg1) {
                            try {                                   
                                fotos.add(imageData);
                                tempos.add(new SimpleDateFormat("HH_mm_ss_SSS", Locale.getDefault()).format(new Date()));
                            } catch(Exception e) {
                                System.out.println("ERRO: " + e);
                            }

                        }
                    });
                }
                else
                {
                    recording = false;
                    try {
                        thread.join();
                    } catch (Exception e) {

                    }
                }
            }               
        });
        thread = new Thread(new Runnable() {
              public void run() {
                  while(recording) {
                      if(fotos.size()>0 && tempos.size()>0)
                      {
                          File pictureFile = getOutputMediaFile(1, tempos.get(0));
                            if (pictureFile == null){
                                System.out.println("Error creating media file, check storage permissions: ");
                                return;
                            }

                            try {               
                                FileOutputStream fos = new FileOutputStream(pictureFile);
                                fos.write(fotos.get(0));
                                fos.close();
                                pictureFile = null;
                                cam.addCallbackBuffer(fotos.get(0));
                                fotos.remove(0);
                                tempos.remove(0);           
                            } catch (FileNotFoundException e) {
                                System.out.println("ERRO FILE NOT FOUND! : " + e);
                            } catch (IOException e) {
                                System.out.println("ERRO IOException!");
                            }
                      }
                  }

              }
        });
    }
    else
    {
        Toast.makeText(getActivity(), "Camera not available", Toast.LENGTH_LONG).show();
    }

    return rootView;
}

public static Camera getCameraInstance(){
    Camera c = null;
    try {
        c = Camera.open();
    }
    catch (Exception e){

    }
    return c;
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    cam.release();
}

private static File getOutputMediaFile(int type, String timeStamp){
    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "L_P");
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            System.out.println("L_P failed to create directory");
            return null;
        }
    }

    String timeStampDay = new SimpleDateFormat("ddMMyyyy", Locale.getDefault()).format(new Date());

    new File(mediaStorageDir.getPath() + File.separator + timeStampDay).mkdirs();

    File mediaFile;
    if (type == 1){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + timeStampDay + File.separator + "IMG_"+ timeStamp + ".jpg");
    } else if(type == 2) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

}

【问题讨论】:

    标签: android camera screen photo


    【解决方案1】:

    您声称该文件是 JPEG。但是,您没有做任何事情来将图像转换为 JPEG。默认情况下,预览帧不是 JPEG,而是NV21 格式。使用getSupportedPreviewFormats() 查看是否可以进行JPEG 预览,然后使用setPreviewFormat() 请求JPEG 预览。

    而且,正如我在您之前的问题中指出的那样, 是否有两个线程与ArrayList 一起工作。此外,不要让您的后台线程忙于等待不断寻找图像以显示在ArrayList 上。使用LinkedBlockingQueue 或其他线程安全的,并允许后台线程在等待图像时阻塞。

    【讨论】:

    • 感谢您的帮助!现在我正在将 NV21 转换为 JPEG,照片工作正常。今天我将arraylist改为LinkedBlockingQueue。现在我有另一个问题:我正在尝试获取预览并将其丢弃(只是为了看看我可以获得多少 fps),但我不能获得超过 16/17 fps。我已经下载了一个可以从我的智能手机获得 27/28 fps 的应用程序。知道为什么吗?再次感谢你! :)
    • @user2989493:您可能需要通过addCallbackBuffer() 添加更多缓冲区。如果出现预览帧,并且所有现有缓冲区都在使用中,则该帧将被丢弃。您不能发疯并添加 100 个缓冲区,因为您将耗尽内存。但是您可以尝试添加第四个,然后是第五个,等等,直到添加更多缓冲区无济于事。
    • 我已经添加了两个和三个缓冲区,并且 fps 的数量仍然相同。但是我只尝试了一个缓冲区,并且 fps 的数量与三个或更多缓冲区相同。这正常吗?
    • @user2989493:我无法真正回答,抱歉。听起来不对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 2018-06-24
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多